libcoap 4.3.5-develop-19cef11
coap_threadsafe.c
Go to the documentation of this file.
1/* coap_threadsafe.c -- Thread safe function locking wrappers
2 *
3 * Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
17
18#if COAP_THREAD_SAFE
19#if COAP_THREAD_RECURSIVE_CHECK
20void
21coap_lock_unlock_func(const char *file, int line) {
22 assert(coap_thread_pid == global_lock.pid);
23 if (global_lock.in_callback) {
24 assert(global_lock.lock_count > 0);
25 global_lock.lock_count--;
26 } else {
27 global_lock.pid = 0;
28 global_lock.unlock_file = file;
29 global_lock.unlock_line = line;
30 coap_mutex_unlock(&global_lock.mutex);
31 }
32}
33
34int
35coap_lock_lock_func(const char *file, int line) {
36 if (!coap_started) {
37 /* libcoap not initialized with coap_startup() */
38 return 0;
39 }
40 if (coap_mutex_trylock(&global_lock.mutex)) {
41 if (coap_thread_pid == global_lock.pid) {
42 /* This thread locked the mutex */
43 if (global_lock.in_callback) {
44 /* This is called from within an app callback */
45 global_lock.lock_count++;
46 assert(global_lock.in_callback == global_lock.lock_count);
47 return 1;
48 } else {
49 coap_log_alert("Thread Deadlock: Last %s: %u, this %s: %u\n",
50 global_lock.lock_file, global_lock.lock_line, file, line);
51 assert(0);
52 }
53 }
54 /* Wait for the other thread to unlock */
55 coap_mutex_lock(&global_lock.mutex);
56 }
57 /* Just got the lock, so should not be in a locked callback */
58 assert(!global_lock.in_callback);
59 global_lock.pid = coap_thread_pid;
60 global_lock.lock_file = file;
61 global_lock.lock_line = line;
62 return 1;
63}
64
65#else /* ! COAP_THREAD_RECURSIVE_CHECK */
66
67void
68coap_lock_unlock_func(void) {
69 assert(coap_thread_pid == global_lock.pid);
70 if (global_lock.in_callback) {
71 assert(global_lock.lock_count > 0);
72 global_lock.lock_count--;
73 } else {
74 global_lock.pid = 0;
75 coap_mutex_unlock(&global_lock.mutex);
76 }
77}
78
79int
80coap_lock_lock_func(void) {
81 if (!coap_started) {
82 /* libcoap not initialized with coap_startup() */
83 return 0;
84 }
85 /*
86 * Some OS do not have support for coap_mutex_trylock() so
87 * cannot use that here and have to rely on lock-pid being stable
88 */
89 if (global_lock.in_callback && coap_thread_pid == global_lock.pid) {
90 global_lock.lock_count++;
91 assert(global_lock.in_callback == global_lock.lock_count);
92 return 1;
93 }
94 coap_mutex_lock(&global_lock.mutex);
95 /* Just got the lock, so should not be in a locked callback */
96 assert(!global_lock.in_callback);
97 global_lock.pid = coap_thread_pid;
98 return 1;
99}
100#endif /* ! COAP_THREAD_RECURSIVE_CHECK */
101
102#else /* ! COAP_THREAD_SAFE */
103
104#ifdef __clang__
105/* Make compilers happy that do not like empty modules. As this function is
106 * never used, we ignore -Wunused-function at the end of compiling this file
107 */
108#pragma GCC diagnostic ignored "-Wunused-function"
109#endif
110static inline void
111dummy(void) {
112}
113
114#endif /* ! COAP_THREAD_SAFE */
Library specific build wrapper for coap_internal.h.
#define coap_thread_pid
#define coap_mutex_unlock(a)
#define coap_mutex_trylock(a)
#define coap_mutex_lock(a)
int coap_started
Definition: coap_net.c:4606
static void dummy(void)
#define coap_log_alert(...)
Definition: coap_debug.h:84