2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifdef DEBUG_OBJECT_POSSIBLE
23 #ifdef DEBUG_OBJECT_POSSIBLE
24 static bool mutex_debug = false;
25 static bool thread_debug = false;
27 static const bool mutex_debug = false;
28 static const bool thread_debug = false;
31 #if defined(DEBUG_OBJECT_POSSIBLE) || !defined(THREAD_NONE)
33 void mutex_init_position(mutex_t *m argument_position)
35 if (unlikely(mutex_debug))
36 obj_registry_insert(OBJ_TYPE_MUTEX, ptr_to_num((void *)m), position_arg);
40 void mutex_done_position(mutex_t *m argument_position)
42 if (unlikely(mutex_debug))
43 obj_registry_remove(OBJ_TYPE_MUTEX, ptr_to_num((void *)m), position_arg);
47 void attr_fastcall mutex_lock_position(mutex_t *m argument_position)
49 if (unlikely(mutex_debug))
50 obj_registry_verify(OBJ_TYPE_MUTEX, ptr_to_num((void *)m), position_arg);
54 bool attr_fastcall mutex_trylock_position(mutex_t *m argument_position)
56 if (unlikely(mutex_debug))
57 obj_registry_verify(OBJ_TYPE_MUTEX, ptr_to_num((void *)m), position_arg);
63 void attr_fastcall mutex_unlock_position(mutex_t *m argument_position)
65 if (unlikely(mutex_debug))
66 obj_registry_verify(OBJ_TYPE_MUTEX, ptr_to_num((void *)m), position_arg);
73 #if defined(DEBUG_OBJECT_POSSIBLE) || !defined(THREAD_NONE)
75 void rwmutex_init_position(rwmutex_t *m argument_position)
77 if (unlikely(mutex_debug))
78 obj_registry_insert(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
82 void rwmutex_done_position(rwmutex_t *m argument_position)
84 if (unlikely(mutex_debug))
85 obj_registry_remove(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
89 void attr_fastcall rwmutex_lock_read_position(rwmutex_t *m argument_position)
91 if (unlikely(mutex_debug))
92 obj_registry_verify(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
93 do_rwmutex_lock_read(m);
96 void attr_fastcall rwmutex_unlock_read_position(rwmutex_t *m argument_position)
98 if (unlikely(mutex_debug))
99 obj_registry_verify(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
100 do_rwmutex_unlock_read(m);
103 void attr_fastcall rwmutex_lock_write_position(rwmutex_t *m argument_position)
105 if (unlikely(mutex_debug))
106 obj_registry_verify(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
107 do_rwmutex_lock_write(m);
110 void attr_fastcall rwmutex_unlock_write_position(rwmutex_t *m argument_position)
112 if (unlikely(mutex_debug))
113 obj_registry_verify(OBJ_TYPE_RWMUTEX, ptr_to_num((void *)m), position_arg);
114 do_rwmutex_unlock_write(m);
120 #if defined(DEBUG_OBJECT_POSSIBLE) || !defined(THREAD_NONE)
122 void cond_init_position(cond_t *c argument_position)
124 if (unlikely(mutex_debug))
125 obj_registry_insert(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
129 void cond_done_position(cond_t *c argument_position)
131 if (unlikely(mutex_debug))
132 obj_registry_remove(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
136 void attr_fastcall cond_lock_position(cond_t *c argument_position)
138 if (unlikely(mutex_debug))
139 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
143 void attr_fastcall cond_unlock_position(cond_t *c argument_position)
145 if (unlikely(mutex_debug))
146 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
150 void attr_fastcall cond_unlock_signal_position(cond_t *c argument_position)
152 if (unlikely(mutex_debug))
153 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
154 do_cond_unlock_signal(c);
157 void attr_fastcall cond_unlock_broadcast_position(cond_t *c argument_position)
159 if (unlikely(mutex_debug))
160 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
161 do_cond_unlock_broadcast(c);
164 void attr_fastcall cond_wait_position(cond_t *c argument_position)
166 if (unlikely(mutex_debug))
167 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
171 bool attr_fastcall cond_wait_us_position(cond_t *c, uint32_t us argument_position)
173 if (unlikely(mutex_debug))
174 obj_registry_verify(OBJ_TYPE_COND, ptr_to_num(c), position_arg);
175 do_cond_wait_us(c, us);
184 bool thread_spawn_position(thread_t *t, thread_function_t *function, void *arg, thread_priority_t attr_unused priority, ajla_error_t *err argument_position)
186 do_thread_spawn(t, function, arg, priority, err);
187 if (unlikely(thread_debug) && sizeof(thread_t) <= sizeof(obj_id)) {
189 memcpy(&id, t, sizeof(thread_t));
190 obj_registry_insert(OBJ_TYPE_THREAD, id, position_arg);
195 void thread_join_position(thread_t *t argument_position)
197 if (unlikely(thread_debug) && sizeof(thread_t) <= sizeof(obj_id)) {
199 memcpy(&id, t, sizeof(thread_t));
200 obj_registry_remove(OBJ_TYPE_THREAD, id, position_arg);
207 #if defined(HAVE___THREAD)
208 #define do_tls_init(m) do { } while (0)
209 #define do_tls_done(m) do { } while (0)
212 void tls_init__position(tls_t_ attr_unused *m argument_position)
214 if (unlikely(mutex_debug))
215 obj_registry_insert(OBJ_TYPE_TLS, ptr_to_num(m), position_arg);
219 void tls_done__position(tls_t_ attr_unused *m argument_position)
221 if (unlikely(mutex_debug))
222 obj_registry_remove(OBJ_TYPE_TLS, ptr_to_num(m), position_arg);
226 #if !defined(HAVE___THREAD)
228 uintptr_t attr_fastcall tls_get__position(const tls_t_ *m argument_position)
231 if (unlikely(mutex_debug))
232 obj_registry_verify(OBJ_TYPE_TLS, ptr_to_num(m), position_arg);
237 void attr_fastcall tls_set__position(const tls_t_ *m, uintptr_t val argument_position)
239 if (unlikely(mutex_debug))
240 obj_registry_verify(OBJ_TYPE_TLS, ptr_to_num(m), position_arg);
244 uintptr_t attr_fastcall tls_get__nocheck(const tls_t_ *m)
246 #ifdef DEBUG_TRACK_FILE_LINE
247 const char attr_unused *position_arg = "tls_get__nocheck";
254 void attr_fastcall tls_set__nocheck(const tls_t_ *m, uintptr_t val)
256 #ifdef DEBUG_TRACK_FILE_LINE
257 const char attr_unused *position_arg = "tls_set__nocheck";
267 static tls_decl(tls_destructor_t *, tls_destructors);
269 void tls_destructor_position(tls_destructor_t *destr, tls_destructor_fn *fn argument_position)
272 destr->previous = tls_get(tls_destructor_t *, tls_destructors);
273 tls_set(tls_destructor_t *, tls_destructors, destr);
276 void tls_destructor_call(void)
278 tls_destructor_t *destr;
279 while ((destr = tls_get(tls_destructor_t *, tls_destructors))) {
280 tls_set(tls_destructor_t *, tls_destructors, destr->previous);
286 static tls_decl(int, thread_id);
288 void thread_set_id(int id)
290 tls_set(int, thread_id, id);
293 int thread_get_id(void)
295 return tls_get(int, thread_id);
299 static void thread_common_init(void)
301 tls_init(tls_destructor_t *, tls_destructors);
303 tls_init(int, thread_id);
307 static void thread_common_done(void)
309 tls_destructor_call();
310 tls_done(tls_destructor_t *, tls_destructors);
312 tls_done(int, thread_id);
319 bool thread_enable_debugging_option(const char *option, size_t l)
321 #ifndef DEBUG_OBJECT_POSSIBLE
322 bool attr_unused mutex_debug = false;
323 bool attr_unused thread_debug = false;
326 mutex_debug = thread_debug = true;
327 else if (l == 5 && !strncmp(option, "mutex", 5))
329 else if (l == 16 && !strncmp(option, "mutex-errorcheck", 16))
331 else if (l == 6 && !strncmp(option, "thread", 6))
335 #if defined(OS_OS2) || defined(OS_WIN32)