Imported Upstream version 2.5.2p1
[debian/amanda] / gnulib / lock.h
1 /* Locking in multithreaded situations.
2    Copyright (C) 2005-2006 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 2, 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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
19    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
20    gthr-win32.h.  */
21
22 /* This file contains locking primitives for use with a given thread library.
23    It does not contain primitives for creating threads or for other
24    synchronization primitives.
25
26    Normal (non-recursive) locks:
27      Type:                gl_lock_t
28      Declaration:         gl_lock_define(extern, name)
29      Initializer:         gl_lock_define_initialized(, name)
30      Initialization:      gl_lock_init (name);
31      Taking the lock:     gl_lock_lock (name);
32      Releasing the lock:  gl_lock_unlock (name);
33      De-initialization:   gl_lock_destroy (name);
34
35    Read-Write (non-recursive) locks:
36      Type:                gl_rwlock_t
37      Declaration:         gl_rwlock_define(extern, name)
38      Initializer:         gl_rwlock_define_initialized(, name)
39      Initialization:      gl_rwlock_init (name);
40      Taking the lock:     gl_rwlock_rdlock (name);
41                           gl_rwlock_wrlock (name);
42      Releasing the lock:  gl_rwlock_unlock (name);
43      De-initialization:   gl_rwlock_destroy (name);
44
45    Recursive locks:
46      Type:                gl_recursive_lock_t
47      Declaration:         gl_recursive_lock_define(extern, name)
48      Initializer:         gl_recursive_lock_define_initialized(, name)
49      Initialization:      gl_recursive_lock_init (name);
50      Taking the lock:     gl_recursive_lock_lock (name);
51      Releasing the lock:  gl_recursive_lock_unlock (name);
52      De-initialization:   gl_recursive_lock_destroy (name);
53
54   Once-only execution:
55      Type:                gl_once_t
56      Initializer:         gl_once_define(extern, name)
57      Execution:           gl_once (name, initfunction);
58 */
59
60
61 #ifndef _LOCK_H
62 #define _LOCK_H
63
64 /* ========================================================================= */
65
66 #if USE_POSIX_THREADS
67
68 /* Use the POSIX threads library.  */
69
70 # include <pthread.h>
71 # include <stdlib.h>
72
73 # ifdef __cplusplus
74 extern "C" {
75 # endif
76
77 # if PTHREAD_IN_USE_DETECTION_HARD
78
79 /* The pthread_in_use() detection needs to be done at runtime.  */
80 #  define pthread_in_use() \
81      glthread_in_use ()
82 extern int glthread_in_use (void);
83
84 # endif
85
86 # if USE_POSIX_THREADS_WEAK
87
88 /* Use weak references to the POSIX threads library.  */
89
90 /* Weak references avoid dragging in external libraries if the other parts
91    of the program don't use them.  Here we use them, because we don't want
92    every program that uses libintl to depend on libpthread.  This assumes
93    that libpthread would not be loaded after libintl; i.e. if libintl is
94    loaded first, by an executable that does not depend on libpthread, and
95    then a module is dynamically loaded that depends on libpthread, libintl
96    will not be multithread-safe.  */
97
98 /* The way to test at runtime whether libpthread is present is to test
99    whether a function pointer's value, such as &pthread_mutex_init, is
100    non-NULL.  However, some versions of GCC have a bug through which, in
101    PIC mode, &foo != NULL always evaluates to true if there is a direct
102    call to foo(...) in the same function.  To avoid this, we test the
103    address of a function in libpthread that we don't use.  */
104
105 #  pragma weak pthread_mutex_init
106 #  pragma weak pthread_mutex_lock
107 #  pragma weak pthread_mutex_unlock
108 #  pragma weak pthread_mutex_destroy
109 #  pragma weak pthread_rwlock_init
110 #  pragma weak pthread_rwlock_rdlock
111 #  pragma weak pthread_rwlock_wrlock
112 #  pragma weak pthread_rwlock_unlock
113 #  pragma weak pthread_rwlock_destroy
114 #  pragma weak pthread_once
115 #  pragma weak pthread_cond_init
116 #  pragma weak pthread_cond_wait
117 #  pragma weak pthread_cond_signal
118 #  pragma weak pthread_cond_broadcast
119 #  pragma weak pthread_cond_destroy
120 #  pragma weak pthread_mutexattr_init
121 #  pragma weak pthread_mutexattr_settype
122 #  pragma weak pthread_mutexattr_destroy
123 #  ifndef pthread_self
124 #   pragma weak pthread_self
125 #  endif
126
127 #  if !PTHREAD_IN_USE_DETECTION_HARD
128 #   pragma weak pthread_cancel
129 #   define pthread_in_use() (pthread_cancel != NULL)
130 #  endif
131
132 # else
133
134 #  if !PTHREAD_IN_USE_DETECTION_HARD
135 #   define pthread_in_use() 1
136 #  endif
137
138 # endif
139
140 /* -------------------------- gl_lock_t datatype -------------------------- */
141
142 typedef pthread_mutex_t gl_lock_t;
143 # define gl_lock_define(STORAGECLASS, NAME) \
144     STORAGECLASS pthread_mutex_t NAME;
145 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
146     STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
147 # define gl_lock_initializer \
148     PTHREAD_MUTEX_INITIALIZER
149 # define gl_lock_init(NAME) \
150     if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
151 # define gl_lock_lock(NAME) \
152     if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
153 # define gl_lock_unlock(NAME) \
154     if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
155 # define gl_lock_destroy(NAME) \
156     if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
157
158 /* ------------------------- gl_rwlock_t datatype ------------------------- */
159
160 # if HAVE_PTHREAD_RWLOCK
161
162 #  ifdef PTHREAD_RWLOCK_INITIALIZER
163
164 typedef pthread_rwlock_t gl_rwlock_t;
165 #   define gl_rwlock_define(STORAGECLASS, NAME) \
166       STORAGECLASS pthread_rwlock_t NAME;
167 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
168       STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
169 #   define gl_rwlock_initializer \
170       PTHREAD_RWLOCK_INITIALIZER
171 #   define gl_rwlock_init(NAME) \
172       if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
173 #   define gl_rwlock_rdlock(NAME) \
174       if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
175 #   define gl_rwlock_wrlock(NAME) \
176       if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
177 #   define gl_rwlock_unlock(NAME) \
178       if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
179 #   define gl_rwlock_destroy(NAME) \
180       if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
181
182 #  else
183
184 typedef struct
185         {
186           int initialized;
187           pthread_mutex_t guard;   /* protects the initialization */
188           pthread_rwlock_t rwlock; /* read-write lock */
189         }
190         gl_rwlock_t;
191 #   define gl_rwlock_define(STORAGECLASS, NAME) \
192       STORAGECLASS gl_rwlock_t NAME;
193 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
194       STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
195 #   define gl_rwlock_initializer \
196       { 0, PTHREAD_MUTEX_INITIALIZER }
197 #   define gl_rwlock_init(NAME) \
198       if (pthread_in_use ()) glthread_rwlock_init (&NAME)
199 #   define gl_rwlock_rdlock(NAME) \
200       if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
201 #   define gl_rwlock_wrlock(NAME) \
202       if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
203 #   define gl_rwlock_unlock(NAME) \
204       if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
205 #   define gl_rwlock_destroy(NAME) \
206       if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
207 extern void glthread_rwlock_init (gl_rwlock_t *lock);
208 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
209 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
210 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
211 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
212
213 #  endif
214
215 # else
216
217 typedef struct
218         {
219           pthread_mutex_t lock; /* protects the remaining fields */
220           pthread_cond_t waiting_readers; /* waiting readers */
221           pthread_cond_t waiting_writers; /* waiting writers */
222           unsigned int waiting_writers_count; /* number of waiting writers */
223           int runcount; /* number of readers running, or -1 when a writer runs */
224         }
225         gl_rwlock_t;
226 # define gl_rwlock_define(STORAGECLASS, NAME) \
227     STORAGECLASS gl_rwlock_t NAME;
228 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
229     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
230 # define gl_rwlock_initializer \
231     { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
232 # define gl_rwlock_init(NAME) \
233     if (pthread_in_use ()) glthread_rwlock_init (&NAME)
234 # define gl_rwlock_rdlock(NAME) \
235     if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
236 # define gl_rwlock_wrlock(NAME) \
237     if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
238 # define gl_rwlock_unlock(NAME) \
239     if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
240 # define gl_rwlock_destroy(NAME) \
241     if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
242 extern void glthread_rwlock_init (gl_rwlock_t *lock);
243 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
244 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
245 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
246 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
247
248 # endif
249
250 /* --------------------- gl_recursive_lock_t datatype --------------------- */
251
252 # if HAVE_PTHREAD_MUTEX_RECURSIVE
253
254 #  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
255
256 typedef pthread_mutex_t gl_recursive_lock_t;
257 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
258       STORAGECLASS pthread_mutex_t NAME;
259 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
260       STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
261 #   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
262 #    define gl_recursive_lock_initializer \
263        PTHREAD_RECURSIVE_MUTEX_INITIALIZER
264 #   else
265 #    define gl_recursive_lock_initializer \
266        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
267 #   endif
268 #   define gl_recursive_lock_init(NAME) \
269       if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
270 #   define gl_recursive_lock_lock(NAME) \
271       if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
272 #   define gl_recursive_lock_unlock(NAME) \
273       if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
274 #   define gl_recursive_lock_destroy(NAME) \
275       if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
276
277 #  else
278
279 typedef struct
280         {
281           pthread_mutex_t recmutex; /* recursive mutex */
282           pthread_mutex_t guard;    /* protects the initialization */
283           int initialized;
284         }
285         gl_recursive_lock_t;
286 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
287       STORAGECLASS gl_recursive_lock_t NAME;
288 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
289       STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
290 #   define gl_recursive_lock_initializer \
291       { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
292 #   define gl_recursive_lock_init(NAME) \
293       if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
294 #   define gl_recursive_lock_lock(NAME) \
295       if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
296 #   define gl_recursive_lock_unlock(NAME) \
297       if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
298 #   define gl_recursive_lock_destroy(NAME) \
299       if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
300 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
301 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
302 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
303 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
304
305 #  endif
306
307 # else
308
309 /* Old versions of POSIX threads on Solaris did not have recursive locks.
310    We have to implement them ourselves.  */
311
312 typedef struct
313         {
314           pthread_mutex_t mutex;
315           pthread_t owner;
316           unsigned long depth;
317         }
318         gl_recursive_lock_t;
319 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
320      STORAGECLASS gl_recursive_lock_t NAME;
321 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
322      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
323 #  define gl_recursive_lock_initializer \
324      { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
325 #  define gl_recursive_lock_init(NAME) \
326      if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
327 #  define gl_recursive_lock_lock(NAME) \
328      if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
329 #  define gl_recursive_lock_unlock(NAME) \
330      if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
331 #  define gl_recursive_lock_destroy(NAME) \
332      if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
333 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
334 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
335 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
336 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
337
338 # endif
339
340 /* -------------------------- gl_once_t datatype -------------------------- */
341
342 typedef pthread_once_t gl_once_t;
343 # define gl_once_define(STORAGECLASS, NAME) \
344     STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
345 # define gl_once(NAME, INITFUNCTION) \
346     do                                                   \
347       {                                                  \
348         if (pthread_in_use ())                           \
349           {                                              \
350             if (pthread_once (&NAME, INITFUNCTION) != 0) \
351               abort ();                                  \
352           }                                              \
353         else                                             \
354           {                                              \
355             if (glthread_once_singlethreaded (&NAME))    \
356               INITFUNCTION ();                           \
357           }                                              \
358       }                                                  \
359     while (0)
360 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
361
362 # ifdef __cplusplus
363 }
364 # endif
365
366 #endif
367
368 /* ========================================================================= */
369
370 #if USE_PTH_THREADS
371
372 /* Use the GNU Pth threads library.  */
373
374 # include <pth.h>
375 # include <stdlib.h>
376
377 # ifdef __cplusplus
378 extern "C" {
379 # endif
380
381 # if USE_PTH_THREADS_WEAK
382
383 /* Use weak references to the GNU Pth threads library.  */
384
385 #  pragma weak pth_mutex_init
386 #  pragma weak pth_mutex_acquire
387 #  pragma weak pth_mutex_release
388 #  pragma weak pth_rwlock_init
389 #  pragma weak pth_rwlock_acquire
390 #  pragma weak pth_rwlock_release
391 #  pragma weak pth_once
392
393 #  pragma weak pth_cancel
394 #  define pth_in_use() (pth_cancel != NULL)
395
396 # else
397
398 #  define pth_in_use() 1
399
400 # endif
401
402 /* -------------------------- gl_lock_t datatype -------------------------- */
403
404 typedef pth_mutex_t gl_lock_t;
405 # define gl_lock_define(STORAGECLASS, NAME) \
406     STORAGECLASS pth_mutex_t NAME;
407 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
408     STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
409 # define gl_lock_initializer \
410     PTH_MUTEX_INIT
411 # define gl_lock_init(NAME) \
412     if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
413 # define gl_lock_lock(NAME) \
414     if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
415 # define gl_lock_unlock(NAME) \
416     if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
417 # define gl_lock_destroy(NAME) \
418     (void)(&NAME)
419
420 /* ------------------------- gl_rwlock_t datatype ------------------------- */
421
422 typedef pth_rwlock_t gl_rwlock_t;
423 #  define gl_rwlock_define(STORAGECLASS, NAME) \
424      STORAGECLASS pth_rwlock_t NAME;
425 #  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
426      STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
427 #  define gl_rwlock_initializer \
428      PTH_RWLOCK_INIT
429 #  define gl_rwlock_init(NAME) \
430      if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
431 #  define gl_rwlock_rdlock(NAME) \
432      if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
433 #  define gl_rwlock_wrlock(NAME) \
434      if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
435 #  define gl_rwlock_unlock(NAME) \
436      if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
437 #  define gl_rwlock_destroy(NAME) \
438      (void)(&NAME)
439
440 /* --------------------- gl_recursive_lock_t datatype --------------------- */
441
442 /* In Pth, mutexes are recursive by default.  */
443 typedef pth_mutex_t gl_recursive_lock_t;
444 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
445      STORAGECLASS pth_mutex_t NAME;
446 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
447      STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
448 #  define gl_recursive_lock_initializer \
449      PTH_MUTEX_INIT
450 #  define gl_recursive_lock_init(NAME) \
451      if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
452 #  define gl_recursive_lock_lock(NAME) \
453      if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
454 #  define gl_recursive_lock_unlock(NAME) \
455      if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
456 #  define gl_recursive_lock_destroy(NAME) \
457      (void)(&NAME)
458
459 /* -------------------------- gl_once_t datatype -------------------------- */
460
461 typedef pth_once_t gl_once_t;
462 # define gl_once_define(STORAGECLASS, NAME) \
463     STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
464 # define gl_once(NAME, INITFUNCTION) \
465     do                                                                \
466       {                                                               \
467         if (pth_in_use ())                                            \
468           {                                                           \
469             void (*gl_once_temp) (void) = INITFUNCTION;               \
470             if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
471               abort ();                                               \
472           }                                                           \
473         else                                                          \
474           {                                                           \
475             if (glthread_once_singlethreaded (&NAME))                 \
476               INITFUNCTION ();                                        \
477           }                                                           \
478       }                                                               \
479     while (0)
480 extern void glthread_once_call (void *arg);
481 extern int glthread_once_singlethreaded (pth_once_t *once_control);
482
483 # ifdef __cplusplus
484 }
485 # endif
486
487 #endif
488
489 /* ========================================================================= */
490
491 #if USE_SOLARIS_THREADS
492
493 /* Use the old Solaris threads library.  */
494
495 # include <thread.h>
496 # include <synch.h>
497 # include <stdlib.h>
498
499 # ifdef __cplusplus
500 extern "C" {
501 # endif
502
503 # if USE_SOLARIS_THREADS_WEAK
504
505 /* Use weak references to the old Solaris threads library.  */
506
507 #  pragma weak mutex_init
508 #  pragma weak mutex_lock
509 #  pragma weak mutex_unlock
510 #  pragma weak mutex_destroy
511 #  pragma weak rwlock_init
512 #  pragma weak rw_rdlock
513 #  pragma weak rw_wrlock
514 #  pragma weak rw_unlock
515 #  pragma weak rwlock_destroy
516 #  pragma weak thr_self
517
518 #  pragma weak thr_suspend
519 #  define thread_in_use() (thr_suspend != NULL)
520
521 # else
522
523 #  define thread_in_use() 1
524
525 # endif
526
527 /* -------------------------- gl_lock_t datatype -------------------------- */
528
529 typedef mutex_t gl_lock_t;
530 # define gl_lock_define(STORAGECLASS, NAME) \
531     STORAGECLASS mutex_t NAME;
532 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
533     STORAGECLASS mutex_t NAME = gl_lock_initializer;
534 # define gl_lock_initializer \
535     DEFAULTMUTEX
536 # define gl_lock_init(NAME) \
537     if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
538 # define gl_lock_lock(NAME) \
539     if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
540 # define gl_lock_unlock(NAME) \
541     if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
542 # define gl_lock_destroy(NAME) \
543     if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
544
545 /* ------------------------- gl_rwlock_t datatype ------------------------- */
546
547 typedef rwlock_t gl_rwlock_t;
548 # define gl_rwlock_define(STORAGECLASS, NAME) \
549     STORAGECLASS rwlock_t NAME;
550 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
551     STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
552 # define gl_rwlock_initializer \
553     DEFAULTRWLOCK
554 # define gl_rwlock_init(NAME) \
555     if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
556 # define gl_rwlock_rdlock(NAME) \
557     if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
558 # define gl_rwlock_wrlock(NAME) \
559     if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
560 # define gl_rwlock_unlock(NAME) \
561     if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
562 # define gl_rwlock_destroy(NAME) \
563     if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
564
565 /* --------------------- gl_recursive_lock_t datatype --------------------- */
566
567 /* Old Solaris threads did not have recursive locks.
568    We have to implement them ourselves.  */
569
570 typedef struct
571         {
572           mutex_t mutex;
573           thread_t owner;
574           unsigned long depth;
575         }
576         gl_recursive_lock_t;
577 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
578     STORAGECLASS gl_recursive_lock_t NAME;
579 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
580     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
581 # define gl_recursive_lock_initializer \
582     { DEFAULTMUTEX, (thread_t) 0, 0 }
583 # define gl_recursive_lock_init(NAME) \
584     if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
585 # define gl_recursive_lock_lock(NAME) \
586     if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
587 # define gl_recursive_lock_unlock(NAME) \
588     if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
589 # define gl_recursive_lock_destroy(NAME) \
590     if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
591 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
592 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
593 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
594 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
595
596 /* -------------------------- gl_once_t datatype -------------------------- */
597
598 typedef struct
599         {
600           volatile int inited;
601           mutex_t mutex;
602         }
603         gl_once_t;
604 # define gl_once_define(STORAGECLASS, NAME) \
605     STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
606 # define gl_once(NAME, INITFUNCTION) \
607     do                                                \
608       {                                               \
609         if (thread_in_use ())                         \
610           {                                           \
611             glthread_once (&NAME, INITFUNCTION);      \
612           }                                           \
613         else                                          \
614           {                                           \
615             if (glthread_once_singlethreaded (&NAME)) \
616               INITFUNCTION ();                        \
617           }                                           \
618       }                                               \
619     while (0)
620 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
621 extern int glthread_once_singlethreaded (gl_once_t *once_control);
622
623 # ifdef __cplusplus
624 }
625 # endif
626
627 #endif
628
629 /* ========================================================================= */
630
631 #if USE_WIN32_THREADS
632
633 # include <windows.h>
634
635 # ifdef __cplusplus
636 extern "C" {
637 # endif
638
639 /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
640    Semaphore types, because
641      - we need only to synchronize inside a single process (address space),
642        not inter-process locking,
643      - we don't need to support trylock operations.  (TryEnterCriticalSection
644        does not work on Windows 95/98/ME.  Packages that need trylock usually
645        define their own mutex type.)  */
646
647 /* There is no way to statically initialize a CRITICAL_SECTION.  It needs
648    to be done lazily, once only.  For this we need spinlocks.  */
649
650 typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
651
652 /* -------------------------- gl_lock_t datatype -------------------------- */
653
654 typedef struct
655         {
656           gl_spinlock_t guard; /* protects the initialization */
657           CRITICAL_SECTION lock;
658         }
659         gl_lock_t;
660 # define gl_lock_define(STORAGECLASS, NAME) \
661     STORAGECLASS gl_lock_t NAME;
662 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
663     STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
664 # define gl_lock_initializer \
665     { { 0, -1 } }
666 # define gl_lock_init(NAME) \
667     glthread_lock_init (&NAME)
668 # define gl_lock_lock(NAME) \
669     glthread_lock_lock (&NAME)
670 # define gl_lock_unlock(NAME) \
671     glthread_lock_unlock (&NAME)
672 # define gl_lock_destroy(NAME) \
673     glthread_lock_destroy (&NAME)
674 extern void glthread_lock_init (gl_lock_t *lock);
675 extern void glthread_lock_lock (gl_lock_t *lock);
676 extern void glthread_lock_unlock (gl_lock_t *lock);
677 extern void glthread_lock_destroy (gl_lock_t *lock);
678
679 /* ------------------------- gl_rwlock_t datatype ------------------------- */
680
681 /* It is impossible to implement read-write locks using plain locks, without
682    introducing an extra thread dedicated to managing read-write locks.
683    Therefore here we need to use the low-level Event type.  */
684
685 typedef struct
686         {
687           HANDLE *array; /* array of waiting threads, each represented by an event */
688           unsigned int count; /* number of waiting threads */
689           unsigned int alloc; /* length of allocated array */
690           unsigned int offset; /* index of first waiting thread in array */
691         }
692         gl_waitqueue_t;
693 typedef struct
694         {
695           gl_spinlock_t guard; /* protects the initialization */
696           CRITICAL_SECTION lock; /* protects the remaining fields */
697           gl_waitqueue_t waiting_readers; /* waiting readers */
698           gl_waitqueue_t waiting_writers; /* waiting writers */
699           int runcount; /* number of readers running, or -1 when a writer runs */
700         }
701         gl_rwlock_t;
702 # define gl_rwlock_define(STORAGECLASS, NAME) \
703     STORAGECLASS gl_rwlock_t NAME;
704 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
705     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
706 # define gl_rwlock_initializer \
707     { { 0, -1 } }
708 # define gl_rwlock_init(NAME) \
709     glthread_rwlock_init (&NAME)
710 # define gl_rwlock_rdlock(NAME) \
711     glthread_rwlock_rdlock (&NAME)
712 # define gl_rwlock_wrlock(NAME) \
713     glthread_rwlock_wrlock (&NAME)
714 # define gl_rwlock_unlock(NAME) \
715     glthread_rwlock_unlock (&NAME)
716 # define gl_rwlock_destroy(NAME) \
717     glthread_rwlock_destroy (&NAME)
718 extern void glthread_rwlock_init (gl_rwlock_t *lock);
719 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
720 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
721 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
722 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
723
724 /* --------------------- gl_recursive_lock_t datatype --------------------- */
725
726 /* The Win32 documentation says that CRITICAL_SECTION already implements a
727    recursive lock.  But we need not rely on it: It's easy to implement a
728    recursive lock without this assumption.  */
729
730 typedef struct
731         {
732           gl_spinlock_t guard; /* protects the initialization */
733           DWORD owner;
734           unsigned long depth;
735           CRITICAL_SECTION lock;
736         }
737         gl_recursive_lock_t;
738 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
739     STORAGECLASS gl_recursive_lock_t NAME;
740 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
741     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
742 # define gl_recursive_lock_initializer \
743     { { 0, -1 }, 0, 0 }
744 # define gl_recursive_lock_init(NAME) \
745     glthread_recursive_lock_init (&NAME)
746 # define gl_recursive_lock_lock(NAME) \
747     glthread_recursive_lock_lock (&NAME)
748 # define gl_recursive_lock_unlock(NAME) \
749     glthread_recursive_lock_unlock (&NAME)
750 # define gl_recursive_lock_destroy(NAME) \
751     glthread_recursive_lock_destroy (&NAME)
752 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
753 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
754 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
755 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
756
757 /* -------------------------- gl_once_t datatype -------------------------- */
758
759 typedef struct
760         {
761           volatile int inited;
762           volatile long started;
763           CRITICAL_SECTION lock;
764         }
765         gl_once_t;
766 # define gl_once_define(STORAGECLASS, NAME) \
767     STORAGECLASS gl_once_t NAME = { -1, -1 };
768 # define gl_once(NAME, INITFUNCTION) \
769     glthread_once (&NAME, INITFUNCTION)
770 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
771
772 # ifdef __cplusplus
773 }
774 # endif
775
776 #endif
777
778 /* ========================================================================= */
779
780 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
781
782 /* Provide dummy implementation if threads are not supported.  */
783
784 /* -------------------------- gl_lock_t datatype -------------------------- */
785
786 typedef int gl_lock_t;
787 # define gl_lock_define(STORAGECLASS, NAME)
788 # define gl_lock_define_initialized(STORAGECLASS, NAME)
789 # define gl_lock_init(NAME)
790 # define gl_lock_lock(NAME)
791 # define gl_lock_unlock(NAME)
792
793 /* ------------------------- gl_rwlock_t datatype ------------------------- */
794
795 typedef int gl_rwlock_t;
796 # define gl_rwlock_define(STORAGECLASS, NAME)
797 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
798 # define gl_rwlock_init(NAME)
799 # define gl_rwlock_rdlock(NAME)
800 # define gl_rwlock_wrlock(NAME)
801 # define gl_rwlock_unlock(NAME)
802
803 /* --------------------- gl_recursive_lock_t datatype --------------------- */
804
805 typedef int gl_recursive_lock_t;
806 # define gl_recursive_lock_define(STORAGECLASS, NAME)
807 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
808 # define gl_recursive_lock_init(NAME)
809 # define gl_recursive_lock_lock(NAME)
810 # define gl_recursive_lock_unlock(NAME)
811
812 /* -------------------------- gl_once_t datatype -------------------------- */
813
814 typedef int gl_once_t;
815 # define gl_once_define(STORAGECLASS, NAME) \
816     STORAGECLASS gl_once_t NAME = 0;
817 # define gl_once(NAME, INITFUNCTION) \
818     do                       \
819       {                      \
820         if (NAME == 0)       \
821           {                  \
822             NAME = ~ 0;      \
823             INITFUNCTION (); \
824           }                  \
825       }                      \
826     while (0)
827
828 #endif
829
830 /* ========================================================================= */
831
832 #endif /* _LOCK_H */