"Fossies" - the Fresh Open Source Software Archive

Member "bison-3.4.1/lib/glthread/lock.h" (28 Mar 2019, 39081 Bytes) of package /linux/misc/bison-3.4.1.tar.xz:


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 and the last Fossies "Diffs" side-by-side code changes report: 3.2.4_vs_3.3.

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