]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gnulib/import/glthread/lock.h
Update gnulib
[thirdparty/binutils-gdb.git] / gnulib / import / glthread / lock.h
CommitLineData
5abebf3c 1/* Locking in multithreaded situations.
dc6c21da 2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
5abebf3c 3
dc6c21da
TT
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.
5abebf3c 8
dc6c21da 9 This file is distributed in the hope that it will be useful,
5abebf3c
CB
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dc6c21da 12 GNU Lesser General Public License for more details.
5abebf3c 13
dc6c21da
TT
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/>. */
5abebf3c
CB
16
17/* Written by Bruno Haible <bruno@clisp.org>, 2005.
c0c3707f 18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
5abebf3c
CB
19
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.
23
24 Normal (non-recursive) locks:
25 Type: gl_lock_t
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);
37
38 Read-Write (non-recursive) locks:
39 Type: gl_rwlock_t
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);
53
54 Recursive locks:
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);
67
68 Once-only execution:
69 Type: gl_once_t
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);
74*/
75
76
77#ifndef _LOCK_H
78#define _LOCK_H
79
80#include <errno.h>
81#include <stdlib.h>
82
c0c3707f 83#if !defined c11_threads_in_use
dc6c21da
TT
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
c0c3707f
CB
87# include <threads.h>
88# pragma weak thrd_exit
89# define c11_threads_in_use() (thrd_exit != NULL)
90# else
91# define c11_threads_in_use() 0
92# endif
93#endif
94
95/* ========================================================================= */
96
97#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
98
99/* Use the ISO C threads library. */
100
101# include <threads.h>
102
103# ifdef __cplusplus
104extern "C" {
105# endif
106
107/* -------------------------- gl_lock_t datatype -------------------------- */
108
109typedef struct
110 {
111 int volatile init_needed;
112 once_flag init_once;
113 void (*init_func) (void);
114 mtx_t mutex;
115 }
116 gl_lock_t;
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) \
124 { \
125 if (glthread_lock_init (&(NAME))) \
126 abort (); \
127 }
128extern int glthread_lock_init (gl_lock_t *lock);
129extern int glthread_lock_lock (gl_lock_t *lock);
130extern int glthread_lock_unlock (gl_lock_t *lock);
131extern int glthread_lock_destroy (gl_lock_t *lock);
132
133/* ------------------------- gl_rwlock_t datatype ------------------------- */
134
135typedef struct
136 {
137 int volatile init_needed;
138 once_flag init_once;
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 */
145 }
146 gl_rwlock_t;
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) \
154 { \
155 if (glthread_rwlock_init (&(NAME))) \
156 abort (); \
157 }
158extern int glthread_rwlock_init (gl_rwlock_t *lock);
159extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
160extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
161extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
162extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
163
164/* --------------------- gl_recursive_lock_t datatype --------------------- */
165
166typedef struct
167 {
168 int volatile init_needed;
169 once_flag init_once;
170 void (*init_func) (void);
171 mtx_t mutex;
172 }
173 gl_recursive_lock_t;
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) \
181 { \
182 if (glthread_recursive_lock_init (&(NAME))) \
183 abort (); \
184 }
185extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
186extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
187extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
188extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
189
190/* -------------------------- gl_once_t datatype -------------------------- */
191
192typedef 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)
197
198# ifdef __cplusplus
199}
200# endif
201
202#endif
203
5abebf3c
CB
204/* ========================================================================= */
205
206#if USE_POSIX_THREADS
207
208/* Use the POSIX threads library. */
209
210# include <pthread.h>
211
212# ifdef __cplusplus
213extern "C" {
214# endif
215
216# if PTHREAD_IN_USE_DETECTION_HARD
217
218/* The pthread_in_use() detection needs to be done at runtime. */
219# define pthread_in_use() \
220 glthread_in_use ()
221extern int glthread_in_use (void);
222
223# endif
224
225# if USE_POSIX_THREADS_WEAK
226
227/* Use weak references to the POSIX threads library. */
228
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. */
236
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. */
243
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
c0c3707f
CB
262# pragma weak pthread_rwlockattr_init
263# if __GNU_LIBRARY__ > 1
264# pragma weak pthread_rwlockattr_setkind_np
265# endif
266# pragma weak pthread_rwlockattr_destroy
5abebf3c
CB
267# ifndef pthread_self
268# pragma weak pthread_self
269# endif
270
271# if !PTHREAD_IN_USE_DETECTION_HARD
c0c3707f
CB
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
277 */
278# pragma weak pthread_mutexattr_gettype
279# define pthread_in_use() \
280 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
5abebf3c
CB
281# endif
282
283# else
284
285# if !PTHREAD_IN_USE_DETECTION_HARD
286# define pthread_in_use() 1
287# endif
288
289# endif
290
291/* -------------------------- gl_lock_t datatype -------------------------- */
292
293typedef 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)
308
309/* ------------------------- gl_rwlock_t datatype ------------------------- */
310
c0c3707f 311# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
5abebf3c 312
5df4cba6 313# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
5abebf3c
CB
314
315typedef 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;
c0c3707f 320# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
5df4cba6
SM
321# if defined PTHREAD_RWLOCK_INITIALIZER
322# define gl_rwlock_initializer \
323 PTHREAD_RWLOCK_INITIALIZER
324# else
325# define gl_rwlock_initializer \
326 PTHREAD_RWLOCK_INITIALIZER_NP
327# endif
c0c3707f
CB
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)
335extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
336# endif
5abebf3c
CB
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)
345
346# else
347
348typedef struct
349 {
350 int initialized;
351 pthread_mutex_t guard; /* protects the initialization */
352 pthread_rwlock_t rwlock; /* read-write lock */
353 }
354 gl_rwlock_t;
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)
371extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
372extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
373extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
374extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
375extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
376
377# endif
378
379# else
380
381typedef struct
382 {
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 */
388 }
389 gl_rwlock_t;
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)
406extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
407extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
408extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
409extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
410extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
411
412# endif
413
414/* --------------------- gl_recursive_lock_t datatype --------------------- */
415
416# if HAVE_PTHREAD_MUTEX_RECURSIVE
417
418# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
419
420typedef 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
428# else
429# define gl_recursive_lock_initializer \
430 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
431# endif
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)
440extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
441
442# else
443
444typedef struct
445 {
446 pthread_mutex_t recmutex; /* recursive mutex */
447 pthread_mutex_t guard; /* protects the initialization */
448 int initialized;
449 }
450 gl_recursive_lock_t;
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)
465extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
466extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
467extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
468extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
469
470# endif
471
472# else
473
474/* Old versions of POSIX threads on Solaris did not have recursive locks.
475 We have to implement them ourselves. */
476
477typedef struct
478 {
479 pthread_mutex_t mutex;
480 pthread_t owner;
481 unsigned long depth;
482 }
483 gl_recursive_lock_t;
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)
498extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
499extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
500extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
501extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
502
503# endif
504
505/* -------------------------- gl_once_t datatype -------------------------- */
506
507typedef pthread_once_t gl_once_t;
508# define gl_once_define(STORAGECLASS, NAME) \
509 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
5df4cba6
SM
510# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
511# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
512 (pthread_in_use () \
513 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
514 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
515# else
516# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
517 (pthread_in_use () \
518 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
519 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
520extern int glthread_once_multithreaded (pthread_once_t *once_control,
521 void (*init_function) (void));
522# endif
5abebf3c
CB
523extern int glthread_once_singlethreaded (pthread_once_t *once_control);
524
525# ifdef __cplusplus
526}
527# endif
528
529#endif
530
531/* ========================================================================= */
532
5abebf3c
CB
533#if USE_WINDOWS_THREADS
534
535# define WIN32_LEAN_AND_MEAN /* avoid including junk */
536# include <windows.h>
537
c0c3707f
CB
538# include "windows-mutex.h"
539# include "windows-rwlock.h"
540# include "windows-recmutex.h"
541# include "windows-once.h"
542
5abebf3c
CB
543# ifdef __cplusplus
544extern "C" {
545# endif
546
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.) */
554
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. */
557
5abebf3c
CB
558/* -------------------------- gl_lock_t datatype -------------------------- */
559
c0c3707f 560typedef glwthread_mutex_t gl_lock_t;
5abebf3c
CB
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 \
c0c3707f 566 GLWTHREAD_MUTEX_INIT
5abebf3c 567# define glthread_lock_init(LOCK) \
c0c3707f 568 (glwthread_mutex_init (LOCK), 0)
5abebf3c 569# define glthread_lock_lock(LOCK) \
c0c3707f 570 glwthread_mutex_lock (LOCK)
5abebf3c 571# define glthread_lock_unlock(LOCK) \
c0c3707f 572 glwthread_mutex_unlock (LOCK)
5abebf3c 573# define glthread_lock_destroy(LOCK) \
c0c3707f 574 glwthread_mutex_destroy (LOCK)
5abebf3c
CB
575
576/* ------------------------- gl_rwlock_t datatype ------------------------- */
577
c0c3707f 578typedef glwthread_rwlock_t gl_rwlock_t;
5abebf3c
CB
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 \
c0c3707f 584 GLWTHREAD_RWLOCK_INIT
5abebf3c 585# define glthread_rwlock_init(LOCK) \
c0c3707f 586 (glwthread_rwlock_init (LOCK), 0)
5abebf3c 587# define glthread_rwlock_rdlock(LOCK) \
c0c3707f 588 glwthread_rwlock_rdlock (LOCK)
5abebf3c 589# define glthread_rwlock_wrlock(LOCK) \
c0c3707f 590 glwthread_rwlock_wrlock (LOCK)
5abebf3c 591# define glthread_rwlock_unlock(LOCK) \
c0c3707f 592 glwthread_rwlock_unlock (LOCK)
5abebf3c 593# define glthread_rwlock_destroy(LOCK) \
c0c3707f 594 glwthread_rwlock_destroy (LOCK)
5abebf3c
CB
595
596/* --------------------- gl_recursive_lock_t datatype --------------------- */
597
c0c3707f 598typedef glwthread_recmutex_t gl_recursive_lock_t;
5abebf3c
CB
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 \
c0c3707f 604 GLWTHREAD_RECMUTEX_INIT
5abebf3c 605# define glthread_recursive_lock_init(LOCK) \
c0c3707f 606 (glwthread_recmutex_init (LOCK), 0)
5abebf3c 607# define glthread_recursive_lock_lock(LOCK) \
c0c3707f 608 glwthread_recmutex_lock (LOCK)
5abebf3c 609# define glthread_recursive_lock_unlock(LOCK) \
c0c3707f 610 glwthread_recmutex_unlock (LOCK)
5abebf3c 611# define glthread_recursive_lock_destroy(LOCK) \
c0c3707f 612 glwthread_recmutex_destroy (LOCK)
5abebf3c
CB
613
614/* -------------------------- gl_once_t datatype -------------------------- */
615
c0c3707f 616typedef glwthread_once_t gl_once_t;
5abebf3c 617# define gl_once_define(STORAGECLASS, NAME) \
c0c3707f 618 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
5abebf3c 619# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
c0c3707f 620 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
5abebf3c
CB
621
622# ifdef __cplusplus
623}
624# endif
625
626#endif
627
628/* ========================================================================= */
629
c0c3707f 630#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
5abebf3c
CB
631
632/* Provide dummy implementation if threads are not supported. */
633
634/* -------------------------- gl_lock_t datatype -------------------------- */
635
636typedef 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
643
644/* ------------------------- gl_rwlock_t datatype ------------------------- */
645
646typedef 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
654
655/* --------------------- gl_recursive_lock_t datatype --------------------- */
656
657typedef 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
664
665/* -------------------------- gl_once_t datatype -------------------------- */
666
667typedef 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)
672
673#endif
674
675/* ========================================================================= */
676
677/* Macros with built-in error handling. */
678
679/* -------------------------- gl_lock_t datatype -------------------------- */
680
681#define gl_lock_init(NAME) \
682 do \
683 { \
684 if (glthread_lock_init (&NAME)) \
685 abort (); \
686 } \
687 while (0)
688#define gl_lock_lock(NAME) \
689 do \
690 { \
691 if (glthread_lock_lock (&NAME)) \
692 abort (); \
693 } \
694 while (0)
695#define gl_lock_unlock(NAME) \
696 do \
697 { \
698 if (glthread_lock_unlock (&NAME)) \
699 abort (); \
700 } \
701 while (0)
702#define gl_lock_destroy(NAME) \
703 do \
704 { \
705 if (glthread_lock_destroy (&NAME)) \
706 abort (); \
707 } \
708 while (0)
709
710/* ------------------------- gl_rwlock_t datatype ------------------------- */
711
712#define gl_rwlock_init(NAME) \
713 do \
714 { \
715 if (glthread_rwlock_init (&NAME)) \
716 abort (); \
717 } \
718 while (0)
719#define gl_rwlock_rdlock(NAME) \
720 do \
721 { \
722 if (glthread_rwlock_rdlock (&NAME)) \
723 abort (); \
724 } \
725 while (0)
726#define gl_rwlock_wrlock(NAME) \
727 do \
728 { \
729 if (glthread_rwlock_wrlock (&NAME)) \
730 abort (); \
731 } \
732 while (0)
733#define gl_rwlock_unlock(NAME) \
734 do \
735 { \
736 if (glthread_rwlock_unlock (&NAME)) \
737 abort (); \
738 } \
739 while (0)
740#define gl_rwlock_destroy(NAME) \
741 do \
742 { \
743 if (glthread_rwlock_destroy (&NAME)) \
744 abort (); \
745 } \
746 while (0)
747
748/* --------------------- gl_recursive_lock_t datatype --------------------- */
749
750#define gl_recursive_lock_init(NAME) \
751 do \
752 { \
753 if (glthread_recursive_lock_init (&NAME)) \
754 abort (); \
755 } \
756 while (0)
757#define gl_recursive_lock_lock(NAME) \
758 do \
759 { \
760 if (glthread_recursive_lock_lock (&NAME)) \
761 abort (); \
762 } \
763 while (0)
764#define gl_recursive_lock_unlock(NAME) \
765 do \
766 { \
767 if (glthread_recursive_lock_unlock (&NAME)) \
768 abort (); \
769 } \
770 while (0)
771#define gl_recursive_lock_destroy(NAME) \
772 do \
773 { \
774 if (glthread_recursive_lock_destroy (&NAME)) \
775 abort (); \
776 } \
777 while (0)
778
779/* -------------------------- gl_once_t datatype -------------------------- */
780
781#define gl_once(NAME, INITFUNCTION) \
782 do \
783 { \
784 if (glthread_once (&NAME, INITFUNCTION)) \
785 abort (); \
786 } \
787 while (0)
788
789/* ========================================================================= */
790
791#endif /* _LOCK_H */