vendor/grep: upgrade from 2.22 to 3.4
[dragonfly.git] / contrib / grep / lib / glthread / lock.h
1 /* Locking in multithreaded situations.
2    Copyright (C) 2005-2020 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8
9    This program 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 General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
18    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
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
83 #if !defined c11_threads_in_use
84 # if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
85 #  include <threads.h>
86 #  pragma weak thrd_exit
87 #  define c11_threads_in_use() (thrd_exit != NULL)
88 # else
89 #  define c11_threads_in_use() 0
90 # endif
91 #endif
92
93 /* ========================================================================= */
94
95 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
96
97 /* Use the ISO C threads library.  */
98
99 # include <threads.h>
100
101 # ifdef __cplusplus
102 extern "C" {
103 # endif
104
105 /* -------------------------- gl_lock_t datatype -------------------------- */
106
107 typedef struct
108         {
109           int volatile init_needed;
110           once_flag init_once;
111           void (*init_func) (void);
112           mtx_t mutex;
113         }
114         gl_lock_t;
115 # define gl_lock_define(STORAGECLASS, NAME) \
116     STORAGECLASS gl_lock_t NAME;
117 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
118     static void _atomic_init_##NAME (void);       \
119     STORAGECLASS gl_lock_t NAME =                 \
120       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
121     static void _atomic_init_##NAME (void)        \
122     {                                             \
123       if (glthread_lock_init (&(NAME)))           \
124         abort ();                                 \
125     }
126 extern int glthread_lock_init (gl_lock_t *lock);
127 extern int glthread_lock_lock (gl_lock_t *lock);
128 extern int glthread_lock_unlock (gl_lock_t *lock);
129 extern int glthread_lock_destroy (gl_lock_t *lock);
130
131 /* ------------------------- gl_rwlock_t datatype ------------------------- */
132
133 typedef struct
134         {
135           int volatile init_needed;
136           once_flag init_once;
137           void (*init_func) (void);
138           mtx_t lock; /* protects the remaining fields */
139           cnd_t waiting_readers; /* waiting readers */
140           cnd_t waiting_writers; /* waiting writers */
141           unsigned int waiting_writers_count; /* number of waiting writers */
142           int runcount; /* number of readers running, or -1 when a writer runs */
143         }
144         gl_rwlock_t;
145 # define gl_rwlock_define(STORAGECLASS, NAME) \
146     STORAGECLASS gl_rwlock_t NAME;
147 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
148     static void _atomic_init_##NAME (void);       \
149     STORAGECLASS gl_rwlock_t NAME =               \
150       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
151     static void _atomic_init_##NAME (void)        \
152     {                                             \
153       if (glthread_rwlock_init (&(NAME)))         \
154         abort ();                                 \
155     }
156 extern int glthread_rwlock_init (gl_rwlock_t *lock);
157 extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
158 extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
159 extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
160 extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
161
162 /* --------------------- gl_recursive_lock_t datatype --------------------- */
163
164 typedef struct
165         {
166           int volatile init_needed;
167           once_flag init_once;
168           void (*init_func) (void);
169           mtx_t mutex;
170         }
171         gl_recursive_lock_t;
172 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
173     STORAGECLASS gl_recursive_lock_t NAME;
174 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
175     static void _atomic_init_##NAME (void);       \
176     STORAGECLASS gl_recursive_lock_t NAME =       \
177       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
178     static void _atomic_init_##NAME (void)        \
179     {                                             \
180       if (glthread_recursive_lock_init (&(NAME))) \
181         abort ();                                 \
182     }
183 extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
184 extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
185 extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
186 extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
187
188 /* -------------------------- gl_once_t datatype -------------------------- */
189
190 typedef once_flag gl_once_t;
191 # define gl_once_define(STORAGECLASS, NAME) \
192     STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
193 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
194     (call_once (ONCE_CONTROL, INITFUNCTION), 0)
195
196 # ifdef __cplusplus
197 }
198 # endif
199
200 #endif
201
202 /* ========================================================================= */
203
204 #if USE_POSIX_THREADS
205
206 /* Use the POSIX threads library.  */
207
208 # include <pthread.h>
209
210 # ifdef __cplusplus
211 extern "C" {
212 # endif
213
214 # if PTHREAD_IN_USE_DETECTION_HARD
215
216 /* The pthread_in_use() detection needs to be done at runtime.  */
217 #  define pthread_in_use() \
218      glthread_in_use ()
219 extern int glthread_in_use (void);
220
221 # endif
222
223 # if USE_POSIX_THREADS_WEAK
224
225 /* Use weak references to the POSIX threads library.  */
226
227 /* Weak references avoid dragging in external libraries if the other parts
228    of the program don't use them.  Here we use them, because we don't want
229    every program that uses libintl to depend on libpthread.  This assumes
230    that libpthread would not be loaded after libintl; i.e. if libintl is
231    loaded first, by an executable that does not depend on libpthread, and
232    then a module is dynamically loaded that depends on libpthread, libintl
233    will not be multithread-safe.  */
234
235 /* The way to test at runtime whether libpthread is present is to test
236    whether a function pointer's value, such as &pthread_mutex_init, is
237    non-NULL.  However, some versions of GCC have a bug through which, in
238    PIC mode, &foo != NULL always evaluates to true if there is a direct
239    call to foo(...) in the same function.  To avoid this, we test the
240    address of a function in libpthread that we don't use.  */
241
242 #  pragma weak pthread_mutex_init
243 #  pragma weak pthread_mutex_lock
244 #  pragma weak pthread_mutex_unlock
245 #  pragma weak pthread_mutex_destroy
246 #  pragma weak pthread_rwlock_init
247 #  pragma weak pthread_rwlock_rdlock
248 #  pragma weak pthread_rwlock_wrlock
249 #  pragma weak pthread_rwlock_unlock
250 #  pragma weak pthread_rwlock_destroy
251 #  pragma weak pthread_once
252 #  pragma weak pthread_cond_init
253 #  pragma weak pthread_cond_wait
254 #  pragma weak pthread_cond_signal
255 #  pragma weak pthread_cond_broadcast
256 #  pragma weak pthread_cond_destroy
257 #  pragma weak pthread_mutexattr_init
258 #  pragma weak pthread_mutexattr_settype
259 #  pragma weak pthread_mutexattr_destroy
260 #  pragma weak pthread_rwlockattr_init
261 #  if __GNU_LIBRARY__ > 1
262 #   pragma weak pthread_rwlockattr_setkind_np
263 #  endif
264 #  pragma weak pthread_rwlockattr_destroy
265 #  ifndef pthread_self
266 #   pragma weak pthread_self
267 #  endif
268
269 #  if !PTHREAD_IN_USE_DETECTION_HARD
270     /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
271        can be used to determine whether libpthread is in use.  These are:
272          pthread_mutexattr_gettype
273          pthread_rwlockattr_destroy
274          pthread_rwlockattr_init
275      */
276 #   pragma weak pthread_mutexattr_gettype
277 #   define pthread_in_use() \
278       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
279 #  endif
280
281 # else
282
283 #  if !PTHREAD_IN_USE_DETECTION_HARD
284 #   define pthread_in_use() 1
285 #  endif
286
287 # endif
288
289 /* -------------------------- gl_lock_t datatype -------------------------- */
290
291 typedef pthread_mutex_t gl_lock_t;
292 # define gl_lock_define(STORAGECLASS, NAME) \
293     STORAGECLASS pthread_mutex_t NAME;
294 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
295     STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
296 # define gl_lock_initializer \
297     PTHREAD_MUTEX_INITIALIZER
298 # define glthread_lock_init(LOCK) \
299     (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
300 # define glthread_lock_lock(LOCK) \
301     (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
302 # define glthread_lock_unlock(LOCK) \
303     (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
304 # define glthread_lock_destroy(LOCK) \
305     (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
306
307 /* ------------------------- gl_rwlock_t datatype ------------------------- */
308
309 # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
310
311 #  if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
312
313 typedef pthread_rwlock_t gl_rwlock_t;
314 #   define gl_rwlock_define(STORAGECLASS, NAME) \
315       STORAGECLASS pthread_rwlock_t NAME;
316 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
317       STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
318 #   if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
319 #    if defined PTHREAD_RWLOCK_INITIALIZER
320 #     define gl_rwlock_initializer \
321         PTHREAD_RWLOCK_INITIALIZER
322 #    else
323 #     define gl_rwlock_initializer \
324         PTHREAD_RWLOCK_INITIALIZER_NP
325 #    endif
326 #    define glthread_rwlock_init(LOCK) \
327        (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
328 #   else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
329 #    define gl_rwlock_initializer \
330        PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
331 #    define glthread_rwlock_init(LOCK) \
332        (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
333 extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
334 #   endif
335 #   define glthread_rwlock_rdlock(LOCK) \
336       (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
337 #   define glthread_rwlock_wrlock(LOCK) \
338       (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
339 #   define glthread_rwlock_unlock(LOCK) \
340       (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
341 #   define glthread_rwlock_destroy(LOCK) \
342       (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
343
344 #  else
345
346 typedef struct
347         {
348           int initialized;
349           pthread_mutex_t guard;   /* protects the initialization */
350           pthread_rwlock_t rwlock; /* read-write lock */
351         }
352         gl_rwlock_t;
353 #   define gl_rwlock_define(STORAGECLASS, NAME) \
354       STORAGECLASS gl_rwlock_t NAME;
355 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
356       STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
357 #   define gl_rwlock_initializer \
358       { 0, PTHREAD_MUTEX_INITIALIZER }
359 #   define glthread_rwlock_init(LOCK) \
360       (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
361 #   define glthread_rwlock_rdlock(LOCK) \
362       (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
363 #   define glthread_rwlock_wrlock(LOCK) \
364       (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
365 #   define glthread_rwlock_unlock(LOCK) \
366       (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
367 #   define glthread_rwlock_destroy(LOCK) \
368       (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
369 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
370 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
371 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
372 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
373 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
374
375 #  endif
376
377 # else
378
379 typedef struct
380         {
381           pthread_mutex_t lock; /* protects the remaining fields */
382           pthread_cond_t waiting_readers; /* waiting readers */
383           pthread_cond_t waiting_writers; /* waiting writers */
384           unsigned int waiting_writers_count; /* number of waiting writers */
385           int runcount; /* number of readers running, or -1 when a writer runs */
386         }
387         gl_rwlock_t;
388 # define gl_rwlock_define(STORAGECLASS, NAME) \
389     STORAGECLASS gl_rwlock_t NAME;
390 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
391     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
392 # define gl_rwlock_initializer \
393     { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
394 # define glthread_rwlock_init(LOCK) \
395     (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
396 # define glthread_rwlock_rdlock(LOCK) \
397     (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
398 # define glthread_rwlock_wrlock(LOCK) \
399     (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
400 # define glthread_rwlock_unlock(LOCK) \
401     (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
402 # define glthread_rwlock_destroy(LOCK) \
403     (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
404 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
405 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
406 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
407 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
408 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
409
410 # endif
411
412 /* --------------------- gl_recursive_lock_t datatype --------------------- */
413
414 # if HAVE_PTHREAD_MUTEX_RECURSIVE
415
416 #  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
417
418 typedef pthread_mutex_t gl_recursive_lock_t;
419 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
420       STORAGECLASS pthread_mutex_t NAME;
421 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
422       STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
423 #   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
424 #    define gl_recursive_lock_initializer \
425        PTHREAD_RECURSIVE_MUTEX_INITIALIZER
426 #   else
427 #    define gl_recursive_lock_initializer \
428        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
429 #   endif
430 #   define glthread_recursive_lock_init(LOCK) \
431       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
432 #   define glthread_recursive_lock_lock(LOCK) \
433       (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
434 #   define glthread_recursive_lock_unlock(LOCK) \
435       (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
436 #   define glthread_recursive_lock_destroy(LOCK) \
437       (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
438 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
439
440 #  else
441
442 typedef struct
443         {
444           pthread_mutex_t recmutex; /* recursive mutex */
445           pthread_mutex_t guard;    /* protects the initialization */
446           int initialized;
447         }
448         gl_recursive_lock_t;
449 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
450       STORAGECLASS gl_recursive_lock_t NAME;
451 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
452       STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
453 #   define gl_recursive_lock_initializer \
454       { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
455 #   define glthread_recursive_lock_init(LOCK) \
456       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
457 #   define glthread_recursive_lock_lock(LOCK) \
458       (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
459 #   define glthread_recursive_lock_unlock(LOCK) \
460       (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
461 #   define glthread_recursive_lock_destroy(LOCK) \
462       (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
463 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
464 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
465 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
466 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
467
468 #  endif
469
470 # else
471
472 /* Old versions of POSIX threads on Solaris did not have recursive locks.
473    We have to implement them ourselves.  */
474
475 typedef struct
476         {
477           pthread_mutex_t mutex;
478           pthread_t owner;
479           unsigned long depth;
480         }
481         gl_recursive_lock_t;
482 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
483      STORAGECLASS gl_recursive_lock_t NAME;
484 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
485      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
486 #  define gl_recursive_lock_initializer \
487      { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
488 #  define glthread_recursive_lock_init(LOCK) \
489      (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
490 #  define glthread_recursive_lock_lock(LOCK) \
491      (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
492 #  define glthread_recursive_lock_unlock(LOCK) \
493      (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
494 #  define glthread_recursive_lock_destroy(LOCK) \
495      (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
496 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
497 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
498 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
499 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
500
501 # endif
502
503 /* -------------------------- gl_once_t datatype -------------------------- */
504
505 typedef pthread_once_t gl_once_t;
506 # define gl_once_define(STORAGECLASS, NAME) \
507     STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
508 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
509     (pthread_in_use ()                                                         \
510      ? pthread_once (ONCE_CONTROL, INITFUNCTION)                               \
511      : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
512 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
513
514 # ifdef __cplusplus
515 }
516 # endif
517
518 #endif
519
520 /* ========================================================================= */
521
522 #if USE_WINDOWS_THREADS
523
524 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
525 # include <windows.h>
526
527 # include "windows-mutex.h"
528 # include "windows-rwlock.h"
529 # include "windows-recmutex.h"
530 # include "windows-once.h"
531
532 # ifdef __cplusplus
533 extern "C" {
534 # endif
535
536 /* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
537    Mutex, Semaphore types, because
538      - we need only to synchronize inside a single process (address space),
539        not inter-process locking,
540      - we don't need to support trylock operations.  (TryEnterCriticalSection
541        does not work on Windows 95/98/ME.  Packages that need trylock usually
542        define their own mutex type.)  */
543
544 /* There is no way to statically initialize a CRITICAL_SECTION.  It needs
545    to be done lazily, once only.  For this we need spinlocks.  */
546
547 /* -------------------------- gl_lock_t datatype -------------------------- */
548
549 typedef glwthread_mutex_t gl_lock_t;
550 # define gl_lock_define(STORAGECLASS, NAME) \
551     STORAGECLASS gl_lock_t NAME;
552 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
553     STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
554 # define gl_lock_initializer \
555     GLWTHREAD_MUTEX_INIT
556 # define glthread_lock_init(LOCK) \
557     (glwthread_mutex_init (LOCK), 0)
558 # define glthread_lock_lock(LOCK) \
559     glwthread_mutex_lock (LOCK)
560 # define glthread_lock_unlock(LOCK) \
561     glwthread_mutex_unlock (LOCK)
562 # define glthread_lock_destroy(LOCK) \
563     glwthread_mutex_destroy (LOCK)
564
565 /* ------------------------- gl_rwlock_t datatype ------------------------- */
566
567 typedef glwthread_rwlock_t gl_rwlock_t;
568 # define gl_rwlock_define(STORAGECLASS, NAME) \
569     STORAGECLASS gl_rwlock_t NAME;
570 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
571     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
572 # define gl_rwlock_initializer \
573     GLWTHREAD_RWLOCK_INIT
574 # define glthread_rwlock_init(LOCK) \
575     (glwthread_rwlock_init (LOCK), 0)
576 # define glthread_rwlock_rdlock(LOCK) \
577     glwthread_rwlock_rdlock (LOCK)
578 # define glthread_rwlock_wrlock(LOCK) \
579     glwthread_rwlock_wrlock (LOCK)
580 # define glthread_rwlock_unlock(LOCK) \
581     glwthread_rwlock_unlock (LOCK)
582 # define glthread_rwlock_destroy(LOCK) \
583     glwthread_rwlock_destroy (LOCK)
584
585 /* --------------------- gl_recursive_lock_t datatype --------------------- */
586
587 typedef glwthread_recmutex_t gl_recursive_lock_t;
588 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
589     STORAGECLASS gl_recursive_lock_t NAME;
590 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
591     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
592 # define gl_recursive_lock_initializer \
593     GLWTHREAD_RECMUTEX_INIT
594 # define glthread_recursive_lock_init(LOCK) \
595     (glwthread_recmutex_init (LOCK), 0)
596 # define glthread_recursive_lock_lock(LOCK) \
597     glwthread_recmutex_lock (LOCK)
598 # define glthread_recursive_lock_unlock(LOCK) \
599     glwthread_recmutex_unlock (LOCK)
600 # define glthread_recursive_lock_destroy(LOCK) \
601     glwthread_recmutex_destroy (LOCK)
602
603 /* -------------------------- gl_once_t datatype -------------------------- */
604
605 typedef glwthread_once_t gl_once_t;
606 # define gl_once_define(STORAGECLASS, NAME) \
607     STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
608 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
609     (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
610
611 # ifdef __cplusplus
612 }
613 # endif
614
615 #endif
616
617 /* ========================================================================= */
618
619 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
620
621 /* Provide dummy implementation if threads are not supported.  */
622
623 /* -------------------------- gl_lock_t datatype -------------------------- */
624
625 typedef int gl_lock_t;
626 # define gl_lock_define(STORAGECLASS, NAME)
627 # define gl_lock_define_initialized(STORAGECLASS, NAME)
628 # define glthread_lock_init(NAME) 0
629 # define glthread_lock_lock(NAME) 0
630 # define glthread_lock_unlock(NAME) 0
631 # define glthread_lock_destroy(NAME) 0
632
633 /* ------------------------- gl_rwlock_t datatype ------------------------- */
634
635 typedef int gl_rwlock_t;
636 # define gl_rwlock_define(STORAGECLASS, NAME)
637 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
638 # define glthread_rwlock_init(NAME) 0
639 # define glthread_rwlock_rdlock(NAME) 0
640 # define glthread_rwlock_wrlock(NAME) 0
641 # define glthread_rwlock_unlock(NAME) 0
642 # define glthread_rwlock_destroy(NAME) 0
643
644 /* --------------------- gl_recursive_lock_t datatype --------------------- */
645
646 typedef int gl_recursive_lock_t;
647 # define gl_recursive_lock_define(STORAGECLASS, NAME)
648 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
649 # define glthread_recursive_lock_init(NAME) 0
650 # define glthread_recursive_lock_lock(NAME) 0
651 # define glthread_recursive_lock_unlock(NAME) 0
652 # define glthread_recursive_lock_destroy(NAME) 0
653
654 /* -------------------------- gl_once_t datatype -------------------------- */
655
656 typedef int gl_once_t;
657 # define gl_once_define(STORAGECLASS, NAME) \
658     STORAGECLASS gl_once_t NAME = 0;
659 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
660     (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
661
662 #endif
663
664 /* ========================================================================= */
665
666 /* Macros with built-in error handling.  */
667
668 /* -------------------------- gl_lock_t datatype -------------------------- */
669
670 #define gl_lock_init(NAME) \
671    do                                  \
672      {                                 \
673        if (glthread_lock_init (&NAME)) \
674          abort ();                     \
675      }                                 \
676    while (0)
677 #define gl_lock_lock(NAME) \
678    do                                  \
679      {                                 \
680        if (glthread_lock_lock (&NAME)) \
681          abort ();                     \
682      }                                 \
683    while (0)
684 #define gl_lock_unlock(NAME) \
685    do                                    \
686      {                                   \
687        if (glthread_lock_unlock (&NAME)) \
688          abort ();                       \
689      }                                   \
690    while (0)
691 #define gl_lock_destroy(NAME) \
692    do                                     \
693      {                                    \
694        if (glthread_lock_destroy (&NAME)) \
695          abort ();                        \
696      }                                    \
697    while (0)
698
699 /* ------------------------- gl_rwlock_t datatype ------------------------- */
700
701 #define gl_rwlock_init(NAME) \
702    do                                    \
703      {                                   \
704        if (glthread_rwlock_init (&NAME)) \
705          abort ();                       \
706      }                                   \
707    while (0)
708 #define gl_rwlock_rdlock(NAME) \
709    do                                      \
710      {                                     \
711        if (glthread_rwlock_rdlock (&NAME)) \
712          abort ();                         \
713      }                                     \
714    while (0)
715 #define gl_rwlock_wrlock(NAME) \
716    do                                      \
717      {                                     \
718        if (glthread_rwlock_wrlock (&NAME)) \
719          abort ();                         \
720      }                                     \
721    while (0)
722 #define gl_rwlock_unlock(NAME) \
723    do                                      \
724      {                                     \
725        if (glthread_rwlock_unlock (&NAME)) \
726          abort ();                         \
727      }                                     \
728    while (0)
729 #define gl_rwlock_destroy(NAME) \
730    do                                       \
731      {                                      \
732        if (glthread_rwlock_destroy (&NAME)) \
733          abort ();                          \
734      }                                      \
735    while (0)
736
737 /* --------------------- gl_recursive_lock_t datatype --------------------- */
738
739 #define gl_recursive_lock_init(NAME) \
740    do                                            \
741      {                                           \
742        if (glthread_recursive_lock_init (&NAME)) \
743          abort ();                               \
744      }                                           \
745    while (0)
746 #define gl_recursive_lock_lock(NAME) \
747    do                                            \
748      {                                           \
749        if (glthread_recursive_lock_lock (&NAME)) \
750          abort ();                               \
751      }                                           \
752    while (0)
753 #define gl_recursive_lock_unlock(NAME) \
754    do                                              \
755      {                                             \
756        if (glthread_recursive_lock_unlock (&NAME)) \
757          abort ();                                 \
758      }                                             \
759    while (0)
760 #define gl_recursive_lock_destroy(NAME) \
761    do                                               \
762      {                                              \
763        if (glthread_recursive_lock_destroy (&NAME)) \
764          abort ();                                  \
765      }                                              \
766    while (0)
767
768 /* -------------------------- gl_once_t datatype -------------------------- */
769
770 #define gl_once(NAME, INITFUNCTION) \
771    do                                           \
772      {                                          \
773        if (glthread_once (&NAME, INITFUNCTION)) \
774          abort ();                              \
775      }                                          \
776    while (0)
777
778 /* ========================================================================= */
779
780 #endif /* _LOCK_H */