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