xref: /dragonfly/contrib/grep/lib/glthread/lock.h (revision 09d4459f)
1680a9cb8SJohn Marino /* Locking in multithreaded situations.
2*09d4459fSDaniel Fojt    Copyright (C) 2005-2020 Free Software Foundation, Inc.
3680a9cb8SJohn Marino 
4680a9cb8SJohn Marino    This program is free software; you can redistribute it and/or modify
5680a9cb8SJohn Marino    it under the terms of the GNU General Public License as published by
6680a9cb8SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
7680a9cb8SJohn Marino    any later version.
8680a9cb8SJohn Marino 
9680a9cb8SJohn Marino    This program is distributed in the hope that it will be useful,
10680a9cb8SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
11680a9cb8SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12680a9cb8SJohn Marino    GNU General Public License for more details.
13680a9cb8SJohn Marino 
14680a9cb8SJohn Marino    You should have received a copy of the GNU General Public License
15*09d4459fSDaniel Fojt    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
16680a9cb8SJohn Marino 
17680a9cb8SJohn Marino /* Written by Bruno Haible <bruno@clisp.org>, 2005.
18*09d4459fSDaniel Fojt    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
19680a9cb8SJohn Marino 
20680a9cb8SJohn Marino /* This file contains locking primitives for use with a given thread library.
21680a9cb8SJohn Marino    It does not contain primitives for creating threads or for other
22680a9cb8SJohn Marino    synchronization primitives.
23680a9cb8SJohn Marino 
24680a9cb8SJohn Marino    Normal (non-recursive) locks:
25680a9cb8SJohn Marino      Type:                gl_lock_t
26680a9cb8SJohn Marino      Declaration:         gl_lock_define(extern, name)
27680a9cb8SJohn Marino      Initializer:         gl_lock_define_initialized(, name)
28680a9cb8SJohn Marino      Initialization:      gl_lock_init (name);
29680a9cb8SJohn Marino      Taking the lock:     gl_lock_lock (name);
30680a9cb8SJohn Marino      Releasing the lock:  gl_lock_unlock (name);
31680a9cb8SJohn Marino      De-initialization:   gl_lock_destroy (name);
32680a9cb8SJohn Marino    Equivalent functions with control of error handling:
33680a9cb8SJohn Marino      Initialization:      err = glthread_lock_init (&name);
34680a9cb8SJohn Marino      Taking the lock:     err = glthread_lock_lock (&name);
35680a9cb8SJohn Marino      Releasing the lock:  err = glthread_lock_unlock (&name);
36680a9cb8SJohn Marino      De-initialization:   err = glthread_lock_destroy (&name);
37680a9cb8SJohn Marino 
38680a9cb8SJohn Marino    Read-Write (non-recursive) locks:
39680a9cb8SJohn Marino      Type:                gl_rwlock_t
40680a9cb8SJohn Marino      Declaration:         gl_rwlock_define(extern, name)
41680a9cb8SJohn Marino      Initializer:         gl_rwlock_define_initialized(, name)
42680a9cb8SJohn Marino      Initialization:      gl_rwlock_init (name);
43680a9cb8SJohn Marino      Taking the lock:     gl_rwlock_rdlock (name);
44680a9cb8SJohn Marino                           gl_rwlock_wrlock (name);
45680a9cb8SJohn Marino      Releasing the lock:  gl_rwlock_unlock (name);
46680a9cb8SJohn Marino      De-initialization:   gl_rwlock_destroy (name);
47680a9cb8SJohn Marino    Equivalent functions with control of error handling:
48680a9cb8SJohn Marino      Initialization:      err = glthread_rwlock_init (&name);
49680a9cb8SJohn Marino      Taking the lock:     err = glthread_rwlock_rdlock (&name);
50680a9cb8SJohn Marino                           err = glthread_rwlock_wrlock (&name);
51680a9cb8SJohn Marino      Releasing the lock:  err = glthread_rwlock_unlock (&name);
52680a9cb8SJohn Marino      De-initialization:   err = glthread_rwlock_destroy (&name);
53680a9cb8SJohn Marino 
54680a9cb8SJohn Marino    Recursive locks:
55680a9cb8SJohn Marino      Type:                gl_recursive_lock_t
56680a9cb8SJohn Marino      Declaration:         gl_recursive_lock_define(extern, name)
57680a9cb8SJohn Marino      Initializer:         gl_recursive_lock_define_initialized(, name)
58680a9cb8SJohn Marino      Initialization:      gl_recursive_lock_init (name);
59680a9cb8SJohn Marino      Taking the lock:     gl_recursive_lock_lock (name);
60680a9cb8SJohn Marino      Releasing the lock:  gl_recursive_lock_unlock (name);
61680a9cb8SJohn Marino      De-initialization:   gl_recursive_lock_destroy (name);
62680a9cb8SJohn Marino    Equivalent functions with control of error handling:
63680a9cb8SJohn Marino      Initialization:      err = glthread_recursive_lock_init (&name);
64680a9cb8SJohn Marino      Taking the lock:     err = glthread_recursive_lock_lock (&name);
65680a9cb8SJohn Marino      Releasing the lock:  err = glthread_recursive_lock_unlock (&name);
66680a9cb8SJohn Marino      De-initialization:   err = glthread_recursive_lock_destroy (&name);
67680a9cb8SJohn Marino 
68680a9cb8SJohn Marino   Once-only execution:
69680a9cb8SJohn Marino      Type:                gl_once_t
70680a9cb8SJohn Marino      Initializer:         gl_once_define(extern, name)
71680a9cb8SJohn Marino      Execution:           gl_once (name, initfunction);
72680a9cb8SJohn Marino    Equivalent functions with control of error handling:
73680a9cb8SJohn Marino      Execution:           err = glthread_once (&name, initfunction);
74680a9cb8SJohn Marino */
75680a9cb8SJohn Marino 
76680a9cb8SJohn Marino 
77680a9cb8SJohn Marino #ifndef _LOCK_H
78680a9cb8SJohn Marino #define _LOCK_H
79680a9cb8SJohn Marino 
80680a9cb8SJohn Marino #include <errno.h>
81680a9cb8SJohn Marino #include <stdlib.h>
82680a9cb8SJohn Marino 
83*09d4459fSDaniel Fojt #if !defined c11_threads_in_use
84*09d4459fSDaniel Fojt # if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
85*09d4459fSDaniel Fojt #  include <threads.h>
86*09d4459fSDaniel Fojt #  pragma weak thrd_exit
87*09d4459fSDaniel Fojt #  define c11_threads_in_use() (thrd_exit != NULL)
88*09d4459fSDaniel Fojt # else
89*09d4459fSDaniel Fojt #  define c11_threads_in_use() 0
90*09d4459fSDaniel Fojt # endif
91*09d4459fSDaniel Fojt #endif
92*09d4459fSDaniel Fojt 
93*09d4459fSDaniel Fojt /* ========================================================================= */
94*09d4459fSDaniel Fojt 
95*09d4459fSDaniel Fojt #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
96*09d4459fSDaniel Fojt 
97*09d4459fSDaniel Fojt /* Use the ISO C threads library.  */
98*09d4459fSDaniel Fojt 
99*09d4459fSDaniel Fojt # include <threads.h>
100*09d4459fSDaniel Fojt 
101*09d4459fSDaniel Fojt # ifdef __cplusplus
102*09d4459fSDaniel Fojt extern "C" {
103*09d4459fSDaniel Fojt # endif
104*09d4459fSDaniel Fojt 
105*09d4459fSDaniel Fojt /* -------------------------- gl_lock_t datatype -------------------------- */
106*09d4459fSDaniel Fojt 
107*09d4459fSDaniel Fojt typedef struct
108*09d4459fSDaniel Fojt         {
109*09d4459fSDaniel Fojt           int volatile init_needed;
110*09d4459fSDaniel Fojt           once_flag init_once;
111*09d4459fSDaniel Fojt           void (*init_func) (void);
112*09d4459fSDaniel Fojt           mtx_t mutex;
113*09d4459fSDaniel Fojt         }
114*09d4459fSDaniel Fojt         gl_lock_t;
115*09d4459fSDaniel Fojt # define gl_lock_define(STORAGECLASS, NAME) \
116*09d4459fSDaniel Fojt     STORAGECLASS gl_lock_t NAME;
117*09d4459fSDaniel Fojt # define gl_lock_define_initialized(STORAGECLASS, NAME) \
118*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void);       \
119*09d4459fSDaniel Fojt     STORAGECLASS gl_lock_t NAME =                 \
120*09d4459fSDaniel Fojt       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
121*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void)        \
122*09d4459fSDaniel Fojt     {                                             \
123*09d4459fSDaniel Fojt       if (glthread_lock_init (&(NAME)))           \
124*09d4459fSDaniel Fojt         abort ();                                 \
125*09d4459fSDaniel Fojt     }
126*09d4459fSDaniel Fojt extern int glthread_lock_init (gl_lock_t *lock);
127*09d4459fSDaniel Fojt extern int glthread_lock_lock (gl_lock_t *lock);
128*09d4459fSDaniel Fojt extern int glthread_lock_unlock (gl_lock_t *lock);
129*09d4459fSDaniel Fojt extern int glthread_lock_destroy (gl_lock_t *lock);
130*09d4459fSDaniel Fojt 
131*09d4459fSDaniel Fojt /* ------------------------- gl_rwlock_t datatype ------------------------- */
132*09d4459fSDaniel Fojt 
133*09d4459fSDaniel Fojt typedef struct
134*09d4459fSDaniel Fojt         {
135*09d4459fSDaniel Fojt           int volatile init_needed;
136*09d4459fSDaniel Fojt           once_flag init_once;
137*09d4459fSDaniel Fojt           void (*init_func) (void);
138*09d4459fSDaniel Fojt           mtx_t lock; /* protects the remaining fields */
139*09d4459fSDaniel Fojt           cnd_t waiting_readers; /* waiting readers */
140*09d4459fSDaniel Fojt           cnd_t waiting_writers; /* waiting writers */
141*09d4459fSDaniel Fojt           unsigned int waiting_writers_count; /* number of waiting writers */
142*09d4459fSDaniel Fojt           int runcount; /* number of readers running, or -1 when a writer runs */
143*09d4459fSDaniel Fojt         }
144*09d4459fSDaniel Fojt         gl_rwlock_t;
145*09d4459fSDaniel Fojt # define gl_rwlock_define(STORAGECLASS, NAME) \
146*09d4459fSDaniel Fojt     STORAGECLASS gl_rwlock_t NAME;
147*09d4459fSDaniel Fojt # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
148*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void);       \
149*09d4459fSDaniel Fojt     STORAGECLASS gl_rwlock_t NAME =               \
150*09d4459fSDaniel Fojt       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
151*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void)        \
152*09d4459fSDaniel Fojt     {                                             \
153*09d4459fSDaniel Fojt       if (glthread_rwlock_init (&(NAME)))         \
154*09d4459fSDaniel Fojt         abort ();                                 \
155*09d4459fSDaniel Fojt     }
156*09d4459fSDaniel Fojt extern int glthread_rwlock_init (gl_rwlock_t *lock);
157*09d4459fSDaniel Fojt extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
158*09d4459fSDaniel Fojt extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
159*09d4459fSDaniel Fojt extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
160*09d4459fSDaniel Fojt extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
161*09d4459fSDaniel Fojt 
162*09d4459fSDaniel Fojt /* --------------------- gl_recursive_lock_t datatype --------------------- */
163*09d4459fSDaniel Fojt 
164*09d4459fSDaniel Fojt typedef struct
165*09d4459fSDaniel Fojt         {
166*09d4459fSDaniel Fojt           int volatile init_needed;
167*09d4459fSDaniel Fojt           once_flag init_once;
168*09d4459fSDaniel Fojt           void (*init_func) (void);
169*09d4459fSDaniel Fojt           mtx_t mutex;
170*09d4459fSDaniel Fojt         }
171*09d4459fSDaniel Fojt         gl_recursive_lock_t;
172*09d4459fSDaniel Fojt # define gl_recursive_lock_define(STORAGECLASS, NAME) \
173*09d4459fSDaniel Fojt     STORAGECLASS gl_recursive_lock_t NAME;
174*09d4459fSDaniel Fojt # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
175*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void);       \
176*09d4459fSDaniel Fojt     STORAGECLASS gl_recursive_lock_t NAME =       \
177*09d4459fSDaniel Fojt       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
178*09d4459fSDaniel Fojt     static void _atomic_init_##NAME (void)        \
179*09d4459fSDaniel Fojt     {                                             \
180*09d4459fSDaniel Fojt       if (glthread_recursive_lock_init (&(NAME))) \
181*09d4459fSDaniel Fojt         abort ();                                 \
182*09d4459fSDaniel Fojt     }
183*09d4459fSDaniel Fojt extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
184*09d4459fSDaniel Fojt extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
185*09d4459fSDaniel Fojt extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
186*09d4459fSDaniel Fojt extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
187*09d4459fSDaniel Fojt 
188*09d4459fSDaniel Fojt /* -------------------------- gl_once_t datatype -------------------------- */
189*09d4459fSDaniel Fojt 
190*09d4459fSDaniel Fojt typedef once_flag gl_once_t;
191*09d4459fSDaniel Fojt # define gl_once_define(STORAGECLASS, NAME) \
192*09d4459fSDaniel Fojt     STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
193*09d4459fSDaniel Fojt # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
194*09d4459fSDaniel Fojt     (call_once (ONCE_CONTROL, INITFUNCTION), 0)
195*09d4459fSDaniel Fojt 
196*09d4459fSDaniel Fojt # ifdef __cplusplus
197*09d4459fSDaniel Fojt }
198*09d4459fSDaniel Fojt # endif
199*09d4459fSDaniel Fojt 
200*09d4459fSDaniel Fojt #endif
201*09d4459fSDaniel Fojt 
202680a9cb8SJohn Marino /* ========================================================================= */
203680a9cb8SJohn Marino 
204680a9cb8SJohn Marino #if USE_POSIX_THREADS
205680a9cb8SJohn Marino 
206680a9cb8SJohn Marino /* Use the POSIX threads library.  */
207680a9cb8SJohn Marino 
208680a9cb8SJohn Marino # include <pthread.h>
209680a9cb8SJohn Marino 
210680a9cb8SJohn Marino # ifdef __cplusplus
211680a9cb8SJohn Marino extern "C" {
212680a9cb8SJohn Marino # endif
213680a9cb8SJohn Marino 
214680a9cb8SJohn Marino # if PTHREAD_IN_USE_DETECTION_HARD
215680a9cb8SJohn Marino 
216680a9cb8SJohn Marino /* The pthread_in_use() detection needs to be done at runtime.  */
217680a9cb8SJohn Marino #  define pthread_in_use() \
218680a9cb8SJohn Marino      glthread_in_use ()
219680a9cb8SJohn Marino extern int glthread_in_use (void);
220680a9cb8SJohn Marino 
221680a9cb8SJohn Marino # endif
222680a9cb8SJohn Marino 
223680a9cb8SJohn Marino # if USE_POSIX_THREADS_WEAK
224680a9cb8SJohn Marino 
225680a9cb8SJohn Marino /* Use weak references to the POSIX threads library.  */
226680a9cb8SJohn Marino 
227680a9cb8SJohn Marino /* Weak references avoid dragging in external libraries if the other parts
228680a9cb8SJohn Marino    of the program don't use them.  Here we use them, because we don't want
229680a9cb8SJohn Marino    every program that uses libintl to depend on libpthread.  This assumes
230680a9cb8SJohn Marino    that libpthread would not be loaded after libintl; i.e. if libintl is
231680a9cb8SJohn Marino    loaded first, by an executable that does not depend on libpthread, and
232680a9cb8SJohn Marino    then a module is dynamically loaded that depends on libpthread, libintl
233680a9cb8SJohn Marino    will not be multithread-safe.  */
234680a9cb8SJohn Marino 
235680a9cb8SJohn Marino /* The way to test at runtime whether libpthread is present is to test
236680a9cb8SJohn Marino    whether a function pointer's value, such as &pthread_mutex_init, is
237680a9cb8SJohn Marino    non-NULL.  However, some versions of GCC have a bug through which, in
238680a9cb8SJohn Marino    PIC mode, &foo != NULL always evaluates to true if there is a direct
239680a9cb8SJohn Marino    call to foo(...) in the same function.  To avoid this, we test the
240680a9cb8SJohn Marino    address of a function in libpthread that we don't use.  */
241680a9cb8SJohn Marino 
242680a9cb8SJohn Marino #  pragma weak pthread_mutex_init
243680a9cb8SJohn Marino #  pragma weak pthread_mutex_lock
244680a9cb8SJohn Marino #  pragma weak pthread_mutex_unlock
245680a9cb8SJohn Marino #  pragma weak pthread_mutex_destroy
246680a9cb8SJohn Marino #  pragma weak pthread_rwlock_init
247680a9cb8SJohn Marino #  pragma weak pthread_rwlock_rdlock
248680a9cb8SJohn Marino #  pragma weak pthread_rwlock_wrlock
249680a9cb8SJohn Marino #  pragma weak pthread_rwlock_unlock
250680a9cb8SJohn Marino #  pragma weak pthread_rwlock_destroy
251680a9cb8SJohn Marino #  pragma weak pthread_once
252680a9cb8SJohn Marino #  pragma weak pthread_cond_init
253680a9cb8SJohn Marino #  pragma weak pthread_cond_wait
254680a9cb8SJohn Marino #  pragma weak pthread_cond_signal
255680a9cb8SJohn Marino #  pragma weak pthread_cond_broadcast
256680a9cb8SJohn Marino #  pragma weak pthread_cond_destroy
257680a9cb8SJohn Marino #  pragma weak pthread_mutexattr_init
258680a9cb8SJohn Marino #  pragma weak pthread_mutexattr_settype
259680a9cb8SJohn Marino #  pragma weak pthread_mutexattr_destroy
260*09d4459fSDaniel Fojt #  pragma weak pthread_rwlockattr_init
261*09d4459fSDaniel Fojt #  if __GNU_LIBRARY__ > 1
262*09d4459fSDaniel Fojt #   pragma weak pthread_rwlockattr_setkind_np
263*09d4459fSDaniel Fojt #  endif
264*09d4459fSDaniel Fojt #  pragma weak pthread_rwlockattr_destroy
265680a9cb8SJohn Marino #  ifndef pthread_self
266680a9cb8SJohn Marino #   pragma weak pthread_self
267680a9cb8SJohn Marino #  endif
268680a9cb8SJohn Marino 
269680a9cb8SJohn Marino #  if !PTHREAD_IN_USE_DETECTION_HARD
270*09d4459fSDaniel Fojt     /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
271*09d4459fSDaniel Fojt        can be used to determine whether libpthread is in use.  These are:
272*09d4459fSDaniel Fojt          pthread_mutexattr_gettype
273*09d4459fSDaniel Fojt          pthread_rwlockattr_destroy
274*09d4459fSDaniel Fojt          pthread_rwlockattr_init
275*09d4459fSDaniel Fojt      */
276*09d4459fSDaniel Fojt #   pragma weak pthread_mutexattr_gettype
277*09d4459fSDaniel Fojt #   define pthread_in_use() \
278*09d4459fSDaniel Fojt       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
279680a9cb8SJohn Marino #  endif
280680a9cb8SJohn Marino 
281680a9cb8SJohn Marino # else
282680a9cb8SJohn Marino 
283680a9cb8SJohn Marino #  if !PTHREAD_IN_USE_DETECTION_HARD
284680a9cb8SJohn Marino #   define pthread_in_use() 1
285680a9cb8SJohn Marino #  endif
286680a9cb8SJohn Marino 
287680a9cb8SJohn Marino # endif
288680a9cb8SJohn Marino 
289680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */
290680a9cb8SJohn Marino 
291680a9cb8SJohn Marino typedef pthread_mutex_t gl_lock_t;
292680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME) \
293680a9cb8SJohn Marino     STORAGECLASS pthread_mutex_t NAME;
294680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME) \
295680a9cb8SJohn Marino     STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
296680a9cb8SJohn Marino # define gl_lock_initializer \
297680a9cb8SJohn Marino     PTHREAD_MUTEX_INITIALIZER
298680a9cb8SJohn Marino # define glthread_lock_init(LOCK) \
299680a9cb8SJohn Marino     (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
300680a9cb8SJohn Marino # define glthread_lock_lock(LOCK) \
301680a9cb8SJohn Marino     (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
302680a9cb8SJohn Marino # define glthread_lock_unlock(LOCK) \
303680a9cb8SJohn Marino     (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
304680a9cb8SJohn Marino # define glthread_lock_destroy(LOCK) \
305680a9cb8SJohn Marino     (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
306680a9cb8SJohn Marino 
307680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */
308680a9cb8SJohn Marino 
309*09d4459fSDaniel Fojt # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
310680a9cb8SJohn Marino 
311*09d4459fSDaniel Fojt #  if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
312680a9cb8SJohn Marino 
313680a9cb8SJohn Marino typedef pthread_rwlock_t gl_rwlock_t;
314680a9cb8SJohn Marino #   define gl_rwlock_define(STORAGECLASS, NAME) \
315680a9cb8SJohn Marino       STORAGECLASS pthread_rwlock_t NAME;
316680a9cb8SJohn Marino #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
317680a9cb8SJohn Marino       STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
318*09d4459fSDaniel Fojt #   if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
319*09d4459fSDaniel Fojt #    if defined PTHREAD_RWLOCK_INITIALIZER
320680a9cb8SJohn Marino #     define gl_rwlock_initializer \
321680a9cb8SJohn Marino         PTHREAD_RWLOCK_INITIALIZER
322*09d4459fSDaniel Fojt #    else
323*09d4459fSDaniel Fojt #     define gl_rwlock_initializer \
324*09d4459fSDaniel Fojt         PTHREAD_RWLOCK_INITIALIZER_NP
325*09d4459fSDaniel Fojt #    endif
326680a9cb8SJohn Marino #    define glthread_rwlock_init(LOCK) \
327680a9cb8SJohn Marino        (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
328*09d4459fSDaniel Fojt #   else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
329*09d4459fSDaniel Fojt #    define gl_rwlock_initializer \
330*09d4459fSDaniel Fojt        PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
331*09d4459fSDaniel Fojt #    define glthread_rwlock_init(LOCK) \
332*09d4459fSDaniel Fojt        (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
333*09d4459fSDaniel Fojt extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
334*09d4459fSDaniel Fojt #   endif
335680a9cb8SJohn Marino #   define glthread_rwlock_rdlock(LOCK) \
336680a9cb8SJohn Marino       (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
337680a9cb8SJohn Marino #   define glthread_rwlock_wrlock(LOCK) \
338680a9cb8SJohn Marino       (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
339680a9cb8SJohn Marino #   define glthread_rwlock_unlock(LOCK) \
340680a9cb8SJohn Marino       (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
341680a9cb8SJohn Marino #   define glthread_rwlock_destroy(LOCK) \
342680a9cb8SJohn Marino       (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
343680a9cb8SJohn Marino 
344680a9cb8SJohn Marino #  else
345680a9cb8SJohn Marino 
346680a9cb8SJohn Marino typedef struct
347680a9cb8SJohn Marino         {
348680a9cb8SJohn Marino           int initialized;
349680a9cb8SJohn Marino           pthread_mutex_t guard;   /* protects the initialization */
350680a9cb8SJohn Marino           pthread_rwlock_t rwlock; /* read-write lock */
351680a9cb8SJohn Marino         }
352680a9cb8SJohn Marino         gl_rwlock_t;
353680a9cb8SJohn Marino #   define gl_rwlock_define(STORAGECLASS, NAME) \
354680a9cb8SJohn Marino       STORAGECLASS gl_rwlock_t NAME;
355680a9cb8SJohn Marino #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
356680a9cb8SJohn Marino       STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
357680a9cb8SJohn Marino #   define gl_rwlock_initializer \
358680a9cb8SJohn Marino       { 0, PTHREAD_MUTEX_INITIALIZER }
359680a9cb8SJohn Marino #   define glthread_rwlock_init(LOCK) \
360680a9cb8SJohn Marino       (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
361680a9cb8SJohn Marino #   define glthread_rwlock_rdlock(LOCK) \
362680a9cb8SJohn Marino       (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
363680a9cb8SJohn Marino #   define glthread_rwlock_wrlock(LOCK) \
364680a9cb8SJohn Marino       (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
365680a9cb8SJohn Marino #   define glthread_rwlock_unlock(LOCK) \
366680a9cb8SJohn Marino       (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
367680a9cb8SJohn Marino #   define glthread_rwlock_destroy(LOCK) \
368680a9cb8SJohn Marino       (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
369680a9cb8SJohn Marino extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
370680a9cb8SJohn Marino extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
371680a9cb8SJohn Marino extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
372680a9cb8SJohn Marino extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
373680a9cb8SJohn Marino extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
374680a9cb8SJohn Marino 
375680a9cb8SJohn Marino #  endif
376680a9cb8SJohn Marino 
377680a9cb8SJohn Marino # else
378680a9cb8SJohn Marino 
379680a9cb8SJohn Marino typedef struct
380680a9cb8SJohn Marino         {
381680a9cb8SJohn Marino           pthread_mutex_t lock; /* protects the remaining fields */
382680a9cb8SJohn Marino           pthread_cond_t waiting_readers; /* waiting readers */
383680a9cb8SJohn Marino           pthread_cond_t waiting_writers; /* waiting writers */
384680a9cb8SJohn Marino           unsigned int waiting_writers_count; /* number of waiting writers */
385680a9cb8SJohn Marino           int runcount; /* number of readers running, or -1 when a writer runs */
386680a9cb8SJohn Marino         }
387680a9cb8SJohn Marino         gl_rwlock_t;
388680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \
389680a9cb8SJohn Marino     STORAGECLASS gl_rwlock_t NAME;
390680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
391680a9cb8SJohn Marino     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
392680a9cb8SJohn Marino # define gl_rwlock_initializer \
393680a9cb8SJohn Marino     { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
394680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \
395680a9cb8SJohn Marino     (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
396680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \
397680a9cb8SJohn Marino     (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
398680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \
399680a9cb8SJohn Marino     (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
400680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \
401680a9cb8SJohn Marino     (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
402680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \
403680a9cb8SJohn Marino     (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
404680a9cb8SJohn Marino extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
405680a9cb8SJohn Marino extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
406680a9cb8SJohn Marino extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
407680a9cb8SJohn Marino extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
408680a9cb8SJohn Marino extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
409680a9cb8SJohn Marino 
410680a9cb8SJohn Marino # endif
411680a9cb8SJohn Marino 
412680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */
413680a9cb8SJohn Marino 
414680a9cb8SJohn Marino # if HAVE_PTHREAD_MUTEX_RECURSIVE
415680a9cb8SJohn Marino 
416680a9cb8SJohn Marino #  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
417680a9cb8SJohn Marino 
418680a9cb8SJohn Marino typedef pthread_mutex_t gl_recursive_lock_t;
419680a9cb8SJohn Marino #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
420680a9cb8SJohn Marino       STORAGECLASS pthread_mutex_t NAME;
421680a9cb8SJohn Marino #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
422680a9cb8SJohn Marino       STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
423680a9cb8SJohn Marino #   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
424680a9cb8SJohn Marino #    define gl_recursive_lock_initializer \
425680a9cb8SJohn Marino        PTHREAD_RECURSIVE_MUTEX_INITIALIZER
426680a9cb8SJohn Marino #   else
427680a9cb8SJohn Marino #    define gl_recursive_lock_initializer \
428680a9cb8SJohn Marino        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
429680a9cb8SJohn Marino #   endif
430680a9cb8SJohn Marino #   define glthread_recursive_lock_init(LOCK) \
431680a9cb8SJohn Marino       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
432680a9cb8SJohn Marino #   define glthread_recursive_lock_lock(LOCK) \
433680a9cb8SJohn Marino       (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
434680a9cb8SJohn Marino #   define glthread_recursive_lock_unlock(LOCK) \
435680a9cb8SJohn Marino       (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
436680a9cb8SJohn Marino #   define glthread_recursive_lock_destroy(LOCK) \
437680a9cb8SJohn Marino       (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
438680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
439680a9cb8SJohn Marino 
440680a9cb8SJohn Marino #  else
441680a9cb8SJohn Marino 
442680a9cb8SJohn Marino typedef struct
443680a9cb8SJohn Marino         {
444680a9cb8SJohn Marino           pthread_mutex_t recmutex; /* recursive mutex */
445680a9cb8SJohn Marino           pthread_mutex_t guard;    /* protects the initialization */
446680a9cb8SJohn Marino           int initialized;
447680a9cb8SJohn Marino         }
448680a9cb8SJohn Marino         gl_recursive_lock_t;
449680a9cb8SJohn Marino #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
450680a9cb8SJohn Marino       STORAGECLASS gl_recursive_lock_t NAME;
451680a9cb8SJohn Marino #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
452680a9cb8SJohn Marino       STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
453680a9cb8SJohn Marino #   define gl_recursive_lock_initializer \
454680a9cb8SJohn Marino       { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
455680a9cb8SJohn Marino #   define glthread_recursive_lock_init(LOCK) \
456680a9cb8SJohn Marino       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
457680a9cb8SJohn Marino #   define glthread_recursive_lock_lock(LOCK) \
458680a9cb8SJohn Marino       (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
459680a9cb8SJohn Marino #   define glthread_recursive_lock_unlock(LOCK) \
460680a9cb8SJohn Marino       (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
461680a9cb8SJohn Marino #   define glthread_recursive_lock_destroy(LOCK) \
462680a9cb8SJohn Marino       (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
463680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
464680a9cb8SJohn Marino extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
465680a9cb8SJohn Marino extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
466680a9cb8SJohn Marino extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
467680a9cb8SJohn Marino 
468680a9cb8SJohn Marino #  endif
469680a9cb8SJohn Marino 
470680a9cb8SJohn Marino # else
471680a9cb8SJohn Marino 
472680a9cb8SJohn Marino /* Old versions of POSIX threads on Solaris did not have recursive locks.
473680a9cb8SJohn Marino    We have to implement them ourselves.  */
474680a9cb8SJohn Marino 
475680a9cb8SJohn Marino typedef struct
476680a9cb8SJohn Marino         {
477680a9cb8SJohn Marino           pthread_mutex_t mutex;
478680a9cb8SJohn Marino           pthread_t owner;
479680a9cb8SJohn Marino           unsigned long depth;
480680a9cb8SJohn Marino         }
481680a9cb8SJohn Marino         gl_recursive_lock_t;
482680a9cb8SJohn Marino #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
483680a9cb8SJohn Marino      STORAGECLASS gl_recursive_lock_t NAME;
484680a9cb8SJohn Marino #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
485680a9cb8SJohn Marino      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
486680a9cb8SJohn Marino #  define gl_recursive_lock_initializer \
487680a9cb8SJohn Marino      { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
488680a9cb8SJohn Marino #  define glthread_recursive_lock_init(LOCK) \
489680a9cb8SJohn Marino      (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
490680a9cb8SJohn Marino #  define glthread_recursive_lock_lock(LOCK) \
491680a9cb8SJohn Marino      (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
492680a9cb8SJohn Marino #  define glthread_recursive_lock_unlock(LOCK) \
493680a9cb8SJohn Marino      (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
494680a9cb8SJohn Marino #  define glthread_recursive_lock_destroy(LOCK) \
495680a9cb8SJohn Marino      (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
496680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
497680a9cb8SJohn Marino extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
498680a9cb8SJohn Marino extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
499680a9cb8SJohn Marino extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
500680a9cb8SJohn Marino 
501680a9cb8SJohn Marino # endif
502680a9cb8SJohn Marino 
503680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */
504680a9cb8SJohn Marino 
505680a9cb8SJohn Marino typedef pthread_once_t gl_once_t;
506680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \
507680a9cb8SJohn Marino     STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
508680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
509680a9cb8SJohn Marino     (pthread_in_use ()                                                         \
510680a9cb8SJohn Marino      ? pthread_once (ONCE_CONTROL, INITFUNCTION)                               \
511680a9cb8SJohn Marino      : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
512680a9cb8SJohn Marino extern int glthread_once_singlethreaded (pthread_once_t *once_control);
513680a9cb8SJohn Marino 
514680a9cb8SJohn Marino # ifdef __cplusplus
515680a9cb8SJohn Marino }
516680a9cb8SJohn Marino # endif
517680a9cb8SJohn Marino 
518680a9cb8SJohn Marino #endif
519680a9cb8SJohn Marino 
520680a9cb8SJohn Marino /* ========================================================================= */
521680a9cb8SJohn Marino 
522680a9cb8SJohn Marino #if USE_WINDOWS_THREADS
523680a9cb8SJohn Marino 
524680a9cb8SJohn Marino # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
525680a9cb8SJohn Marino # include <windows.h>
526680a9cb8SJohn Marino 
527*09d4459fSDaniel Fojt # include "windows-mutex.h"
528*09d4459fSDaniel Fojt # include "windows-rwlock.h"
529*09d4459fSDaniel Fojt # include "windows-recmutex.h"
530*09d4459fSDaniel Fojt # include "windows-once.h"
531*09d4459fSDaniel Fojt 
532680a9cb8SJohn Marino # ifdef __cplusplus
533680a9cb8SJohn Marino extern "C" {
534680a9cb8SJohn Marino # endif
535680a9cb8SJohn Marino 
536680a9cb8SJohn Marino /* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
537680a9cb8SJohn Marino    Mutex, Semaphore types, because
538680a9cb8SJohn Marino      - we need only to synchronize inside a single process (address space),
539680a9cb8SJohn Marino        not inter-process locking,
540680a9cb8SJohn Marino      - we don't need to support trylock operations.  (TryEnterCriticalSection
541680a9cb8SJohn Marino        does not work on Windows 95/98/ME.  Packages that need trylock usually
542680a9cb8SJohn Marino        define their own mutex type.)  */
543680a9cb8SJohn Marino 
544680a9cb8SJohn Marino /* There is no way to statically initialize a CRITICAL_SECTION.  It needs
545680a9cb8SJohn Marino    to be done lazily, once only.  For this we need spinlocks.  */
546680a9cb8SJohn Marino 
547680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */
548680a9cb8SJohn Marino 
549*09d4459fSDaniel Fojt typedef glwthread_mutex_t gl_lock_t;
550680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME) \
551680a9cb8SJohn Marino     STORAGECLASS gl_lock_t NAME;
552680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME) \
553680a9cb8SJohn Marino     STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
554680a9cb8SJohn Marino # define gl_lock_initializer \
555*09d4459fSDaniel Fojt     GLWTHREAD_MUTEX_INIT
556680a9cb8SJohn Marino # define glthread_lock_init(LOCK) \
557*09d4459fSDaniel Fojt     (glwthread_mutex_init (LOCK), 0)
558680a9cb8SJohn Marino # define glthread_lock_lock(LOCK) \
559*09d4459fSDaniel Fojt     glwthread_mutex_lock (LOCK)
560680a9cb8SJohn Marino # define glthread_lock_unlock(LOCK) \
561*09d4459fSDaniel Fojt     glwthread_mutex_unlock (LOCK)
562680a9cb8SJohn Marino # define glthread_lock_destroy(LOCK) \
563*09d4459fSDaniel Fojt     glwthread_mutex_destroy (LOCK)
564680a9cb8SJohn Marino 
565680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */
566680a9cb8SJohn Marino 
567*09d4459fSDaniel Fojt typedef glwthread_rwlock_t gl_rwlock_t;
568680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \
569680a9cb8SJohn Marino     STORAGECLASS gl_rwlock_t NAME;
570680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
571680a9cb8SJohn Marino     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
572680a9cb8SJohn Marino # define gl_rwlock_initializer \
573*09d4459fSDaniel Fojt     GLWTHREAD_RWLOCK_INIT
574680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \
575*09d4459fSDaniel Fojt     (glwthread_rwlock_init (LOCK), 0)
576680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \
577*09d4459fSDaniel Fojt     glwthread_rwlock_rdlock (LOCK)
578680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \
579*09d4459fSDaniel Fojt     glwthread_rwlock_wrlock (LOCK)
580680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \
581*09d4459fSDaniel Fojt     glwthread_rwlock_unlock (LOCK)
582680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \
583*09d4459fSDaniel Fojt     glwthread_rwlock_destroy (LOCK)
584680a9cb8SJohn Marino 
585680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */
586680a9cb8SJohn Marino 
587*09d4459fSDaniel Fojt typedef glwthread_recmutex_t gl_recursive_lock_t;
588680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) \
589680a9cb8SJohn Marino     STORAGECLASS gl_recursive_lock_t NAME;
590680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
591680a9cb8SJohn Marino     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
592680a9cb8SJohn Marino # define gl_recursive_lock_initializer \
593*09d4459fSDaniel Fojt     GLWTHREAD_RECMUTEX_INIT
594680a9cb8SJohn Marino # define glthread_recursive_lock_init(LOCK) \
595*09d4459fSDaniel Fojt     (glwthread_recmutex_init (LOCK), 0)
596680a9cb8SJohn Marino # define glthread_recursive_lock_lock(LOCK) \
597*09d4459fSDaniel Fojt     glwthread_recmutex_lock (LOCK)
598680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(LOCK) \
599*09d4459fSDaniel Fojt     glwthread_recmutex_unlock (LOCK)
600680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(LOCK) \
601*09d4459fSDaniel Fojt     glwthread_recmutex_destroy (LOCK)
602680a9cb8SJohn Marino 
603680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */
604680a9cb8SJohn Marino 
605*09d4459fSDaniel Fojt typedef glwthread_once_t gl_once_t;
606680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \
607*09d4459fSDaniel Fojt     STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
608680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
609*09d4459fSDaniel Fojt     (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
610680a9cb8SJohn Marino 
611680a9cb8SJohn Marino # ifdef __cplusplus
612680a9cb8SJohn Marino }
613680a9cb8SJohn Marino # endif
614680a9cb8SJohn Marino 
615680a9cb8SJohn Marino #endif
616680a9cb8SJohn Marino 
617680a9cb8SJohn Marino /* ========================================================================= */
618680a9cb8SJohn Marino 
619*09d4459fSDaniel Fojt #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
620680a9cb8SJohn Marino 
621680a9cb8SJohn Marino /* Provide dummy implementation if threads are not supported.  */
622680a9cb8SJohn Marino 
623680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */
624680a9cb8SJohn Marino 
625680a9cb8SJohn Marino typedef int gl_lock_t;
626680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME)
627680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME)
628680a9cb8SJohn Marino # define glthread_lock_init(NAME) 0
629680a9cb8SJohn Marino # define glthread_lock_lock(NAME) 0
630680a9cb8SJohn Marino # define glthread_lock_unlock(NAME) 0
631680a9cb8SJohn Marino # define glthread_lock_destroy(NAME) 0
632680a9cb8SJohn Marino 
633680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */
634680a9cb8SJohn Marino 
635680a9cb8SJohn Marino typedef int gl_rwlock_t;
636680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME)
637680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
638680a9cb8SJohn Marino # define glthread_rwlock_init(NAME) 0
639680a9cb8SJohn Marino # define glthread_rwlock_rdlock(NAME) 0
640680a9cb8SJohn Marino # define glthread_rwlock_wrlock(NAME) 0
641680a9cb8SJohn Marino # define glthread_rwlock_unlock(NAME) 0
642680a9cb8SJohn Marino # define glthread_rwlock_destroy(NAME) 0
643680a9cb8SJohn Marino 
644680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */
645680a9cb8SJohn Marino 
646680a9cb8SJohn Marino typedef int gl_recursive_lock_t;
647680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME)
648680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
649680a9cb8SJohn Marino # define glthread_recursive_lock_init(NAME) 0
650680a9cb8SJohn Marino # define glthread_recursive_lock_lock(NAME) 0
651680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(NAME) 0
652680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(NAME) 0
653680a9cb8SJohn Marino 
654680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */
655680a9cb8SJohn Marino 
656680a9cb8SJohn Marino typedef int gl_once_t;
657680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \
658680a9cb8SJohn Marino     STORAGECLASS gl_once_t NAME = 0;
659680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
660680a9cb8SJohn Marino     (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
661680a9cb8SJohn Marino 
662680a9cb8SJohn Marino #endif
663680a9cb8SJohn Marino 
664680a9cb8SJohn Marino /* ========================================================================= */
665680a9cb8SJohn Marino 
666680a9cb8SJohn Marino /* Macros with built-in error handling.  */
667680a9cb8SJohn Marino 
668680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */
669680a9cb8SJohn Marino 
670680a9cb8SJohn Marino #define gl_lock_init(NAME) \
671680a9cb8SJohn Marino    do                                  \
672680a9cb8SJohn Marino      {                                 \
673680a9cb8SJohn Marino        if (glthread_lock_init (&NAME)) \
674680a9cb8SJohn Marino          abort ();                     \
675680a9cb8SJohn Marino      }                                 \
676680a9cb8SJohn Marino    while (0)
677680a9cb8SJohn Marino #define gl_lock_lock(NAME) \
678680a9cb8SJohn Marino    do                                  \
679680a9cb8SJohn Marino      {                                 \
680680a9cb8SJohn Marino        if (glthread_lock_lock (&NAME)) \
681680a9cb8SJohn Marino          abort ();                     \
682680a9cb8SJohn Marino      }                                 \
683680a9cb8SJohn Marino    while (0)
684680a9cb8SJohn Marino #define gl_lock_unlock(NAME) \
685680a9cb8SJohn Marino    do                                    \
686680a9cb8SJohn Marino      {                                   \
687680a9cb8SJohn Marino        if (glthread_lock_unlock (&NAME)) \
688680a9cb8SJohn Marino          abort ();                       \
689680a9cb8SJohn Marino      }                                   \
690680a9cb8SJohn Marino    while (0)
691680a9cb8SJohn Marino #define gl_lock_destroy(NAME) \
692680a9cb8SJohn Marino    do                                     \
693680a9cb8SJohn Marino      {                                    \
694680a9cb8SJohn Marino        if (glthread_lock_destroy (&NAME)) \
695680a9cb8SJohn Marino          abort ();                        \
696680a9cb8SJohn Marino      }                                    \
697680a9cb8SJohn Marino    while (0)
698680a9cb8SJohn Marino 
699680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */
700680a9cb8SJohn Marino 
701680a9cb8SJohn Marino #define gl_rwlock_init(NAME) \
702680a9cb8SJohn Marino    do                                    \
703680a9cb8SJohn Marino      {                                   \
704680a9cb8SJohn Marino        if (glthread_rwlock_init (&NAME)) \
705680a9cb8SJohn Marino          abort ();                       \
706680a9cb8SJohn Marino      }                                   \
707680a9cb8SJohn Marino    while (0)
708680a9cb8SJohn Marino #define gl_rwlock_rdlock(NAME) \
709680a9cb8SJohn Marino    do                                      \
710680a9cb8SJohn Marino      {                                     \
711680a9cb8SJohn Marino        if (glthread_rwlock_rdlock (&NAME)) \
712680a9cb8SJohn Marino          abort ();                         \
713680a9cb8SJohn Marino      }                                     \
714680a9cb8SJohn Marino    while (0)
715680a9cb8SJohn Marino #define gl_rwlock_wrlock(NAME) \
716680a9cb8SJohn Marino    do                                      \
717680a9cb8SJohn Marino      {                                     \
718680a9cb8SJohn Marino        if (glthread_rwlock_wrlock (&NAME)) \
719680a9cb8SJohn Marino          abort ();                         \
720680a9cb8SJohn Marino      }                                     \
721680a9cb8SJohn Marino    while (0)
722680a9cb8SJohn Marino #define gl_rwlock_unlock(NAME) \
723680a9cb8SJohn Marino    do                                      \
724680a9cb8SJohn Marino      {                                     \
725680a9cb8SJohn Marino        if (glthread_rwlock_unlock (&NAME)) \
726680a9cb8SJohn Marino          abort ();                         \
727680a9cb8SJohn Marino      }                                     \
728680a9cb8SJohn Marino    while (0)
729680a9cb8SJohn Marino #define gl_rwlock_destroy(NAME) \
730680a9cb8SJohn Marino    do                                       \
731680a9cb8SJohn Marino      {                                      \
732680a9cb8SJohn Marino        if (glthread_rwlock_destroy (&NAME)) \
733680a9cb8SJohn Marino          abort ();                          \
734680a9cb8SJohn Marino      }                                      \
735680a9cb8SJohn Marino    while (0)
736680a9cb8SJohn Marino 
737680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */
738680a9cb8SJohn Marino 
739680a9cb8SJohn Marino #define gl_recursive_lock_init(NAME) \
740680a9cb8SJohn Marino    do                                            \
741680a9cb8SJohn Marino      {                                           \
742680a9cb8SJohn Marino        if (glthread_recursive_lock_init (&NAME)) \
743680a9cb8SJohn Marino          abort ();                               \
744680a9cb8SJohn Marino      }                                           \
745680a9cb8SJohn Marino    while (0)
746680a9cb8SJohn Marino #define gl_recursive_lock_lock(NAME) \
747680a9cb8SJohn Marino    do                                            \
748680a9cb8SJohn Marino      {                                           \
749680a9cb8SJohn Marino        if (glthread_recursive_lock_lock (&NAME)) \
750680a9cb8SJohn Marino          abort ();                               \
751680a9cb8SJohn Marino      }                                           \
752680a9cb8SJohn Marino    while (0)
753680a9cb8SJohn Marino #define gl_recursive_lock_unlock(NAME) \
754680a9cb8SJohn Marino    do                                              \
755680a9cb8SJohn Marino      {                                             \
756680a9cb8SJohn Marino        if (glthread_recursive_lock_unlock (&NAME)) \
757680a9cb8SJohn Marino          abort ();                                 \
758680a9cb8SJohn Marino      }                                             \
759680a9cb8SJohn Marino    while (0)
760680a9cb8SJohn Marino #define gl_recursive_lock_destroy(NAME) \
761680a9cb8SJohn Marino    do                                               \
762680a9cb8SJohn Marino      {                                              \
763680a9cb8SJohn Marino        if (glthread_recursive_lock_destroy (&NAME)) \
764680a9cb8SJohn Marino          abort ();                                  \
765680a9cb8SJohn Marino      }                                              \
766680a9cb8SJohn Marino    while (0)
767680a9cb8SJohn Marino 
768680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */
769680a9cb8SJohn Marino 
770680a9cb8SJohn Marino #define gl_once(NAME, INITFUNCTION) \
771680a9cb8SJohn Marino    do                                           \
772680a9cb8SJohn Marino      {                                          \
773680a9cb8SJohn Marino        if (glthread_once (&NAME, INITFUNCTION)) \
774680a9cb8SJohn Marino          abort ();                              \
775680a9cb8SJohn Marino      }                                          \
776680a9cb8SJohn Marino    while (0)
777680a9cb8SJohn Marino 
778680a9cb8SJohn Marino /* ========================================================================= */
779680a9cb8SJohn Marino 
780680a9cb8SJohn Marino #endif /* _LOCK_H */
781