"Fossies" - the Fresh Open Source Software Archive

Member "gcal-4.1/lib/glthread/lock.h" (22 Jan 2017, 38478 Bytes) of package /linux/misc/gcal-4.1.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 and the latest Fossies "Diffs" side-by-side code changes report: 4_vs_4.1.

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