1 /* Locking in multithreaded situations.
2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
20 /* This file contains locking primitives for use with a given thread library.
21 It does not contain primitives for creating threads or for other
22 synchronization primitives.
24 Normal (non-recursive) locks:
26 Declaration: gl_lock_define(extern, name)
27 Initializer: gl_lock_define_initialized(, name)
28 Initialization: gl_lock_init (name);
29 Taking the lock: gl_lock_lock (name);
30 Releasing the lock: gl_lock_unlock (name);
31 De-initialization: gl_lock_destroy (name);
32 Equivalent functions with control of error handling:
33 Initialization: err = glthread_lock_init (&name);
34 Taking the lock: err = glthread_lock_lock (&name);
35 Releasing the lock: err = glthread_lock_unlock (&name);
36 De-initialization: err = glthread_lock_destroy (&name);
38 Read-Write (non-recursive) locks:
40 Declaration: gl_rwlock_define(extern, name)
41 Initializer: gl_rwlock_define_initialized(, name)
42 Initialization: gl_rwlock_init (name);
43 Taking the lock: gl_rwlock_rdlock (name);
44 gl_rwlock_wrlock (name);
45 Releasing the lock: gl_rwlock_unlock (name);
46 De-initialization: gl_rwlock_destroy (name);
47 Equivalent functions with control of error handling:
48 Initialization: err = glthread_rwlock_init (&name);
49 Taking the lock: err = glthread_rwlock_rdlock (&name);
50 err = glthread_rwlock_wrlock (&name);
51 Releasing the lock: err = glthread_rwlock_unlock (&name);
52 De-initialization: err = glthread_rwlock_destroy (&name);
55 Type: gl_recursive_lock_t
56 Declaration: gl_recursive_lock_define(extern, name)
57 Initializer: gl_recursive_lock_define_initialized(, name)
58 Initialization: gl_recursive_lock_init (name);
59 Taking the lock: gl_recursive_lock_lock (name);
60 Releasing the lock: gl_recursive_lock_unlock (name);
61 De-initialization: gl_recursive_lock_destroy (name);
62 Equivalent functions with control of error handling:
63 Initialization: err = glthread_recursive_lock_init (&name);
64 Taking the lock: err = glthread_recursive_lock_lock (&name);
65 Releasing the lock: err = glthread_recursive_lock_unlock (&name);
66 De-initialization: err = glthread_recursive_lock_destroy (&name);
70 Initializer: gl_once_define(extern, name)
71 Execution: gl_once (name, initfunction);
72 Equivalent functions with control of error handling:
73 Execution: err = glthread_once (&name, initfunction);
83 #if !defined c11_threads_in_use
84 # if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
85 # define c11_threads_in_use() 1
86 # elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
88 # pragma weak thrd_exit
89 # define c11_threads_in_use() (thrd_exit != NULL)
91 # define c11_threads_in_use() 0
95 /* ========================================================================= */
97 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
99 /* Use the ISO C threads library. */
101 # include <threads.h>
107 /* -------------------------- gl_lock_t datatype -------------------------- */
111 int volatile init_needed;
113 void (*init_func) (void);
117 # define gl_lock_define(STORAGECLASS, NAME) \
118 STORAGECLASS gl_lock_t NAME;
119 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
120 static void _atomic_init_##NAME (void); \
121 STORAGECLASS gl_lock_t NAME = \
122 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
123 static void _atomic_init_##NAME (void) \
125 if (glthread_lock_init (&(NAME))) \
128 extern int glthread_lock_init (gl_lock_t *lock);
129 extern int glthread_lock_lock (gl_lock_t *lock);
130 extern int glthread_lock_unlock (gl_lock_t *lock);
131 extern int glthread_lock_destroy (gl_lock_t *lock);
133 /* ------------------------- gl_rwlock_t datatype ------------------------- */
137 int volatile init_needed;
139 void (*init_func) (void);
140 mtx_t lock; /* protects the remaining fields */
141 cnd_t waiting_readers; /* waiting readers */
142 cnd_t waiting_writers; /* waiting writers */
143 unsigned int waiting_writers_count; /* number of waiting writers */
144 int runcount; /* number of readers running, or -1 when a writer runs */
147 # define gl_rwlock_define(STORAGECLASS, NAME) \
148 STORAGECLASS gl_rwlock_t NAME;
149 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
150 static void _atomic_init_##NAME (void); \
151 STORAGECLASS gl_rwlock_t NAME = \
152 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
153 static void _atomic_init_##NAME (void) \
155 if (glthread_rwlock_init (&(NAME))) \
158 extern int glthread_rwlock_init (gl_rwlock_t *lock);
159 extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
160 extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
161 extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
162 extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
164 /* --------------------- gl_recursive_lock_t datatype --------------------- */
168 int volatile init_needed;
170 void (*init_func) (void);
174 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
175 STORAGECLASS gl_recursive_lock_t NAME;
176 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
177 static void _atomic_init_##NAME (void); \
178 STORAGECLASS gl_recursive_lock_t NAME = \
179 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
180 static void _atomic_init_##NAME (void) \
182 if (glthread_recursive_lock_init (&(NAME))) \
185 extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
186 extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
187 extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
188 extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
190 /* -------------------------- gl_once_t datatype -------------------------- */
192 typedef once_flag gl_once_t;
193 # define gl_once_define(STORAGECLASS, NAME) \
194 STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
195 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
196 (call_once (ONCE_CONTROL, INITFUNCTION), 0)
204 /* ========================================================================= */
206 #if USE_POSIX_THREADS
208 /* Use the POSIX threads library. */
210 # include <pthread.h>
216 # if PTHREAD_IN_USE_DETECTION_HARD
218 /* The pthread_in_use() detection needs to be done at runtime. */
219 # define pthread_in_use() \
221 extern int glthread_in_use (void);
225 # if USE_POSIX_THREADS_WEAK
227 /* Use weak references to the POSIX threads library. */
229 /* Weak references avoid dragging in external libraries if the other parts
230 of the program don't use them. Here we use them, because we don't want
231 every program that uses libintl to depend on libpthread. This assumes
232 that libpthread would not be loaded after libintl; i.e. if libintl is
233 loaded first, by an executable that does not depend on libpthread, and
234 then a module is dynamically loaded that depends on libpthread, libintl
235 will not be multithread-safe. */
237 /* The way to test at runtime whether libpthread is present is to test
238 whether a function pointer's value, such as &pthread_mutex_init, is
239 non-NULL. However, some versions of GCC have a bug through which, in
240 PIC mode, &foo != NULL always evaluates to true if there is a direct
241 call to foo(...) in the same function. To avoid this, we test the
242 address of a function in libpthread that we don't use. */
244 # pragma weak pthread_mutex_init
245 # pragma weak pthread_mutex_lock
246 # pragma weak pthread_mutex_unlock
247 # pragma weak pthread_mutex_destroy
248 # pragma weak pthread_rwlock_init
249 # pragma weak pthread_rwlock_rdlock
250 # pragma weak pthread_rwlock_wrlock
251 # pragma weak pthread_rwlock_unlock
252 # pragma weak pthread_rwlock_destroy
253 # pragma weak pthread_once
254 # pragma weak pthread_cond_init
255 # pragma weak pthread_cond_wait
256 # pragma weak pthread_cond_signal
257 # pragma weak pthread_cond_broadcast
258 # pragma weak pthread_cond_destroy
259 # pragma weak pthread_mutexattr_init
260 # pragma weak pthread_mutexattr_settype
261 # pragma weak pthread_mutexattr_destroy
262 # pragma weak pthread_rwlockattr_init
263 # if __GNU_LIBRARY__ > 1
264 # pragma weak pthread_rwlockattr_setkind_np
266 # pragma weak pthread_rwlockattr_destroy
267 # ifndef pthread_self
268 # pragma weak pthread_self
271 # if !PTHREAD_IN_USE_DETECTION_HARD
272 /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
273 can be used to determine whether libpthread is in use. These are:
274 pthread_mutexattr_gettype
275 pthread_rwlockattr_destroy
276 pthread_rwlockattr_init
278 # pragma weak pthread_mutexattr_gettype
279 # define pthread_in_use() \
280 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
285 # if !PTHREAD_IN_USE_DETECTION_HARD
286 # define pthread_in_use() 1
291 /* -------------------------- gl_lock_t datatype -------------------------- */
293 typedef pthread_mutex_t gl_lock_t;
294 # define gl_lock_define(STORAGECLASS, NAME) \
295 STORAGECLASS pthread_mutex_t NAME;
296 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
297 STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
298 # define gl_lock_initializer \
299 PTHREAD_MUTEX_INITIALIZER
300 # define glthread_lock_init(LOCK) \
301 (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
302 # define glthread_lock_lock(LOCK) \
303 (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
304 # define glthread_lock_unlock(LOCK) \
305 (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
306 # define glthread_lock_destroy(LOCK) \
307 (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
309 /* ------------------------- gl_rwlock_t datatype ------------------------- */
311 # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
313 # if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
315 typedef pthread_rwlock_t gl_rwlock_t;
316 # define gl_rwlock_define(STORAGECLASS, NAME) \
317 STORAGECLASS pthread_rwlock_t NAME;
318 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
319 STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
320 # if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
321 # if defined PTHREAD_RWLOCK_INITIALIZER
322 # define gl_rwlock_initializer \
323 PTHREAD_RWLOCK_INITIALIZER
325 # define gl_rwlock_initializer \
326 PTHREAD_RWLOCK_INITIALIZER_NP
328 # define glthread_rwlock_init(LOCK) \
329 (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
330 # else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
331 # define gl_rwlock_initializer \
332 PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
333 # define glthread_rwlock_init(LOCK) \
334 (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
335 extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
337 # define glthread_rwlock_rdlock(LOCK) \
338 (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
339 # define glthread_rwlock_wrlock(LOCK) \
340 (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
341 # define glthread_rwlock_unlock(LOCK) \
342 (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
343 # define glthread_rwlock_destroy(LOCK) \
344 (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
351 pthread_mutex_t guard; /* protects the initialization */
352 pthread_rwlock_t rwlock; /* read-write lock */
355 # define gl_rwlock_define(STORAGECLASS, NAME) \
356 STORAGECLASS gl_rwlock_t NAME;
357 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
358 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
359 # define gl_rwlock_initializer \
360 { 0, PTHREAD_MUTEX_INITIALIZER }
361 # define glthread_rwlock_init(LOCK) \
362 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
363 # define glthread_rwlock_rdlock(LOCK) \
364 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
365 # define glthread_rwlock_wrlock(LOCK) \
366 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
367 # define glthread_rwlock_unlock(LOCK) \
368 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
369 # define glthread_rwlock_destroy(LOCK) \
370 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
371 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
372 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
373 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
374 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
375 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
383 pthread_mutex_t lock; /* protects the remaining fields */
384 pthread_cond_t waiting_readers; /* waiting readers */
385 pthread_cond_t waiting_writers; /* waiting writers */
386 unsigned int waiting_writers_count; /* number of waiting writers */
387 int runcount; /* number of readers running, or -1 when a writer runs */
390 # define gl_rwlock_define(STORAGECLASS, NAME) \
391 STORAGECLASS gl_rwlock_t NAME;
392 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
393 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
394 # define gl_rwlock_initializer \
395 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
396 # define glthread_rwlock_init(LOCK) \
397 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
398 # define glthread_rwlock_rdlock(LOCK) \
399 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
400 # define glthread_rwlock_wrlock(LOCK) \
401 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
402 # define glthread_rwlock_unlock(LOCK) \
403 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
404 # define glthread_rwlock_destroy(LOCK) \
405 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
406 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
407 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
408 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
409 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
410 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
414 /* --------------------- gl_recursive_lock_t datatype --------------------- */
416 # if HAVE_PTHREAD_MUTEX_RECURSIVE
418 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
420 typedef pthread_mutex_t gl_recursive_lock_t;
421 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
422 STORAGECLASS pthread_mutex_t NAME;
423 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
424 STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
425 # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
426 # define gl_recursive_lock_initializer \
427 PTHREAD_RECURSIVE_MUTEX_INITIALIZER
429 # define gl_recursive_lock_initializer \
430 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
432 # define glthread_recursive_lock_init(LOCK) \
433 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
434 # define glthread_recursive_lock_lock(LOCK) \
435 (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
436 # define glthread_recursive_lock_unlock(LOCK) \
437 (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
438 # define glthread_recursive_lock_destroy(LOCK) \
439 (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
440 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
446 pthread_mutex_t recmutex; /* recursive mutex */
447 pthread_mutex_t guard; /* protects the initialization */
451 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
452 STORAGECLASS gl_recursive_lock_t NAME;
453 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
454 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
455 # define gl_recursive_lock_initializer \
456 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
457 # define glthread_recursive_lock_init(LOCK) \
458 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
459 # define glthread_recursive_lock_lock(LOCK) \
460 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
461 # define glthread_recursive_lock_unlock(LOCK) \
462 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
463 # define glthread_recursive_lock_destroy(LOCK) \
464 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
465 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
466 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
467 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
468 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
474 /* Old versions of POSIX threads on Solaris did not have recursive locks.
475 We have to implement them ourselves. */
479 pthread_mutex_t mutex;
484 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
485 STORAGECLASS gl_recursive_lock_t NAME;
486 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
487 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
488 # define gl_recursive_lock_initializer \
489 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
490 # define glthread_recursive_lock_init(LOCK) \
491 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
492 # define glthread_recursive_lock_lock(LOCK) \
493 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
494 # define glthread_recursive_lock_unlock(LOCK) \
495 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
496 # define glthread_recursive_lock_destroy(LOCK) \
497 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
498 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
499 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
500 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
501 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
505 /* -------------------------- gl_once_t datatype -------------------------- */
507 typedef pthread_once_t gl_once_t;
508 # define gl_once_define(STORAGECLASS, NAME) \
509 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
510 # if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
511 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
513 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
514 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
516 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
518 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
519 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
520 extern int glthread_once_multithreaded (pthread_once_t *once_control,
521 void (*init_function) (void));
523 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
531 /* ========================================================================= */
533 #if USE_WINDOWS_THREADS
535 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
536 # include <windows.h>
538 # include "windows-mutex.h"
539 # include "windows-rwlock.h"
540 # include "windows-recmutex.h"
541 # include "windows-once.h"
547 /* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
548 Mutex, Semaphore types, because
549 - we need only to synchronize inside a single process (address space),
550 not inter-process locking,
551 - we don't need to support trylock operations. (TryEnterCriticalSection
552 does not work on Windows 95/98/ME. Packages that need trylock usually
553 define their own mutex type.) */
555 /* There is no way to statically initialize a CRITICAL_SECTION. It needs
556 to be done lazily, once only. For this we need spinlocks. */
558 /* -------------------------- gl_lock_t datatype -------------------------- */
560 typedef glwthread_mutex_t gl_lock_t;
561 # define gl_lock_define(STORAGECLASS, NAME) \
562 STORAGECLASS gl_lock_t NAME;
563 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
564 STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
565 # define gl_lock_initializer \
567 # define glthread_lock_init(LOCK) \
568 (glwthread_mutex_init (LOCK), 0)
569 # define glthread_lock_lock(LOCK) \
570 glwthread_mutex_lock (LOCK)
571 # define glthread_lock_unlock(LOCK) \
572 glwthread_mutex_unlock (LOCK)
573 # define glthread_lock_destroy(LOCK) \
574 glwthread_mutex_destroy (LOCK)
576 /* ------------------------- gl_rwlock_t datatype ------------------------- */
578 typedef glwthread_rwlock_t gl_rwlock_t;
579 # define gl_rwlock_define(STORAGECLASS, NAME) \
580 STORAGECLASS gl_rwlock_t NAME;
581 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
582 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
583 # define gl_rwlock_initializer \
584 GLWTHREAD_RWLOCK_INIT
585 # define glthread_rwlock_init(LOCK) \
586 (glwthread_rwlock_init (LOCK), 0)
587 # define glthread_rwlock_rdlock(LOCK) \
588 glwthread_rwlock_rdlock (LOCK)
589 # define glthread_rwlock_wrlock(LOCK) \
590 glwthread_rwlock_wrlock (LOCK)
591 # define glthread_rwlock_unlock(LOCK) \
592 glwthread_rwlock_unlock (LOCK)
593 # define glthread_rwlock_destroy(LOCK) \
594 glwthread_rwlock_destroy (LOCK)
596 /* --------------------- gl_recursive_lock_t datatype --------------------- */
598 typedef glwthread_recmutex_t gl_recursive_lock_t;
599 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
600 STORAGECLASS gl_recursive_lock_t NAME;
601 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
602 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
603 # define gl_recursive_lock_initializer \
604 GLWTHREAD_RECMUTEX_INIT
605 # define glthread_recursive_lock_init(LOCK) \
606 (glwthread_recmutex_init (LOCK), 0)
607 # define glthread_recursive_lock_lock(LOCK) \
608 glwthread_recmutex_lock (LOCK)
609 # define glthread_recursive_lock_unlock(LOCK) \
610 glwthread_recmutex_unlock (LOCK)
611 # define glthread_recursive_lock_destroy(LOCK) \
612 glwthread_recmutex_destroy (LOCK)
614 /* -------------------------- gl_once_t datatype -------------------------- */
616 typedef glwthread_once_t gl_once_t;
617 # define gl_once_define(STORAGECLASS, NAME) \
618 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
619 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
620 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
628 /* ========================================================================= */
630 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
632 /* Provide dummy implementation if threads are not supported. */
634 /* -------------------------- gl_lock_t datatype -------------------------- */
636 typedef int gl_lock_t;
637 # define gl_lock_define(STORAGECLASS, NAME)
638 # define gl_lock_define_initialized(STORAGECLASS, NAME)
639 # define glthread_lock_init(NAME) 0
640 # define glthread_lock_lock(NAME) 0
641 # define glthread_lock_unlock(NAME) 0
642 # define glthread_lock_destroy(NAME) 0
644 /* ------------------------- gl_rwlock_t datatype ------------------------- */
646 typedef int gl_rwlock_t;
647 # define gl_rwlock_define(STORAGECLASS, NAME)
648 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
649 # define glthread_rwlock_init(NAME) 0
650 # define glthread_rwlock_rdlock(NAME) 0
651 # define glthread_rwlock_wrlock(NAME) 0
652 # define glthread_rwlock_unlock(NAME) 0
653 # define glthread_rwlock_destroy(NAME) 0
655 /* --------------------- gl_recursive_lock_t datatype --------------------- */
657 typedef int gl_recursive_lock_t;
658 # define gl_recursive_lock_define(STORAGECLASS, NAME)
659 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
660 # define glthread_recursive_lock_init(NAME) 0
661 # define glthread_recursive_lock_lock(NAME) 0
662 # define glthread_recursive_lock_unlock(NAME) 0
663 # define glthread_recursive_lock_destroy(NAME) 0
665 /* -------------------------- gl_once_t datatype -------------------------- */
667 typedef int gl_once_t;
668 # define gl_once_define(STORAGECLASS, NAME) \
669 STORAGECLASS gl_once_t NAME = 0;
670 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
671 (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
675 /* ========================================================================= */
677 /* Macros with built-in error handling. */
679 /* -------------------------- gl_lock_t datatype -------------------------- */
681 #define gl_lock_init(NAME) \
684 if (glthread_lock_init (&NAME)) \
688 #define gl_lock_lock(NAME) \
691 if (glthread_lock_lock (&NAME)) \
695 #define gl_lock_unlock(NAME) \
698 if (glthread_lock_unlock (&NAME)) \
702 #define gl_lock_destroy(NAME) \
705 if (glthread_lock_destroy (&NAME)) \
710 /* ------------------------- gl_rwlock_t datatype ------------------------- */
712 #define gl_rwlock_init(NAME) \
715 if (glthread_rwlock_init (&NAME)) \
719 #define gl_rwlock_rdlock(NAME) \
722 if (glthread_rwlock_rdlock (&NAME)) \
726 #define gl_rwlock_wrlock(NAME) \
729 if (glthread_rwlock_wrlock (&NAME)) \
733 #define gl_rwlock_unlock(NAME) \
736 if (glthread_rwlock_unlock (&NAME)) \
740 #define gl_rwlock_destroy(NAME) \
743 if (glthread_rwlock_destroy (&NAME)) \
748 /* --------------------- gl_recursive_lock_t datatype --------------------- */
750 #define gl_recursive_lock_init(NAME) \
753 if (glthread_recursive_lock_init (&NAME)) \
757 #define gl_recursive_lock_lock(NAME) \
760 if (glthread_recursive_lock_lock (&NAME)) \
764 #define gl_recursive_lock_unlock(NAME) \
767 if (glthread_recursive_lock_unlock (&NAME)) \
771 #define gl_recursive_lock_destroy(NAME) \
774 if (glthread_recursive_lock_destroy (&NAME)) \
779 /* -------------------------- gl_once_t datatype -------------------------- */
781 #define gl_once(NAME, INITFUNCTION) \
784 if (glthread_once (&NAME, INITFUNCTION)) \
789 /* ========================================================================= */