"Fossies" - the Fresh Open Source Software Archive

Member "sitecopy-0.16.6/intl/lock.h" (5 Nov 2007, 44782 Bytes) of archive /linux/www/sitecopy-0.16.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lock.h" see the Fossies "Dox" file reference documentation.

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