root/maint/gnulib/lib/glthread/lock.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 /* Locking in multithreaded situations.
   2    Copyright (C) 2005-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file 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 Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser 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-win32.h.  */
  19 
  20 /* This file contains locking primitives for use with a given thread library.
  21    It does not contain primitives for creating threads or for other
  22    synchronization primitives.
  23 
  24    Normal (non-recursive) locks:
  25      Type:                gl_lock_t
  26      Declaration:         gl_lock_define(extern, name)
  27      Initializer:         gl_lock_define_initialized(, name)
  28      Initialization:      gl_lock_init (name);
  29      Taking the lock:     gl_lock_lock (name);
  30      Releasing the lock:  gl_lock_unlock (name);
  31      De-initialization:   gl_lock_destroy (name);
  32    Equivalent functions with control of error handling:
  33      Initialization:      err = glthread_lock_init (&name);
  34      Taking the lock:     err = glthread_lock_lock (&name);
  35      Releasing the lock:  err = glthread_lock_unlock (&name);
  36      De-initialization:   err = glthread_lock_destroy (&name);
  37 
  38    Read-Write (non-recursive) locks:
  39      Type:                gl_rwlock_t
  40      Declaration:         gl_rwlock_define(extern, name)
  41      Initializer:         gl_rwlock_define_initialized(, name)
  42      Initialization:      gl_rwlock_init (name);
  43      Taking the lock:     gl_rwlock_rdlock (name);
  44                           gl_rwlock_wrlock (name);
  45      Releasing the lock:  gl_rwlock_unlock (name);
  46      De-initialization:   gl_rwlock_destroy (name);
  47    Equivalent functions with control of error handling:
  48      Initialization:      err = glthread_rwlock_init (&name);
  49      Taking the lock:     err = glthread_rwlock_rdlock (&name);
  50                           err = glthread_rwlock_wrlock (&name);
  51      Releasing the lock:  err = glthread_rwlock_unlock (&name);
  52      De-initialization:   err = glthread_rwlock_destroy (&name);
  53 
  54    Recursive locks:
  55      Type:                gl_recursive_lock_t
  56      Declaration:         gl_recursive_lock_define(extern, name)
  57      Initializer:         gl_recursive_lock_define_initialized(, name)
  58      Initialization:      gl_recursive_lock_init (name);
  59      Taking the lock:     gl_recursive_lock_lock (name);
  60      Releasing the lock:  gl_recursive_lock_unlock (name);
  61      De-initialization:   gl_recursive_lock_destroy (name);
  62    Equivalent functions with control of error handling:
  63      Initialization:      err = glthread_recursive_lock_init (&name);
  64      Taking the lock:     err = glthread_recursive_lock_lock (&name);
  65      Releasing the lock:  err = glthread_recursive_lock_unlock (&name);
  66      De-initialization:   err = glthread_recursive_lock_destroy (&name);
  67 
  68   Once-only execution:
  69      Type:                gl_once_t
  70      Initializer:         gl_once_define(extern, name)
  71      Execution:           gl_once (name, initfunction);
  72    Equivalent functions with control of error handling:
  73      Execution:           err = glthread_once (&name, initfunction);
  74 */
  75 
  76 
  77 #ifndef _LOCK_H
  78 #define _LOCK_H
  79 
  80 #include <errno.h>
  81 #include <stdlib.h>
  82 
  83 #if !defined c11_threads_in_use
  84 # if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
  85 #  define c11_threads_in_use() 1
  86 # elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
  87 #  include <threads.h>
  88 #  pragma weak thrd_exit
  89 #  define c11_threads_in_use() (thrd_exit != NULL)
  90 # else
  91 #  define c11_threads_in_use() 0
  92 # endif
  93 #endif
  94 
  95 /* ========================================================================= */
  96 
  97 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
  98 
  99 /* Use the ISO C threads library.  */
 100 
 101 # include <threads.h>
 102 
 103 # ifdef __cplusplus
 104 extern "C" {
 105 # endif
 106 
 107 /* -------------------------- gl_lock_t datatype -------------------------- */
 108 
 109 typedef struct
 110         {
 111           int volatile init_needed;
 112           once_flag init_once;
 113           void (*init_func) (void);
 114           mtx_t mutex;
 115         }
 116         gl_lock_t;
 117 # define gl_lock_define(STORAGECLASS, NAME) \
 118     STORAGECLASS gl_lock_t NAME;
 119 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
 120     static void _atomic_init_##NAME (void);       \
 121     STORAGECLASS gl_lock_t NAME =                 \
 122       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
 123     static void _atomic_init_##NAME (void)        \
 124     {                                             \
 125       if (glthread_lock_init (&(NAME)))           \
 126         abort ();                                 \
 127     }
 128 extern int glthread_lock_init (gl_lock_t *lock);
 129 extern int glthread_lock_lock (gl_lock_t *lock);
 130 extern int glthread_lock_unlock (gl_lock_t *lock);
 131 extern int glthread_lock_destroy (gl_lock_t *lock);
 132 
 133 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 134 
 135 typedef struct
 136         {
 137           int volatile init_needed;
 138           once_flag init_once;
 139           void (*init_func) (void);
 140           mtx_t lock; /* protects the remaining fields */
 141           cnd_t waiting_readers; /* waiting readers */
 142           cnd_t waiting_writers; /* waiting writers */
 143           unsigned int waiting_writers_count; /* number of waiting writers */
 144           int runcount; /* number of readers running, or -1 when a writer runs */
 145         }
 146         gl_rwlock_t;
 147 # define gl_rwlock_define(STORAGECLASS, NAME) \
 148     STORAGECLASS gl_rwlock_t NAME;
 149 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
 150     static void _atomic_init_##NAME (void);       \
 151     STORAGECLASS gl_rwlock_t NAME =               \
 152       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
 153     static void _atomic_init_##NAME (void)        \
 154     {                                             \
 155       if (glthread_rwlock_init (&(NAME)))         \
 156         abort ();                                 \
 157     }
 158 extern int glthread_rwlock_init (gl_rwlock_t *lock);
 159 extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
 160 extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
 161 extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
 162 extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
 163 
 164 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 165 
 166 typedef struct
 167         {
 168           int volatile init_needed;
 169           once_flag init_once;
 170           void (*init_func) (void);
 171           mtx_t mutex;
 172         }
 173         gl_recursive_lock_t;
 174 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
 175     STORAGECLASS gl_recursive_lock_t NAME;
 176 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
 177     static void _atomic_init_##NAME (void);       \
 178     STORAGECLASS gl_recursive_lock_t NAME =       \
 179       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
 180     static void _atomic_init_##NAME (void)        \
 181     {                                             \
 182       if (glthread_recursive_lock_init (&(NAME))) \
 183         abort ();                                 \
 184     }
 185 extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
 186 extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
 187 extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
 188 extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 189 
 190 /* -------------------------- gl_once_t datatype -------------------------- */
 191 
 192 typedef once_flag gl_once_t;
 193 # define gl_once_define(STORAGECLASS, NAME) \
 194     STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
 195 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
 196     (call_once (ONCE_CONTROL, INITFUNCTION), 0)
 197 
 198 # ifdef __cplusplus
 199 }
 200 # endif
 201 
 202 #endif
 203 
 204 /* ========================================================================= */
 205 
 206 #if USE_POSIX_THREADS
 207 
 208 /* Use the POSIX threads library.  */
 209 
 210 # include <pthread.h>
 211 
 212 # ifdef __cplusplus
 213 extern "C" {
 214 # endif
 215 
 216 # if PTHREAD_IN_USE_DETECTION_HARD
 217 
 218 /* The pthread_in_use() detection needs to be done at runtime.  */
 219 #  define pthread_in_use() \
 220      glthread_in_use ()
 221 extern int glthread_in_use (void);
 222 
 223 # endif
 224 
 225 # if USE_POSIX_THREADS_WEAK
 226 
 227 /* Use weak references to the POSIX threads library.  */
 228 
 229 /* Weak references avoid dragging in external libraries if the other parts
 230    of the program don't use them.  Here we use them, because we don't want
 231    every program that uses libintl to depend on libpthread.  This assumes
 232    that libpthread would not be loaded after libintl; i.e. if libintl is
 233    loaded first, by an executable that does not depend on libpthread, and
 234    then a module is dynamically loaded that depends on libpthread, libintl
 235    will not be multithread-safe.  */
 236 
 237 /* The way to test at runtime whether libpthread is present is to test
 238    whether a function pointer's value, such as &pthread_mutex_init, is
 239    non-NULL.  However, some versions of GCC have a bug through which, in
 240    PIC mode, &foo != NULL always evaluates to true if there is a direct
 241    call to foo(...) in the same function.  To avoid this, we test the
 242    address of a function in libpthread that we don't use.  */
 243 
 244 #  pragma weak pthread_mutex_init
 245 #  pragma weak pthread_mutex_lock
 246 #  pragma weak pthread_mutex_unlock
 247 #  pragma weak pthread_mutex_destroy
 248 #  pragma weak pthread_rwlock_init
 249 #  pragma weak pthread_rwlock_rdlock
 250 #  pragma weak pthread_rwlock_wrlock
 251 #  pragma weak pthread_rwlock_unlock
 252 #  pragma weak pthread_rwlock_destroy
 253 #  pragma weak pthread_once
 254 #  pragma weak pthread_cond_init
 255 #  pragma weak pthread_cond_wait
 256 #  pragma weak pthread_cond_signal
 257 #  pragma weak pthread_cond_broadcast
 258 #  pragma weak pthread_cond_destroy
 259 #  pragma weak pthread_mutexattr_init
 260 #  pragma weak pthread_mutexattr_settype
 261 #  pragma weak pthread_mutexattr_destroy
 262 #  pragma weak pthread_rwlockattr_init
 263 #  if __GNU_LIBRARY__ > 1
 264 #   pragma weak pthread_rwlockattr_setkind_np
 265 #  endif
 266 #  pragma weak pthread_rwlockattr_destroy
 267 #  ifndef pthread_self
 268 #   pragma weak pthread_self
 269 #  endif
 270 
 271 #  if !PTHREAD_IN_USE_DETECTION_HARD
 272     /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
 273        can be used to determine whether libpthread is in use.  These are:
 274          pthread_mutexattr_gettype
 275          pthread_rwlockattr_destroy
 276          pthread_rwlockattr_init
 277      */
 278 #   pragma weak pthread_mutexattr_gettype
 279 #   define pthread_in_use() \
 280       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
 281 #  endif
 282 
 283 # else
 284 
 285 #  if !PTHREAD_IN_USE_DETECTION_HARD
 286 #   define pthread_in_use() 1
 287 #  endif
 288 
 289 # endif
 290 
 291 /* -------------------------- gl_lock_t datatype -------------------------- */
 292 
 293 typedef pthread_mutex_t gl_lock_t;
 294 # define gl_lock_define(STORAGECLASS, NAME) \
 295     STORAGECLASS pthread_mutex_t NAME;
 296 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
 297     STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
 298 # define gl_lock_initializer \
 299     PTHREAD_MUTEX_INITIALIZER
 300 # define glthread_lock_init(LOCK) \
 301     (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
 302 # define glthread_lock_lock(LOCK) \
 303     (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
 304 # define glthread_lock_unlock(LOCK) \
 305     (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
 306 # define glthread_lock_destroy(LOCK) \
 307     (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
 308 
 309 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 310 
 311 # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
 312 
 313 #  if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
 314 
 315 typedef pthread_rwlock_t gl_rwlock_t;
 316 #   define gl_rwlock_define(STORAGECLASS, NAME) \
 317       STORAGECLASS pthread_rwlock_t NAME;
 318 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
 319       STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
 320 #   if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
 321 #    if defined PTHREAD_RWLOCK_INITIALIZER
 322 #     define gl_rwlock_initializer \
 323         PTHREAD_RWLOCK_INITIALIZER
 324 #    else
 325 #     define gl_rwlock_initializer \
 326         PTHREAD_RWLOCK_INITIALIZER_NP
 327 #    endif
 328 #    define glthread_rwlock_init(LOCK) \
 329        (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
 330 #   else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
 331 #    define gl_rwlock_initializer \
 332        PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
 333 #    define glthread_rwlock_init(LOCK) \
 334        (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
 335 extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
 336 #   endif
 337 #   define glthread_rwlock_rdlock(LOCK) \
 338       (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
 339 #   define glthread_rwlock_wrlock(LOCK) \
 340       (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
 341 #   define glthread_rwlock_unlock(LOCK) \
 342       (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
 343 #   define glthread_rwlock_destroy(LOCK) \
 344       (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
 345 
 346 #  else
 347 
 348 typedef struct
 349         {
 350           int initialized;
 351           pthread_mutex_t guard;   /* protects the initialization */
 352           pthread_rwlock_t rwlock; /* read-write lock */
 353         }
 354         gl_rwlock_t;
 355 #   define gl_rwlock_define(STORAGECLASS, NAME) \
 356       STORAGECLASS gl_rwlock_t NAME;
 357 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
 358       STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
 359 #   define gl_rwlock_initializer \
 360       { 0, PTHREAD_MUTEX_INITIALIZER }
 361 #   define glthread_rwlock_init(LOCK) \
 362       (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
 363 #   define glthread_rwlock_rdlock(LOCK) \
 364       (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
 365 #   define glthread_rwlock_wrlock(LOCK) \
 366       (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
 367 #   define glthread_rwlock_unlock(LOCK) \
 368       (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
 369 #   define glthread_rwlock_destroy(LOCK) \
 370       (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
 371 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
 372 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
 373 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
 374 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
 375 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
 376 
 377 #  endif
 378 
 379 # else
 380 
 381 typedef struct
 382         {
 383           pthread_mutex_t lock; /* protects the remaining fields */
 384           pthread_cond_t waiting_readers; /* waiting readers */
 385           pthread_cond_t waiting_writers; /* waiting writers */
 386           unsigned int waiting_writers_count; /* number of waiting writers */
 387           int runcount; /* number of readers running, or -1 when a writer runs */
 388         }
 389         gl_rwlock_t;
 390 # define gl_rwlock_define(STORAGECLASS, NAME) \
 391     STORAGECLASS gl_rwlock_t NAME;
 392 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
 393     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
 394 # define gl_rwlock_initializer \
 395     { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
 396 # define glthread_rwlock_init(LOCK) \
 397     (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
 398 # define glthread_rwlock_rdlock(LOCK) \
 399     (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
 400 # define glthread_rwlock_wrlock(LOCK) \
 401     (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
 402 # define glthread_rwlock_unlock(LOCK) \
 403     (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
 404 # define glthread_rwlock_destroy(LOCK) \
 405     (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
 406 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
 407 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
 408 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
 409 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
 410 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
 411 
 412 # endif
 413 
 414 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 415 
 416 # if HAVE_PTHREAD_MUTEX_RECURSIVE
 417 
 418 #  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
 419 
 420 typedef pthread_mutex_t gl_recursive_lock_t;
 421 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
 422       STORAGECLASS pthread_mutex_t NAME;
 423 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
 424       STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
 425 #   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
 426 #    define gl_recursive_lock_initializer \
 427        PTHREAD_RECURSIVE_MUTEX_INITIALIZER
 428 #   else
 429 #    define gl_recursive_lock_initializer \
 430        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
 431 #   endif
 432 #   define glthread_recursive_lock_init(LOCK) \
 433       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
 434 #   define glthread_recursive_lock_lock(LOCK) \
 435       (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
 436 #   define glthread_recursive_lock_unlock(LOCK) \
 437       (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
 438 #   define glthread_recursive_lock_destroy(LOCK) \
 439       (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
 440 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
 441 
 442 #  else
 443 
 444 typedef struct
 445         {
 446           pthread_mutex_t recmutex; /* recursive mutex */
 447           pthread_mutex_t guard;    /* protects the initialization */
 448           int initialized;
 449         }
 450         gl_recursive_lock_t;
 451 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
 452       STORAGECLASS gl_recursive_lock_t NAME;
 453 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
 454       STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
 455 #   define gl_recursive_lock_initializer \
 456       { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
 457 #   define glthread_recursive_lock_init(LOCK) \
 458       (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
 459 #   define glthread_recursive_lock_lock(LOCK) \
 460       (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
 461 #   define glthread_recursive_lock_unlock(LOCK) \
 462       (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
 463 #   define glthread_recursive_lock_destroy(LOCK) \
 464       (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
 465 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
 466 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
 467 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
 468 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
 469 
 470 #  endif
 471 
 472 # else
 473 
 474 /* Old versions of POSIX threads on Solaris did not have recursive locks.
 475    We have to implement them ourselves.  */
 476 
 477 typedef struct
 478         {
 479           pthread_mutex_t mutex;
 480           pthread_t owner;
 481           unsigned long depth;
 482         }
 483         gl_recursive_lock_t;
 484 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
 485      STORAGECLASS gl_recursive_lock_t NAME;
 486 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
 487      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
 488 #  define gl_recursive_lock_initializer \
 489      { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
 490 #  define glthread_recursive_lock_init(LOCK) \
 491      (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
 492 #  define glthread_recursive_lock_lock(LOCK) \
 493      (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
 494 #  define glthread_recursive_lock_unlock(LOCK) \
 495      (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
 496 #  define glthread_recursive_lock_destroy(LOCK) \
 497      (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
 498 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
 499 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
 500 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
 501 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
 502 
 503 # endif
 504 
 505 /* -------------------------- gl_once_t datatype -------------------------- */
 506 
 507 typedef pthread_once_t gl_once_t;
 508 # define gl_once_define(STORAGECLASS, NAME) \
 509     STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
 510 # if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
 511 #  define glthread_once(ONCE_CONTROL, INITFUNCTION) \
 512      (pthread_in_use ()                                                        \
 513       ? pthread_once (ONCE_CONTROL, INITFUNCTION)                              \
 514       : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
 515 # else
 516 #  define glthread_once(ONCE_CONTROL, INITFUNCTION) \
 517      (pthread_in_use ()                                                        \
 518       ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)               \
 519       : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
 520 extern int glthread_once_multithreaded (pthread_once_t *once_control,
 521                                         void (*init_function) (void));
 522 # endif
 523 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
 524 
 525 # ifdef __cplusplus
 526 }
 527 # endif
 528 
 529 #endif
 530 
 531 /* ========================================================================= */
 532 
 533 #if USE_WINDOWS_THREADS
 534 
 535 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 536 # include <windows.h>
 537 
 538 # include "windows-mutex.h"
 539 # include "windows-rwlock.h"
 540 # include "windows-recmutex.h"
 541 # include "windows-once.h"
 542 
 543 # ifdef __cplusplus
 544 extern "C" {
 545 # endif
 546 
 547 /* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
 548    Mutex, Semaphore types, because
 549      - we need only to synchronize inside a single process (address space),
 550        not inter-process locking,
 551      - we don't need to support trylock operations.  (TryEnterCriticalSection
 552        does not work on Windows 95/98/ME.  Packages that need trylock usually
 553        define their own mutex type.)  */
 554 
 555 /* There is no way to statically initialize a CRITICAL_SECTION.  It needs
 556    to be done lazily, once only.  For this we need spinlocks.  */
 557 
 558 /* -------------------------- gl_lock_t datatype -------------------------- */
 559 
 560 typedef glwthread_mutex_t gl_lock_t;
 561 # define gl_lock_define(STORAGECLASS, NAME) \
 562     STORAGECLASS gl_lock_t NAME;
 563 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
 564     STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
 565 # define gl_lock_initializer \
 566     GLWTHREAD_MUTEX_INIT
 567 # define glthread_lock_init(LOCK) \
 568     (glwthread_mutex_init (LOCK), 0)
 569 # define glthread_lock_lock(LOCK) \
 570     glwthread_mutex_lock (LOCK)
 571 # define glthread_lock_unlock(LOCK) \
 572     glwthread_mutex_unlock (LOCK)
 573 # define glthread_lock_destroy(LOCK) \
 574     glwthread_mutex_destroy (LOCK)
 575 
 576 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 577 
 578 typedef glwthread_rwlock_t gl_rwlock_t;
 579 # define gl_rwlock_define(STORAGECLASS, NAME) \
 580     STORAGECLASS gl_rwlock_t NAME;
 581 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
 582     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
 583 # define gl_rwlock_initializer \
 584     GLWTHREAD_RWLOCK_INIT
 585 # define glthread_rwlock_init(LOCK) \
 586     (glwthread_rwlock_init (LOCK), 0)
 587 # define glthread_rwlock_rdlock(LOCK) \
 588     glwthread_rwlock_rdlock (LOCK)
 589 # define glthread_rwlock_wrlock(LOCK) \
 590     glwthread_rwlock_wrlock (LOCK)
 591 # define glthread_rwlock_unlock(LOCK) \
 592     glwthread_rwlock_unlock (LOCK)
 593 # define glthread_rwlock_destroy(LOCK) \
 594     glwthread_rwlock_destroy (LOCK)
 595 
 596 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 597 
 598 typedef glwthread_recmutex_t gl_recursive_lock_t;
 599 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
 600     STORAGECLASS gl_recursive_lock_t NAME;
 601 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
 602     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
 603 # define gl_recursive_lock_initializer \
 604     GLWTHREAD_RECMUTEX_INIT
 605 # define glthread_recursive_lock_init(LOCK) \
 606     (glwthread_recmutex_init (LOCK), 0)
 607 # define glthread_recursive_lock_lock(LOCK) \
 608     glwthread_recmutex_lock (LOCK)
 609 # define glthread_recursive_lock_unlock(LOCK) \
 610     glwthread_recmutex_unlock (LOCK)
 611 # define glthread_recursive_lock_destroy(LOCK) \
 612     glwthread_recmutex_destroy (LOCK)
 613 
 614 /* -------------------------- gl_once_t datatype -------------------------- */
 615 
 616 typedef glwthread_once_t gl_once_t;
 617 # define gl_once_define(STORAGECLASS, NAME) \
 618     STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
 619 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
 620     (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
 621 
 622 # ifdef __cplusplus
 623 }
 624 # endif
 625 
 626 #endif
 627 
 628 /* ========================================================================= */
 629 
 630 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
 631 
 632 /* Provide dummy implementation if threads are not supported.  */
 633 
 634 /* -------------------------- gl_lock_t datatype -------------------------- */
 635 
 636 typedef int gl_lock_t;
 637 # define gl_lock_define(STORAGECLASS, NAME)
 638 # define gl_lock_define_initialized(STORAGECLASS, NAME)
 639 # define glthread_lock_init(NAME) 0
 640 # define glthread_lock_lock(NAME) 0
 641 # define glthread_lock_unlock(NAME) 0
 642 # define glthread_lock_destroy(NAME) 0
 643 
 644 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 645 
 646 typedef int gl_rwlock_t;
 647 # define gl_rwlock_define(STORAGECLASS, NAME)
 648 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
 649 # define glthread_rwlock_init(NAME) 0
 650 # define glthread_rwlock_rdlock(NAME) 0
 651 # define glthread_rwlock_wrlock(NAME) 0
 652 # define glthread_rwlock_unlock(NAME) 0
 653 # define glthread_rwlock_destroy(NAME) 0
 654 
 655 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 656 
 657 typedef int gl_recursive_lock_t;
 658 # define gl_recursive_lock_define(STORAGECLASS, NAME)
 659 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
 660 # define glthread_recursive_lock_init(NAME) 0
 661 # define glthread_recursive_lock_lock(NAME) 0
 662 # define glthread_recursive_lock_unlock(NAME) 0
 663 # define glthread_recursive_lock_destroy(NAME) 0
 664 
 665 /* -------------------------- gl_once_t datatype -------------------------- */
 666 
 667 typedef int gl_once_t;
 668 # define gl_once_define(STORAGECLASS, NAME) \
 669     STORAGECLASS gl_once_t NAME = 0;
 670 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
 671     (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
 672 
 673 #endif
 674 
 675 /* ========================================================================= */
 676 
 677 /* Macros with built-in error handling.  */
 678 
 679 /* -------------------------- gl_lock_t datatype -------------------------- */
 680 
 681 #define gl_lock_init(NAME) \
 682    do                                  \
 683      {                                 \
 684        if (glthread_lock_init (&NAME)) \
 685          abort ();                     \
 686      }                                 \
 687    while (0)
 688 #define gl_lock_lock(NAME) \
 689    do                                  \
 690      {                                 \
 691        if (glthread_lock_lock (&NAME)) \
 692          abort ();                     \
 693      }                                 \
 694    while (0)
 695 #define gl_lock_unlock(NAME) \
 696    do                                    \
 697      {                                   \
 698        if (glthread_lock_unlock (&NAME)) \
 699          abort ();                       \
 700      }                                   \
 701    while (0)
 702 #define gl_lock_destroy(NAME) \
 703    do                                     \
 704      {                                    \
 705        if (glthread_lock_destroy (&NAME)) \
 706          abort ();                        \
 707      }                                    \
 708    while (0)
 709 
 710 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 711 
 712 #define gl_rwlock_init(NAME) \
 713    do                                    \
 714      {                                   \
 715        if (glthread_rwlock_init (&NAME)) \
 716          abort ();                       \
 717      }                                   \
 718    while (0)
 719 #define gl_rwlock_rdlock(NAME) \
 720    do                                      \
 721      {                                     \
 722        if (glthread_rwlock_rdlock (&NAME)) \
 723          abort ();                         \
 724      }                                     \
 725    while (0)
 726 #define gl_rwlock_wrlock(NAME) \
 727    do                                      \
 728      {                                     \
 729        if (glthread_rwlock_wrlock (&NAME)) \
 730          abort ();                         \
 731      }                                     \
 732    while (0)
 733 #define gl_rwlock_unlock(NAME) \
 734    do                                      \
 735      {                                     \
 736        if (glthread_rwlock_unlock (&NAME)) \
 737          abort ();                         \
 738      }                                     \
 739    while (0)
 740 #define gl_rwlock_destroy(NAME) \
 741    do                                       \
 742      {                                      \
 743        if (glthread_rwlock_destroy (&NAME)) \
 744          abort ();                          \
 745      }                                      \
 746    while (0)
 747 
 748 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 749 
 750 #define gl_recursive_lock_init(NAME) \
 751    do                                            \
 752      {                                           \
 753        if (glthread_recursive_lock_init (&NAME)) \
 754          abort ();                               \
 755      }                                           \
 756    while (0)
 757 #define gl_recursive_lock_lock(NAME) \
 758    do                                            \
 759      {                                           \
 760        if (glthread_recursive_lock_lock (&NAME)) \
 761          abort ();                               \
 762      }                                           \
 763    while (0)
 764 #define gl_recursive_lock_unlock(NAME) \
 765    do                                              \
 766      {                                             \
 767        if (glthread_recursive_lock_unlock (&NAME)) \
 768          abort ();                                 \
 769      }                                             \
 770    while (0)
 771 #define gl_recursive_lock_destroy(NAME) \
 772    do                                               \
 773      {                                              \
 774        if (glthread_recursive_lock_destroy (&NAME)) \
 775          abort ();                                  \
 776      }                                              \
 777    while (0)
 778 
 779 /* -------------------------- gl_once_t datatype -------------------------- */
 780 
 781 #define gl_once(NAME, INITFUNCTION) \
 782    do                                           \
 783      {                                          \
 784        if (glthread_once (&NAME, INITFUNCTION)) \
 785          abort ();                              \
 786      }                                          \
 787    while (0)
 788 
 789 /* ========================================================================= */
 790 
 791 #endif /* _LOCK_H */

/* [previous][next][first][last][top][bottom][index][help] */