• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* Locking in multithreaded situations.
2   Copyright (C) 2005-2007 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
74extern "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 ()
82extern 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
142typedef 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    do                                                                  \
151      {                                                                 \
152        if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
153          abort ();                                                     \
154      }                                                                 \
155    while (0)
156# define gl_lock_lock(NAME) \
157    do                                                            \
158      {                                                           \
159        if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
160          abort ();                                               \
161      }                                                           \
162    while (0)
163# define gl_lock_unlock(NAME) \
164    do                                                              \
165      {                                                             \
166        if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
167          abort ();                                                 \
168      }                                                             \
169    while (0)
170# define gl_lock_destroy(NAME) \
171    do                                                               \
172      {                                                              \
173        if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
174          abort ();                                                  \
175      }                                                              \
176    while (0)
177
178/* ------------------------- gl_rwlock_t datatype ------------------------- */
179
180# if HAVE_PTHREAD_RWLOCK
181
182#  ifdef PTHREAD_RWLOCK_INITIALIZER
183
184typedef pthread_rwlock_t gl_rwlock_t;
185#   define gl_rwlock_define(STORAGECLASS, NAME) \
186      STORAGECLASS pthread_rwlock_t NAME;
187#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
188      STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
189#   define gl_rwlock_initializer \
190      PTHREAD_RWLOCK_INITIALIZER
191#   define gl_rwlock_init(NAME) \
192      do                                                                   \
193        {                                                                  \
194          if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \
195            abort ();                                                      \
196        }                                                                  \
197      while (0)
198#   define gl_rwlock_rdlock(NAME) \
199      do                                                               \
200        {                                                              \
201          if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \
202            abort ();                                                  \
203        }                                                              \
204      while (0)
205#   define gl_rwlock_wrlock(NAME) \
206      do                                                               \
207        {                                                              \
208          if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \
209            abort ();                                                  \
210        }                                                              \
211      while (0)
212#   define gl_rwlock_unlock(NAME) \
213      do                                                               \
214        {                                                              \
215          if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \
216            abort ();                                                  \
217        }                                                              \
218      while (0)
219#   define gl_rwlock_destroy(NAME) \
220      do                                                                \
221        {                                                               \
222          if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \
223            abort ();                                                   \
224        }                                                               \
225      while (0)
226
227#  else
228
229typedef struct
230        {
231          int initialized;
232          pthread_mutex_t guard;   /* protects the initialization */
233          pthread_rwlock_t rwlock; /* read-write lock */
234        }
235        gl_rwlock_t;
236#   define gl_rwlock_define(STORAGECLASS, NAME) \
237      STORAGECLASS gl_rwlock_t NAME;
238#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
239      STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
240#   define gl_rwlock_initializer \
241      { 0, PTHREAD_MUTEX_INITIALIZER }
242#   define gl_rwlock_init(NAME) \
243      do                                  \
244        {                                 \
245          if (pthread_in_use ())          \
246            glthread_rwlock_init (&NAME); \
247        }                                 \
248      while (0)
249#   define gl_rwlock_rdlock(NAME) \
250      do                                    \
251        {                                   \
252          if (pthread_in_use ())            \
253            glthread_rwlock_rdlock (&NAME); \
254        }                                   \
255      while (0)
256#   define gl_rwlock_wrlock(NAME) \
257      do                                    \
258        {                                   \
259          if (pthread_in_use ())            \
260            glthread_rwlock_wrlock (&NAME); \
261        }                                   \
262      while (0)
263#   define gl_rwlock_unlock(NAME) \
264      do                                    \
265        {                                   \
266          if (pthread_in_use ())            \
267            glthread_rwlock_unlock (&NAME); \
268        }                                   \
269      while (0)
270#   define gl_rwlock_destroy(NAME) \
271      do                                     \
272        {                                    \
273          if (pthread_in_use ())             \
274            glthread_rwlock_destroy (&NAME); \
275        }                                    \
276      while (0)
277extern void glthread_rwlock_init (gl_rwlock_t *lock);
278extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
279extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
280extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
281extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
282
283#  endif
284
285# else
286
287typedef struct
288        {
289          pthread_mutex_t lock; /* protects the remaining fields */
290          pthread_cond_t waiting_readers; /* waiting readers */
291          pthread_cond_t waiting_writers; /* waiting writers */
292          unsigned int waiting_writers_count; /* number of waiting writers */
293          int runcount; /* number of readers running, or -1 when a writer runs */
294        }
295        gl_rwlock_t;
296# define gl_rwlock_define(STORAGECLASS, NAME) \
297    STORAGECLASS gl_rwlock_t NAME;
298# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
299    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
300# define gl_rwlock_initializer \
301    { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
302# define gl_rwlock_init(NAME) \
303    do                                  \
304      {                                 \
305        if (pthread_in_use ())          \
306          glthread_rwlock_init (&NAME); \
307      }                                 \
308    while (0)
309# define gl_rwlock_rdlock(NAME) \
310    do                                    \
311      {                                   \
312        if (pthread_in_use ())            \
313          glthread_rwlock_rdlock (&NAME); \
314      }                                   \
315    while (0)
316# define gl_rwlock_wrlock(NAME) \
317    do                                    \
318      {                                   \
319        if (pthread_in_use ())            \
320          glthread_rwlock_wrlock (&NAME); \
321      }                                   \
322    while (0)
323# define gl_rwlock_unlock(NAME) \
324    do                                    \
325      {                                   \
326        if (pthread_in_use ())            \
327          glthread_rwlock_unlock (&NAME); \
328      }                                   \
329    while (0)
330# define gl_rwlock_destroy(NAME) \
331    do                                     \
332      {                                    \
333        if (pthread_in_use ())             \
334          glthread_rwlock_destroy (&NAME); \
335      }                                    \
336    while (0)
337extern void glthread_rwlock_init (gl_rwlock_t *lock);
338extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
339extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
340extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
341extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
342
343# endif
344
345/* --------------------- gl_recursive_lock_t datatype --------------------- */
346
347# if HAVE_PTHREAD_MUTEX_RECURSIVE
348
349#  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
350
351typedef pthread_mutex_t gl_recursive_lock_t;
352#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
353      STORAGECLASS pthread_mutex_t NAME;
354#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
355      STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
356#   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
357#    define gl_recursive_lock_initializer \
358       PTHREAD_RECURSIVE_MUTEX_INITIALIZER
359#   else
360#    define gl_recursive_lock_initializer \
361       PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
362#   endif
363#   define gl_recursive_lock_init(NAME) \
364      do                                                                  \
365        {                                                                 \
366          if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
367            abort ();                                                     \
368        }                                                                 \
369      while (0)
370#   define gl_recursive_lock_lock(NAME) \
371      do                                                            \
372        {                                                           \
373          if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
374            abort ();                                               \
375        }                                                           \
376      while (0)
377#   define gl_recursive_lock_unlock(NAME) \
378      do                                                              \
379        {                                                             \
380          if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
381            abort ();                                                 \
382        }                                                             \
383      while (0)
384#   define gl_recursive_lock_destroy(NAME) \
385      do                                                               \
386        {                                                              \
387          if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
388            abort ();                                                  \
389        }                                                              \
390      while (0)
391
392#  else
393
394typedef struct
395        {
396          pthread_mutex_t recmutex; /* recursive mutex */
397          pthread_mutex_t guard;    /* protects the initialization */
398          int initialized;
399        }
400        gl_recursive_lock_t;
401#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
402      STORAGECLASS gl_recursive_lock_t NAME;
403#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
404      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
405#   define gl_recursive_lock_initializer \
406      { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
407#   define gl_recursive_lock_init(NAME) \
408      do                                          \
409        {                                         \
410          if (pthread_in_use ())                  \
411            glthread_recursive_lock_init (&NAME); \
412        }                                         \
413      while (0)
414#   define gl_recursive_lock_lock(NAME) \
415      do                                          \
416        {                                         \
417          if (pthread_in_use ())                  \
418            glthread_recursive_lock_lock (&NAME); \
419        }                                         \
420      while (0)
421#   define gl_recursive_lock_unlock(NAME) \
422      do                                            \
423        {                                           \
424          if (pthread_in_use ())                    \
425            glthread_recursive_lock_unlock (&NAME); \
426        }                                           \
427      while (0)
428#   define gl_recursive_lock_destroy(NAME) \
429      do                                             \
430        {                                            \
431          if (pthread_in_use ())                     \
432            glthread_recursive_lock_destroy (&NAME); \
433        }                                            \
434      while (0)
435extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
436extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
437extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
438extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
439
440#  endif
441
442# else
443
444/* Old versions of POSIX threads on Solaris did not have recursive locks.
445   We have to implement them ourselves.  */
446
447typedef struct
448        {
449          pthread_mutex_t mutex;
450          pthread_t owner;
451          unsigned long depth;
452        }
453        gl_recursive_lock_t;
454#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
455     STORAGECLASS gl_recursive_lock_t NAME;
456#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
457     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
458#  define gl_recursive_lock_initializer \
459     { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
460#  define gl_recursive_lock_init(NAME) \
461     do                                          \
462       {                                         \
463         if (pthread_in_use ())                  \
464           glthread_recursive_lock_init (&NAME); \
465       }                                         \
466     while (0)
467#  define gl_recursive_lock_lock(NAME) \
468     do                                          \
469       {                                         \
470         if (pthread_in_use ())                  \
471           glthread_recursive_lock_lock (&NAME); \
472       }                                         \
473     while (0)
474#  define gl_recursive_lock_unlock(NAME) \
475     do                                            \
476       {                                           \
477         if (pthread_in_use ())                    \
478           glthread_recursive_lock_unlock (&NAME); \
479       }                                           \
480     while (0)
481#  define gl_recursive_lock_destroy(NAME) \
482     do                                             \
483       {                                            \
484         if (pthread_in_use ())                     \
485           glthread_recursive_lock_destroy (&NAME); \
486       }                                            \
487     while (0)
488extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
489extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
490extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
491extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
492
493# endif
494
495/* -------------------------- gl_once_t datatype -------------------------- */
496
497typedef pthread_once_t gl_once_t;
498# define gl_once_define(STORAGECLASS, NAME) \
499    STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
500# define gl_once(NAME, INITFUNCTION) \
501    do                                                   \
502      {                                                  \
503        if (pthread_in_use ())                           \
504          {                                              \
505            if (pthread_once (&NAME, INITFUNCTION) != 0) \
506              abort ();                                  \
507          }                                              \
508        else                                             \
509          {                                              \
510            if (glthread_once_singlethreaded (&NAME))    \
511              INITFUNCTION ();                           \
512          }                                              \
513      }                                                  \
514    while (0)
515extern int glthread_once_singlethreaded (pthread_once_t *once_control);
516
517# ifdef __cplusplus
518}
519# endif
520
521#endif
522
523/* ========================================================================= */
524
525#if USE_PTH_THREADS
526
527/* Use the GNU Pth threads library.  */
528
529# include <pth.h>
530# include <stdlib.h>
531
532# ifdef __cplusplus
533extern "C" {
534# endif
535
536# if USE_PTH_THREADS_WEAK
537
538/* Use weak references to the GNU Pth threads library.  */
539
540#  pragma weak pth_mutex_init
541#  pragma weak pth_mutex_acquire
542#  pragma weak pth_mutex_release
543#  pragma weak pth_rwlock_init
544#  pragma weak pth_rwlock_acquire
545#  pragma weak pth_rwlock_release
546#  pragma weak pth_once
547
548#  pragma weak pth_cancel
549#  define pth_in_use() (pth_cancel != NULL)
550
551# else
552
553#  define pth_in_use() 1
554
555# endif
556
557/* -------------------------- gl_lock_t datatype -------------------------- */
558
559typedef pth_mutex_t gl_lock_t;
560# define gl_lock_define(STORAGECLASS, NAME) \
561    STORAGECLASS pth_mutex_t NAME;
562# define gl_lock_define_initialized(STORAGECLASS, NAME) \
563    STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
564# define gl_lock_initializer \
565    PTH_MUTEX_INIT
566# define gl_lock_init(NAME) \
567    do                                               \
568      {                                              \
569        if (pth_in_use() && !pth_mutex_init (&NAME)) \
570          abort ();                                  \
571      }                                              \
572    while (0)
573# define gl_lock_lock(NAME) \
574    do                                                           \
575      {                                                          \
576        if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
577          abort ();                                              \
578      }                                                          \
579    while (0)
580# define gl_lock_unlock(NAME) \
581    do                                                  \
582      {                                                 \
583        if (pth_in_use() && !pth_mutex_release (&NAME)) \
584          abort ();                                     \
585      }                                                 \
586    while (0)
587# define gl_lock_destroy(NAME) \
588    (void)(&NAME)
589
590/* ------------------------- gl_rwlock_t datatype ------------------------- */
591
592typedef pth_rwlock_t gl_rwlock_t;
593#  define gl_rwlock_define(STORAGECLASS, NAME) \
594     STORAGECLASS pth_rwlock_t NAME;
595#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
596     STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
597#  define gl_rwlock_initializer \
598     PTH_RWLOCK_INIT
599#  define gl_rwlock_init(NAME) \
600     do                                                \
601       {                                               \
602         if (pth_in_use() && !pth_rwlock_init (&NAME)) \
603           abort ();                                   \
604       }                                               \
605     while (0)
606#  define gl_rwlock_rdlock(NAME) \
607     do                                                              \
608       {                                                             \
609         if (pth_in_use()                                            \
610             && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \
611           abort ();                                                 \
612       }                                                             \
613     while (0)
614#  define gl_rwlock_wrlock(NAME) \
615     do                                                              \
616       {                                                             \
617         if (pth_in_use()                                            \
618             && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \
619           abort ();                                                 \
620       }                                                             \
621     while (0)
622#  define gl_rwlock_unlock(NAME) \
623     do                                                   \
624       {                                                  \
625         if (pth_in_use() && !pth_rwlock_release (&NAME)) \
626           abort ();                                      \
627       }                                                  \
628     while (0)
629#  define gl_rwlock_destroy(NAME) \
630     (void)(&NAME)
631
632/* --------------------- gl_recursive_lock_t datatype --------------------- */
633
634/* In Pth, mutexes are recursive by default.  */
635typedef pth_mutex_t gl_recursive_lock_t;
636#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
637     STORAGECLASS pth_mutex_t NAME;
638#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
639     STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
640#  define gl_recursive_lock_initializer \
641     PTH_MUTEX_INIT
642#  define gl_recursive_lock_init(NAME) \
643     do                                               \
644       {                                              \
645         if (pth_in_use() && !pth_mutex_init (&NAME)) \
646           abort ();                                  \
647       }                                              \
648     while (0)
649#  define gl_recursive_lock_lock(NAME) \
650     do                                                           \
651       {                                                          \
652         if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
653           abort ();                                              \
654       }                                                          \
655     while (0)
656#  define gl_recursive_lock_unlock(NAME) \
657     do                                                  \
658       {                                                 \
659         if (pth_in_use() && !pth_mutex_release (&NAME)) \
660           abort ();                                     \
661       }                                                 \
662     while (0)
663#  define gl_recursive_lock_destroy(NAME) \
664     (void)(&NAME)
665
666/* -------------------------- gl_once_t datatype -------------------------- */
667
668typedef pth_once_t gl_once_t;
669# define gl_once_define(STORAGECLASS, NAME) \
670    STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
671# define gl_once(NAME, INITFUNCTION) \
672    do                                                                \
673      {                                                               \
674        if (pth_in_use ())                                            \
675          {                                                           \
676            void (*gl_once_temp) (void) = INITFUNCTION;               \
677            if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
678              abort ();                                               \
679          }                                                           \
680        else                                                          \
681          {                                                           \
682            if (glthread_once_singlethreaded (&NAME))                 \
683              INITFUNCTION ();                                        \
684          }                                                           \
685      }                                                               \
686    while (0)
687extern void glthread_once_call (void *arg);
688extern int glthread_once_singlethreaded (pth_once_t *once_control);
689
690# ifdef __cplusplus
691}
692# endif
693
694#endif
695
696/* ========================================================================= */
697
698#if USE_SOLARIS_THREADS
699
700/* Use the old Solaris threads library.  */
701
702# include <thread.h>
703# include <synch.h>
704# include <stdlib.h>
705
706# ifdef __cplusplus
707extern "C" {
708# endif
709
710# if USE_SOLARIS_THREADS_WEAK
711
712/* Use weak references to the old Solaris threads library.  */
713
714#  pragma weak mutex_init
715#  pragma weak mutex_lock
716#  pragma weak mutex_unlock
717#  pragma weak mutex_destroy
718#  pragma weak rwlock_init
719#  pragma weak rw_rdlock
720#  pragma weak rw_wrlock
721#  pragma weak rw_unlock
722#  pragma weak rwlock_destroy
723#  pragma weak thr_self
724
725#  pragma weak thr_suspend
726#  define thread_in_use() (thr_suspend != NULL)
727
728# else
729
730#  define thread_in_use() 1
731
732# endif
733
734/* -------------------------- gl_lock_t datatype -------------------------- */
735
736typedef mutex_t gl_lock_t;
737# define gl_lock_define(STORAGECLASS, NAME) \
738    STORAGECLASS mutex_t NAME;
739# define gl_lock_define_initialized(STORAGECLASS, NAME) \
740    STORAGECLASS mutex_t NAME = gl_lock_initializer;
741# define gl_lock_initializer \
742    DEFAULTMUTEX
743# define gl_lock_init(NAME) \
744    do                                                                       \
745      {                                                                      \
746        if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \
747          abort ();                                                          \
748      }                                                                      \
749    while (0)
750# define gl_lock_lock(NAME) \
751    do                                                   \
752      {                                                  \
753        if (thread_in_use () && mutex_lock (&NAME) != 0) \
754          abort ();                                      \
755      }                                                  \
756    while (0)
757# define gl_lock_unlock(NAME) \
758    do                                                     \
759      {                                                    \
760        if (thread_in_use () && mutex_unlock (&NAME) != 0) \
761          abort ();                                        \
762      }                                                    \
763    while (0)
764# define gl_lock_destroy(NAME) \
765    do                                                      \
766      {                                                     \
767        if (thread_in_use () && mutex_destroy (&NAME) != 0) \
768          abort ();                                         \
769      }                                                     \
770    while (0)
771
772/* ------------------------- gl_rwlock_t datatype ------------------------- */
773
774typedef rwlock_t gl_rwlock_t;
775# define gl_rwlock_define(STORAGECLASS, NAME) \
776    STORAGECLASS rwlock_t NAME;
777# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
778    STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
779# define gl_rwlock_initializer \
780    DEFAULTRWLOCK
781# define gl_rwlock_init(NAME) \
782    do                                                                        \
783      {                                                                       \
784        if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \
785          abort ();                                                           \
786      }                                                                       \
787    while (0)
788# define gl_rwlock_rdlock(NAME) \
789    do                                                  \
790      {                                                 \
791        if (thread_in_use () && rw_rdlock (&NAME) != 0) \
792          abort ();                                     \
793      }                                                 \
794    while (0)
795# define gl_rwlock_wrlock(NAME) \
796    do                                                  \
797      {                                                 \
798        if (thread_in_use () && rw_wrlock (&NAME) != 0) \
799          abort ();                                     \
800      }                                                 \
801    while (0)
802# define gl_rwlock_unlock(NAME) \
803    do                                                  \
804      {                                                 \
805        if (thread_in_use () && rw_unlock (&NAME) != 0) \
806          abort ();                                     \
807      }                                                 \
808    while (0)
809# define gl_rwlock_destroy(NAME) \
810    do                                                       \
811      {                                                      \
812        if (thread_in_use () && rwlock_destroy (&NAME) != 0) \
813          abort ();                                          \
814      }                                                      \
815    while (0)
816
817/* --------------------- gl_recursive_lock_t datatype --------------------- */
818
819/* Old Solaris threads did not have recursive locks.
820   We have to implement them ourselves.  */
821
822typedef struct
823        {
824          mutex_t mutex;
825          thread_t owner;
826          unsigned long depth;
827        }
828        gl_recursive_lock_t;
829# define gl_recursive_lock_define(STORAGECLASS, NAME) \
830    STORAGECLASS gl_recursive_lock_t NAME;
831# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
832    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
833# define gl_recursive_lock_initializer \
834    { DEFAULTMUTEX, (thread_t) 0, 0 }
835# define gl_recursive_lock_init(NAME) \
836    do                                          \
837      {                                         \
838        if (thread_in_use ())                   \
839          glthread_recursive_lock_init (&NAME); \
840      }                                         \
841    while (0)
842# define gl_recursive_lock_lock(NAME) \
843    do                                          \
844      {                                         \
845        if (thread_in_use ())                   \
846          glthread_recursive_lock_lock (&NAME); \
847      }                                         \
848    while (0)
849# define gl_recursive_lock_unlock(NAME) \
850    do                                            \
851      {                                           \
852        if (thread_in_use ())                     \
853          glthread_recursive_lock_unlock (&NAME); \
854      }                                           \
855    while (0)
856# define gl_recursive_lock_destroy(NAME) \
857    do                                             \
858      {                                            \
859        if (thread_in_use ())                      \
860          glthread_recursive_lock_destroy (&NAME); \
861      }                                            \
862    while (0)
863extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
864extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
865extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
866extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
867
868/* -------------------------- gl_once_t datatype -------------------------- */
869
870typedef struct
871        {
872          volatile int inited;
873          mutex_t mutex;
874        }
875        gl_once_t;
876# define gl_once_define(STORAGECLASS, NAME) \
877    STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
878# define gl_once(NAME, INITFUNCTION) \
879    do                                                \
880      {                                               \
881        if (thread_in_use ())                         \
882          {                                           \
883            glthread_once (&NAME, INITFUNCTION);      \
884          }                                           \
885        else                                          \
886          {                                           \
887            if (glthread_once_singlethreaded (&NAME)) \
888              INITFUNCTION ();                        \
889          }                                           \
890      }                                               \
891    while (0)
892extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
893extern int glthread_once_singlethreaded (gl_once_t *once_control);
894
895# ifdef __cplusplus
896}
897# endif
898
899#endif
900
901/* ========================================================================= */
902
903#if USE_WIN32_THREADS
904
905# include <windows.h>
906
907# ifdef __cplusplus
908extern "C" {
909# endif
910
911/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
912   Semaphore types, because
913     - we need only to synchronize inside a single process (address space),
914       not inter-process locking,
915     - we don't need to support trylock operations.  (TryEnterCriticalSection
916       does not work on Windows 95/98/ME.  Packages that need trylock usually
917       define their own mutex type.)  */
918
919/* There is no way to statically initialize a CRITICAL_SECTION.  It needs
920   to be done lazily, once only.  For this we need spinlocks.  */
921
922typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
923
924/* -------------------------- gl_lock_t datatype -------------------------- */
925
926typedef struct
927        {
928          gl_spinlock_t guard; /* protects the initialization */
929          CRITICAL_SECTION lock;
930        }
931        gl_lock_t;
932# define gl_lock_define(STORAGECLASS, NAME) \
933    STORAGECLASS gl_lock_t NAME;
934# define gl_lock_define_initialized(STORAGECLASS, NAME) \
935    STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
936# define gl_lock_initializer \
937    { { 0, -1 } }
938# define gl_lock_init(NAME) \
939    glthread_lock_init (&NAME)
940# define gl_lock_lock(NAME) \
941    glthread_lock_lock (&NAME)
942# define gl_lock_unlock(NAME) \
943    glthread_lock_unlock (&NAME)
944# define gl_lock_destroy(NAME) \
945    glthread_lock_destroy (&NAME)
946extern void glthread_lock_init (gl_lock_t *lock);
947extern void glthread_lock_lock (gl_lock_t *lock);
948extern void glthread_lock_unlock (gl_lock_t *lock);
949extern void glthread_lock_destroy (gl_lock_t *lock);
950
951/* ------------------------- gl_rwlock_t datatype ------------------------- */
952
953/* It is impossible to implement read-write locks using plain locks, without
954   introducing an extra thread dedicated to managing read-write locks.
955   Therefore here we need to use the low-level Event type.  */
956
957typedef struct
958        {
959          HANDLE *array; /* array of waiting threads, each represented by an event */
960          unsigned int count; /* number of waiting threads */
961          unsigned int alloc; /* length of allocated array */
962          unsigned int offset; /* index of first waiting thread in array */
963        }
964        gl_waitqueue_t;
965typedef struct
966        {
967          gl_spinlock_t guard; /* protects the initialization */
968          CRITICAL_SECTION lock; /* protects the remaining fields */
969          gl_waitqueue_t waiting_readers; /* waiting readers */
970          gl_waitqueue_t waiting_writers; /* waiting writers */
971          int runcount; /* number of readers running, or -1 when a writer runs */
972        }
973        gl_rwlock_t;
974# define gl_rwlock_define(STORAGECLASS, NAME) \
975    STORAGECLASS gl_rwlock_t NAME;
976# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
977    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
978# define gl_rwlock_initializer \
979    { { 0, -1 } }
980# define gl_rwlock_init(NAME) \
981    glthread_rwlock_init (&NAME)
982# define gl_rwlock_rdlock(NAME) \
983    glthread_rwlock_rdlock (&NAME)
984# define gl_rwlock_wrlock(NAME) \
985    glthread_rwlock_wrlock (&NAME)
986# define gl_rwlock_unlock(NAME) \
987    glthread_rwlock_unlock (&NAME)
988# define gl_rwlock_destroy(NAME) \
989    glthread_rwlock_destroy (&NAME)
990extern void glthread_rwlock_init (gl_rwlock_t *lock);
991extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
992extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
993extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
994extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
995
996/* --------------------- gl_recursive_lock_t datatype --------------------- */
997
998/* The Win32 documentation says that CRITICAL_SECTION already implements a
999   recursive lock.  But we need not rely on it: It's easy to implement a
1000   recursive lock without this assumption.  */
1001
1002typedef struct
1003        {
1004          gl_spinlock_t guard; /* protects the initialization */
1005          DWORD owner;
1006          unsigned long depth;
1007          CRITICAL_SECTION lock;
1008        }
1009        gl_recursive_lock_t;
1010# define gl_recursive_lock_define(STORAGECLASS, NAME) \
1011    STORAGECLASS gl_recursive_lock_t NAME;
1012# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
1013    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
1014# define gl_recursive_lock_initializer \
1015    { { 0, -1 }, 0, 0 }
1016# define gl_recursive_lock_init(NAME) \
1017    glthread_recursive_lock_init (&NAME)
1018# define gl_recursive_lock_lock(NAME) \
1019    glthread_recursive_lock_lock (&NAME)
1020# define gl_recursive_lock_unlock(NAME) \
1021    glthread_recursive_lock_unlock (&NAME)
1022# define gl_recursive_lock_destroy(NAME) \
1023    glthread_recursive_lock_destroy (&NAME)
1024extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
1025extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
1026extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
1027extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
1028
1029/* -------------------------- gl_once_t datatype -------------------------- */
1030
1031typedef struct
1032        {
1033          volatile int inited;
1034          volatile long started;
1035          CRITICAL_SECTION lock;
1036        }
1037        gl_once_t;
1038# define gl_once_define(STORAGECLASS, NAME) \
1039    STORAGECLASS gl_once_t NAME = { -1, -1 };
1040# define gl_once(NAME, INITFUNCTION) \
1041    glthread_once (&NAME, INITFUNCTION)
1042extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
1043
1044# ifdef __cplusplus
1045}
1046# endif
1047
1048#endif
1049
1050/* ========================================================================= */
1051
1052#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
1053
1054/* Provide dummy implementation if threads are not supported.  */
1055
1056/* -------------------------- gl_lock_t datatype -------------------------- */
1057
1058typedef int gl_lock_t;
1059# define gl_lock_define(STORAGECLASS, NAME)
1060# define gl_lock_define_initialized(STORAGECLASS, NAME)
1061# define gl_lock_init(NAME)
1062# define gl_lock_lock(NAME)
1063# define gl_lock_unlock(NAME)
1064
1065/* ------------------------- gl_rwlock_t datatype ------------------------- */
1066
1067typedef int gl_rwlock_t;
1068# define gl_rwlock_define(STORAGECLASS, NAME)
1069# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
1070# define gl_rwlock_init(NAME)
1071# define gl_rwlock_rdlock(NAME)
1072# define gl_rwlock_wrlock(NAME)
1073# define gl_rwlock_unlock(NAME)
1074
1075/* --------------------- gl_recursive_lock_t datatype --------------------- */
1076
1077typedef int gl_recursive_lock_t;
1078# define gl_recursive_lock_define(STORAGECLASS, NAME)
1079# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
1080# define gl_recursive_lock_init(NAME)
1081# define gl_recursive_lock_lock(NAME)
1082# define gl_recursive_lock_unlock(NAME)
1083
1084/* -------------------------- gl_once_t datatype -------------------------- */
1085
1086typedef int gl_once_t;
1087# define gl_once_define(STORAGECLASS, NAME) \
1088    STORAGECLASS gl_once_t NAME = 0;
1089# define gl_once(NAME, INITFUNCTION) \
1090    do                       \
1091      {                      \
1092        if (NAME == 0)       \
1093          {                  \
1094            NAME = ~ 0;      \
1095            INITFUNCTION (); \
1096          }                  \
1097      }                      \
1098    while (0)
1099
1100#endif
1101
1102/* ========================================================================= */
1103
1104#endif /* _LOCK_H */
1105