libcoap 4.3.5rc1
Loading...
Searching...
No Matches
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(coap_lock_t *lock, const char *file, int line) {
22 assert(coap_thread_pid == lock->pid);
23 if (lock->in_callback) {
24 assert(lock->lock_count > 0);
25 lock->lock_count--;
26 } else {
27 lock->pid = 0;
28 lock->unlock_file = file;
29 lock->unlock_line = line;
30 coap_mutex_unlock(&lock->mutex);
31 }
32}
33
34int
35coap_lock_lock_func(coap_lock_t *lock, int force, const char *file, int line) {
36 if (!force && lock->being_freed) {
37 /* context is going away */
38 return 0;
39 }
40 if (coap_mutex_trylock(&lock->mutex)) {
41 if (coap_thread_pid == lock->pid) {
42 /* This thread locked the mutex */
43 if (lock->in_callback) {
44 /* This is called from within an app callback */
45 lock->lock_count++;
46 assert(lock->in_callback == lock->lock_count);
47 return 1;
48 } else {
49 coap_log_alert("Thread Deadlock: Last %s: %u, this %s: %u\n",
50 lock->lock_file, lock->lock_line, file, line);
51 assert(0);
52 }
53 }
54 /* Wait for the other thread to unlock */
55 coap_mutex_lock(&lock->mutex);
56 }
57 /* Just got the lock, so should not be in a locked callback */
58 assert(!lock->in_callback);
59 lock->pid = coap_thread_pid;
60 lock->lock_file = file;
61 lock->lock_line = line;
62#ifndef __COVERITY__
63 if (!force && lock->being_freed) {
64 /*
65 * lock->being_freed set when previous thread had lock locked.
66 * Have to unlock to let the next context locking user clean up.
67 */
68 coap_lock_unlock_func(lock, file, line);
69 return 0;
70 }
71#endif /* __COVERITY__ */
72 return 1;
73}
74
75#else /* ! COAP_THREAD_RECURSIVE_CHECK */
76
77void
78coap_lock_unlock_func(coap_lock_t *lock) {
79 assert(coap_thread_pid == lock->pid);
80 if (lock->in_callback) {
81 assert(lock->lock_count > 0);
82 lock->lock_count--;
83 } else {
84 lock->pid = 0;
85 coap_mutex_unlock(&lock->mutex);
86 }
87}
88
89int
90coap_lock_lock_func(coap_lock_t *lock, int force) {
91 if (!force && lock->being_freed) {
92 /* context is going away */
93 return 0;
94 }
95 /*
96 * Some OS do not have support for coap_mutex_trylock() so
97 * cannot use that here and have to rely on lock-pid being stable
98 */
99 if (lock->in_callback && coap_thread_pid == lock->pid) {
100 lock->lock_count++;
101 assert(lock->in_callback == lock->lock_count);
102 return 1;
103 }
104 coap_mutex_lock(&lock->mutex);
105 /* Just got the lock, so should not be in a locked callback */
106 assert(!lock->in_callback);
107 lock->pid = coap_thread_pid;
108#ifndef __COVERITY__
109 if (!force && lock->being_freed) {
110 /*
111 * lock->being_freed set when previous thread had lock locked.
112 * Have to unlock to let the next context locking user clean up.
113 */
114 coap_lock_unlock_func(lock);
115 return 0;
116 }
117#endif /* __COVERITY__ */
118 return 1;
119}
120#endif /* ! COAP_THREAD_RECURSIVE_CHECK */
121
122#else /* ! COAP_THREAD_SAFE */
123
124#ifdef __clang__
125/* Make compilers happy that do not like empty modules. As this function is
126 * never used, we ignore -Wunused-function at the end of compiling this file
127 */
128#pragma GCC diagnostic ignored "-Wunused-function"
129#endif
130static inline void
131dummy(void) {
132}
133
134#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)
static void dummy(void)
coap_mutex_t coap_lock_t
#define coap_log_alert(...)
Definition coap_debug.h:84