1680a9cb8SJohn Marino /* Locking in multithreaded situations. 2*09d4459fSDaniel Fojt Copyright (C) 2005-2020 Free Software Foundation, Inc. 3680a9cb8SJohn Marino 4680a9cb8SJohn Marino This program is free software; you can redistribute it and/or modify 5680a9cb8SJohn Marino it under the terms of the GNU General Public License as published by 6680a9cb8SJohn Marino the Free Software Foundation; either version 3, or (at your option) 7680a9cb8SJohn Marino any later version. 8680a9cb8SJohn Marino 9680a9cb8SJohn Marino This program is distributed in the hope that it will be useful, 10680a9cb8SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 11680a9cb8SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12680a9cb8SJohn Marino GNU General Public License for more details. 13680a9cb8SJohn Marino 14680a9cb8SJohn Marino You should have received a copy of the GNU General Public License 15*09d4459fSDaniel Fojt along with this program; if not, see <https://www.gnu.org/licenses/>. */ 16680a9cb8SJohn Marino 17680a9cb8SJohn Marino /* Written by Bruno Haible <bruno@clisp.org>, 2005. 18*09d4459fSDaniel Fojt Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */ 19680a9cb8SJohn Marino 20680a9cb8SJohn Marino /* This file contains locking primitives for use with a given thread library. 21680a9cb8SJohn Marino It does not contain primitives for creating threads or for other 22680a9cb8SJohn Marino synchronization primitives. 23680a9cb8SJohn Marino 24680a9cb8SJohn Marino Normal (non-recursive) locks: 25680a9cb8SJohn Marino Type: gl_lock_t 26680a9cb8SJohn Marino Declaration: gl_lock_define(extern, name) 27680a9cb8SJohn Marino Initializer: gl_lock_define_initialized(, name) 28680a9cb8SJohn Marino Initialization: gl_lock_init (name); 29680a9cb8SJohn Marino Taking the lock: gl_lock_lock (name); 30680a9cb8SJohn Marino Releasing the lock: gl_lock_unlock (name); 31680a9cb8SJohn Marino De-initialization: gl_lock_destroy (name); 32680a9cb8SJohn Marino Equivalent functions with control of error handling: 33680a9cb8SJohn Marino Initialization: err = glthread_lock_init (&name); 34680a9cb8SJohn Marino Taking the lock: err = glthread_lock_lock (&name); 35680a9cb8SJohn Marino Releasing the lock: err = glthread_lock_unlock (&name); 36680a9cb8SJohn Marino De-initialization: err = glthread_lock_destroy (&name); 37680a9cb8SJohn Marino 38680a9cb8SJohn Marino Read-Write (non-recursive) locks: 39680a9cb8SJohn Marino Type: gl_rwlock_t 40680a9cb8SJohn Marino Declaration: gl_rwlock_define(extern, name) 41680a9cb8SJohn Marino Initializer: gl_rwlock_define_initialized(, name) 42680a9cb8SJohn Marino Initialization: gl_rwlock_init (name); 43680a9cb8SJohn Marino Taking the lock: gl_rwlock_rdlock (name); 44680a9cb8SJohn Marino gl_rwlock_wrlock (name); 45680a9cb8SJohn Marino Releasing the lock: gl_rwlock_unlock (name); 46680a9cb8SJohn Marino De-initialization: gl_rwlock_destroy (name); 47680a9cb8SJohn Marino Equivalent functions with control of error handling: 48680a9cb8SJohn Marino Initialization: err = glthread_rwlock_init (&name); 49680a9cb8SJohn Marino Taking the lock: err = glthread_rwlock_rdlock (&name); 50680a9cb8SJohn Marino err = glthread_rwlock_wrlock (&name); 51680a9cb8SJohn Marino Releasing the lock: err = glthread_rwlock_unlock (&name); 52680a9cb8SJohn Marino De-initialization: err = glthread_rwlock_destroy (&name); 53680a9cb8SJohn Marino 54680a9cb8SJohn Marino Recursive locks: 55680a9cb8SJohn Marino Type: gl_recursive_lock_t 56680a9cb8SJohn Marino Declaration: gl_recursive_lock_define(extern, name) 57680a9cb8SJohn Marino Initializer: gl_recursive_lock_define_initialized(, name) 58680a9cb8SJohn Marino Initialization: gl_recursive_lock_init (name); 59680a9cb8SJohn Marino Taking the lock: gl_recursive_lock_lock (name); 60680a9cb8SJohn Marino Releasing the lock: gl_recursive_lock_unlock (name); 61680a9cb8SJohn Marino De-initialization: gl_recursive_lock_destroy (name); 62680a9cb8SJohn Marino Equivalent functions with control of error handling: 63680a9cb8SJohn Marino Initialization: err = glthread_recursive_lock_init (&name); 64680a9cb8SJohn Marino Taking the lock: err = glthread_recursive_lock_lock (&name); 65680a9cb8SJohn Marino Releasing the lock: err = glthread_recursive_lock_unlock (&name); 66680a9cb8SJohn Marino De-initialization: err = glthread_recursive_lock_destroy (&name); 67680a9cb8SJohn Marino 68680a9cb8SJohn Marino Once-only execution: 69680a9cb8SJohn Marino Type: gl_once_t 70680a9cb8SJohn Marino Initializer: gl_once_define(extern, name) 71680a9cb8SJohn Marino Execution: gl_once (name, initfunction); 72680a9cb8SJohn Marino Equivalent functions with control of error handling: 73680a9cb8SJohn Marino Execution: err = glthread_once (&name, initfunction); 74680a9cb8SJohn Marino */ 75680a9cb8SJohn Marino 76680a9cb8SJohn Marino 77680a9cb8SJohn Marino #ifndef _LOCK_H 78680a9cb8SJohn Marino #define _LOCK_H 79680a9cb8SJohn Marino 80680a9cb8SJohn Marino #include <errno.h> 81680a9cb8SJohn Marino #include <stdlib.h> 82680a9cb8SJohn Marino 83*09d4459fSDaniel Fojt #if !defined c11_threads_in_use 84*09d4459fSDaniel Fojt # if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK 85*09d4459fSDaniel Fojt # include <threads.h> 86*09d4459fSDaniel Fojt # pragma weak thrd_exit 87*09d4459fSDaniel Fojt # define c11_threads_in_use() (thrd_exit != NULL) 88*09d4459fSDaniel Fojt # else 89*09d4459fSDaniel Fojt # define c11_threads_in_use() 0 90*09d4459fSDaniel Fojt # endif 91*09d4459fSDaniel Fojt #endif 92*09d4459fSDaniel Fojt 93*09d4459fSDaniel Fojt /* ========================================================================= */ 94*09d4459fSDaniel Fojt 95*09d4459fSDaniel Fojt #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS 96*09d4459fSDaniel Fojt 97*09d4459fSDaniel Fojt /* Use the ISO C threads library. */ 98*09d4459fSDaniel Fojt 99*09d4459fSDaniel Fojt # include <threads.h> 100*09d4459fSDaniel Fojt 101*09d4459fSDaniel Fojt # ifdef __cplusplus 102*09d4459fSDaniel Fojt extern "C" { 103*09d4459fSDaniel Fojt # endif 104*09d4459fSDaniel Fojt 105*09d4459fSDaniel Fojt /* -------------------------- gl_lock_t datatype -------------------------- */ 106*09d4459fSDaniel Fojt 107*09d4459fSDaniel Fojt typedef struct 108*09d4459fSDaniel Fojt { 109*09d4459fSDaniel Fojt int volatile init_needed; 110*09d4459fSDaniel Fojt once_flag init_once; 111*09d4459fSDaniel Fojt void (*init_func) (void); 112*09d4459fSDaniel Fojt mtx_t mutex; 113*09d4459fSDaniel Fojt } 114*09d4459fSDaniel Fojt gl_lock_t; 115*09d4459fSDaniel Fojt # define gl_lock_define(STORAGECLASS, NAME) \ 116*09d4459fSDaniel Fojt STORAGECLASS gl_lock_t NAME; 117*09d4459fSDaniel Fojt # define gl_lock_define_initialized(STORAGECLASS, NAME) \ 118*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void); \ 119*09d4459fSDaniel Fojt STORAGECLASS gl_lock_t NAME = \ 120*09d4459fSDaniel Fojt { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \ 121*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void) \ 122*09d4459fSDaniel Fojt { \ 123*09d4459fSDaniel Fojt if (glthread_lock_init (&(NAME))) \ 124*09d4459fSDaniel Fojt abort (); \ 125*09d4459fSDaniel Fojt } 126*09d4459fSDaniel Fojt extern int glthread_lock_init (gl_lock_t *lock); 127*09d4459fSDaniel Fojt extern int glthread_lock_lock (gl_lock_t *lock); 128*09d4459fSDaniel Fojt extern int glthread_lock_unlock (gl_lock_t *lock); 129*09d4459fSDaniel Fojt extern int glthread_lock_destroy (gl_lock_t *lock); 130*09d4459fSDaniel Fojt 131*09d4459fSDaniel Fojt /* ------------------------- gl_rwlock_t datatype ------------------------- */ 132*09d4459fSDaniel Fojt 133*09d4459fSDaniel Fojt typedef struct 134*09d4459fSDaniel Fojt { 135*09d4459fSDaniel Fojt int volatile init_needed; 136*09d4459fSDaniel Fojt once_flag init_once; 137*09d4459fSDaniel Fojt void (*init_func) (void); 138*09d4459fSDaniel Fojt mtx_t lock; /* protects the remaining fields */ 139*09d4459fSDaniel Fojt cnd_t waiting_readers; /* waiting readers */ 140*09d4459fSDaniel Fojt cnd_t waiting_writers; /* waiting writers */ 141*09d4459fSDaniel Fojt unsigned int waiting_writers_count; /* number of waiting writers */ 142*09d4459fSDaniel Fojt int runcount; /* number of readers running, or -1 when a writer runs */ 143*09d4459fSDaniel Fojt } 144*09d4459fSDaniel Fojt gl_rwlock_t; 145*09d4459fSDaniel Fojt # define gl_rwlock_define(STORAGECLASS, NAME) \ 146*09d4459fSDaniel Fojt STORAGECLASS gl_rwlock_t NAME; 147*09d4459fSDaniel Fojt # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 148*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void); \ 149*09d4459fSDaniel Fojt STORAGECLASS gl_rwlock_t NAME = \ 150*09d4459fSDaniel Fojt { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \ 151*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void) \ 152*09d4459fSDaniel Fojt { \ 153*09d4459fSDaniel Fojt if (glthread_rwlock_init (&(NAME))) \ 154*09d4459fSDaniel Fojt abort (); \ 155*09d4459fSDaniel Fojt } 156*09d4459fSDaniel Fojt extern int glthread_rwlock_init (gl_rwlock_t *lock); 157*09d4459fSDaniel Fojt extern int glthread_rwlock_rdlock (gl_rwlock_t *lock); 158*09d4459fSDaniel Fojt extern int glthread_rwlock_wrlock (gl_rwlock_t *lock); 159*09d4459fSDaniel Fojt extern int glthread_rwlock_unlock (gl_rwlock_t *lock); 160*09d4459fSDaniel Fojt extern int glthread_rwlock_destroy (gl_rwlock_t *lock); 161*09d4459fSDaniel Fojt 162*09d4459fSDaniel Fojt /* --------------------- gl_recursive_lock_t datatype --------------------- */ 163*09d4459fSDaniel Fojt 164*09d4459fSDaniel Fojt typedef struct 165*09d4459fSDaniel Fojt { 166*09d4459fSDaniel Fojt int volatile init_needed; 167*09d4459fSDaniel Fojt once_flag init_once; 168*09d4459fSDaniel Fojt void (*init_func) (void); 169*09d4459fSDaniel Fojt mtx_t mutex; 170*09d4459fSDaniel Fojt } 171*09d4459fSDaniel Fojt gl_recursive_lock_t; 172*09d4459fSDaniel Fojt # define gl_recursive_lock_define(STORAGECLASS, NAME) \ 173*09d4459fSDaniel Fojt STORAGECLASS gl_recursive_lock_t NAME; 174*09d4459fSDaniel Fojt # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 175*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void); \ 176*09d4459fSDaniel Fojt STORAGECLASS gl_recursive_lock_t NAME = \ 177*09d4459fSDaniel Fojt { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \ 178*09d4459fSDaniel Fojt static void _atomic_init_##NAME (void) \ 179*09d4459fSDaniel Fojt { \ 180*09d4459fSDaniel Fojt if (glthread_recursive_lock_init (&(NAME))) \ 181*09d4459fSDaniel Fojt abort (); \ 182*09d4459fSDaniel Fojt } 183*09d4459fSDaniel Fojt extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock); 184*09d4459fSDaniel Fojt extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock); 185*09d4459fSDaniel Fojt extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); 186*09d4459fSDaniel Fojt extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); 187*09d4459fSDaniel Fojt 188*09d4459fSDaniel Fojt /* -------------------------- gl_once_t datatype -------------------------- */ 189*09d4459fSDaniel Fojt 190*09d4459fSDaniel Fojt typedef once_flag gl_once_t; 191*09d4459fSDaniel Fojt # define gl_once_define(STORAGECLASS, NAME) \ 192*09d4459fSDaniel Fojt STORAGECLASS once_flag NAME = ONCE_FLAG_INIT; 193*09d4459fSDaniel Fojt # define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 194*09d4459fSDaniel Fojt (call_once (ONCE_CONTROL, INITFUNCTION), 0) 195*09d4459fSDaniel Fojt 196*09d4459fSDaniel Fojt # ifdef __cplusplus 197*09d4459fSDaniel Fojt } 198*09d4459fSDaniel Fojt # endif 199*09d4459fSDaniel Fojt 200*09d4459fSDaniel Fojt #endif 201*09d4459fSDaniel Fojt 202680a9cb8SJohn Marino /* ========================================================================= */ 203680a9cb8SJohn Marino 204680a9cb8SJohn Marino #if USE_POSIX_THREADS 205680a9cb8SJohn Marino 206680a9cb8SJohn Marino /* Use the POSIX threads library. */ 207680a9cb8SJohn Marino 208680a9cb8SJohn Marino # include <pthread.h> 209680a9cb8SJohn Marino 210680a9cb8SJohn Marino # ifdef __cplusplus 211680a9cb8SJohn Marino extern "C" { 212680a9cb8SJohn Marino # endif 213680a9cb8SJohn Marino 214680a9cb8SJohn Marino # if PTHREAD_IN_USE_DETECTION_HARD 215680a9cb8SJohn Marino 216680a9cb8SJohn Marino /* The pthread_in_use() detection needs to be done at runtime. */ 217680a9cb8SJohn Marino # define pthread_in_use() \ 218680a9cb8SJohn Marino glthread_in_use () 219680a9cb8SJohn Marino extern int glthread_in_use (void); 220680a9cb8SJohn Marino 221680a9cb8SJohn Marino # endif 222680a9cb8SJohn Marino 223680a9cb8SJohn Marino # if USE_POSIX_THREADS_WEAK 224680a9cb8SJohn Marino 225680a9cb8SJohn Marino /* Use weak references to the POSIX threads library. */ 226680a9cb8SJohn Marino 227680a9cb8SJohn Marino /* Weak references avoid dragging in external libraries if the other parts 228680a9cb8SJohn Marino of the program don't use them. Here we use them, because we don't want 229680a9cb8SJohn Marino every program that uses libintl to depend on libpthread. This assumes 230680a9cb8SJohn Marino that libpthread would not be loaded after libintl; i.e. if libintl is 231680a9cb8SJohn Marino loaded first, by an executable that does not depend on libpthread, and 232680a9cb8SJohn Marino then a module is dynamically loaded that depends on libpthread, libintl 233680a9cb8SJohn Marino will not be multithread-safe. */ 234680a9cb8SJohn Marino 235680a9cb8SJohn Marino /* The way to test at runtime whether libpthread is present is to test 236680a9cb8SJohn Marino whether a function pointer's value, such as &pthread_mutex_init, is 237680a9cb8SJohn Marino non-NULL. However, some versions of GCC have a bug through which, in 238680a9cb8SJohn Marino PIC mode, &foo != NULL always evaluates to true if there is a direct 239680a9cb8SJohn Marino call to foo(...) in the same function. To avoid this, we test the 240680a9cb8SJohn Marino address of a function in libpthread that we don't use. */ 241680a9cb8SJohn Marino 242680a9cb8SJohn Marino # pragma weak pthread_mutex_init 243680a9cb8SJohn Marino # pragma weak pthread_mutex_lock 244680a9cb8SJohn Marino # pragma weak pthread_mutex_unlock 245680a9cb8SJohn Marino # pragma weak pthread_mutex_destroy 246680a9cb8SJohn Marino # pragma weak pthread_rwlock_init 247680a9cb8SJohn Marino # pragma weak pthread_rwlock_rdlock 248680a9cb8SJohn Marino # pragma weak pthread_rwlock_wrlock 249680a9cb8SJohn Marino # pragma weak pthread_rwlock_unlock 250680a9cb8SJohn Marino # pragma weak pthread_rwlock_destroy 251680a9cb8SJohn Marino # pragma weak pthread_once 252680a9cb8SJohn Marino # pragma weak pthread_cond_init 253680a9cb8SJohn Marino # pragma weak pthread_cond_wait 254680a9cb8SJohn Marino # pragma weak pthread_cond_signal 255680a9cb8SJohn Marino # pragma weak pthread_cond_broadcast 256680a9cb8SJohn Marino # pragma weak pthread_cond_destroy 257680a9cb8SJohn Marino # pragma weak pthread_mutexattr_init 258680a9cb8SJohn Marino # pragma weak pthread_mutexattr_settype 259680a9cb8SJohn Marino # pragma weak pthread_mutexattr_destroy 260*09d4459fSDaniel Fojt # pragma weak pthread_rwlockattr_init 261*09d4459fSDaniel Fojt # if __GNU_LIBRARY__ > 1 262*09d4459fSDaniel Fojt # pragma weak pthread_rwlockattr_setkind_np 263*09d4459fSDaniel Fojt # endif 264*09d4459fSDaniel Fojt # pragma weak pthread_rwlockattr_destroy 265680a9cb8SJohn Marino # ifndef pthread_self 266680a9cb8SJohn Marino # pragma weak pthread_self 267680a9cb8SJohn Marino # endif 268680a9cb8SJohn Marino 269680a9cb8SJohn Marino # if !PTHREAD_IN_USE_DETECTION_HARD 270*09d4459fSDaniel Fojt /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols 271*09d4459fSDaniel Fojt can be used to determine whether libpthread is in use. These are: 272*09d4459fSDaniel Fojt pthread_mutexattr_gettype 273*09d4459fSDaniel Fojt pthread_rwlockattr_destroy 274*09d4459fSDaniel Fojt pthread_rwlockattr_init 275*09d4459fSDaniel Fojt */ 276*09d4459fSDaniel Fojt # pragma weak pthread_mutexattr_gettype 277*09d4459fSDaniel Fojt # define pthread_in_use() \ 278*09d4459fSDaniel Fojt (pthread_mutexattr_gettype != NULL || c11_threads_in_use ()) 279680a9cb8SJohn Marino # endif 280680a9cb8SJohn Marino 281680a9cb8SJohn Marino # else 282680a9cb8SJohn Marino 283680a9cb8SJohn Marino # if !PTHREAD_IN_USE_DETECTION_HARD 284680a9cb8SJohn Marino # define pthread_in_use() 1 285680a9cb8SJohn Marino # endif 286680a9cb8SJohn Marino 287680a9cb8SJohn Marino # endif 288680a9cb8SJohn Marino 289680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */ 290680a9cb8SJohn Marino 291680a9cb8SJohn Marino typedef pthread_mutex_t gl_lock_t; 292680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME) \ 293680a9cb8SJohn Marino STORAGECLASS pthread_mutex_t NAME; 294680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME) \ 295680a9cb8SJohn Marino STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer; 296680a9cb8SJohn Marino # define gl_lock_initializer \ 297680a9cb8SJohn Marino PTHREAD_MUTEX_INITIALIZER 298680a9cb8SJohn Marino # define glthread_lock_init(LOCK) \ 299680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0) 300680a9cb8SJohn Marino # define glthread_lock_lock(LOCK) \ 301680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) 302680a9cb8SJohn Marino # define glthread_lock_unlock(LOCK) \ 303680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) 304680a9cb8SJohn Marino # define glthread_lock_destroy(LOCK) \ 305680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) 306680a9cb8SJohn Marino 307680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */ 308680a9cb8SJohn Marino 309*09d4459fSDaniel Fojt # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1))) 310680a9cb8SJohn Marino 311*09d4459fSDaniel Fojt # if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP 312680a9cb8SJohn Marino 313680a9cb8SJohn Marino typedef pthread_rwlock_t gl_rwlock_t; 314680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \ 315680a9cb8SJohn Marino STORAGECLASS pthread_rwlock_t NAME; 316680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 317680a9cb8SJohn Marino STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; 318*09d4459fSDaniel Fojt # if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER 319*09d4459fSDaniel Fojt # if defined PTHREAD_RWLOCK_INITIALIZER 320680a9cb8SJohn Marino # define gl_rwlock_initializer \ 321680a9cb8SJohn Marino PTHREAD_RWLOCK_INITIALIZER 322*09d4459fSDaniel Fojt # else 323*09d4459fSDaniel Fojt # define gl_rwlock_initializer \ 324*09d4459fSDaniel Fojt PTHREAD_RWLOCK_INITIALIZER_NP 325*09d4459fSDaniel Fojt # endif 326680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \ 327680a9cb8SJohn Marino (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) 328*09d4459fSDaniel Fojt # else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */ 329*09d4459fSDaniel Fojt # define gl_rwlock_initializer \ 330*09d4459fSDaniel Fojt PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP 331*09d4459fSDaniel Fojt # define glthread_rwlock_init(LOCK) \ 332*09d4459fSDaniel Fojt (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0) 333*09d4459fSDaniel Fojt extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock); 334*09d4459fSDaniel Fojt # endif 335680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \ 336680a9cb8SJohn Marino (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) 337680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \ 338680a9cb8SJohn Marino (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0) 339680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \ 340680a9cb8SJohn Marino (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0) 341680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \ 342680a9cb8SJohn Marino (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0) 343680a9cb8SJohn Marino 344680a9cb8SJohn Marino # else 345680a9cb8SJohn Marino 346680a9cb8SJohn Marino typedef struct 347680a9cb8SJohn Marino { 348680a9cb8SJohn Marino int initialized; 349680a9cb8SJohn Marino pthread_mutex_t guard; /* protects the initialization */ 350680a9cb8SJohn Marino pthread_rwlock_t rwlock; /* read-write lock */ 351680a9cb8SJohn Marino } 352680a9cb8SJohn Marino gl_rwlock_t; 353680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \ 354680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME; 355680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 356680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; 357680a9cb8SJohn Marino # define gl_rwlock_initializer \ 358680a9cb8SJohn Marino { 0, PTHREAD_MUTEX_INITIALIZER } 359680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \ 360680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) 361680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \ 362680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) 363680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \ 364680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) 365680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \ 366680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) 367680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \ 368680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) 369680a9cb8SJohn Marino extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); 370680a9cb8SJohn Marino extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); 371680a9cb8SJohn Marino extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); 372680a9cb8SJohn Marino extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); 373680a9cb8SJohn Marino extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); 374680a9cb8SJohn Marino 375680a9cb8SJohn Marino # endif 376680a9cb8SJohn Marino 377680a9cb8SJohn Marino # else 378680a9cb8SJohn Marino 379680a9cb8SJohn Marino typedef struct 380680a9cb8SJohn Marino { 381680a9cb8SJohn Marino pthread_mutex_t lock; /* protects the remaining fields */ 382680a9cb8SJohn Marino pthread_cond_t waiting_readers; /* waiting readers */ 383680a9cb8SJohn Marino pthread_cond_t waiting_writers; /* waiting writers */ 384680a9cb8SJohn Marino unsigned int waiting_writers_count; /* number of waiting writers */ 385680a9cb8SJohn Marino int runcount; /* number of readers running, or -1 when a writer runs */ 386680a9cb8SJohn Marino } 387680a9cb8SJohn Marino gl_rwlock_t; 388680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \ 389680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME; 390680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 391680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; 392680a9cb8SJohn Marino # define gl_rwlock_initializer \ 393680a9cb8SJohn Marino { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } 394680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \ 395680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) 396680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \ 397680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) 398680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \ 399680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) 400680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \ 401680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) 402680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \ 403680a9cb8SJohn Marino (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) 404680a9cb8SJohn Marino extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); 405680a9cb8SJohn Marino extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); 406680a9cb8SJohn Marino extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); 407680a9cb8SJohn Marino extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); 408680a9cb8SJohn Marino extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); 409680a9cb8SJohn Marino 410680a9cb8SJohn Marino # endif 411680a9cb8SJohn Marino 412680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */ 413680a9cb8SJohn Marino 414680a9cb8SJohn Marino # if HAVE_PTHREAD_MUTEX_RECURSIVE 415680a9cb8SJohn Marino 416680a9cb8SJohn Marino # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 417680a9cb8SJohn Marino 418680a9cb8SJohn Marino typedef pthread_mutex_t gl_recursive_lock_t; 419680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) \ 420680a9cb8SJohn Marino STORAGECLASS pthread_mutex_t NAME; 421680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 422680a9cb8SJohn Marino STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer; 423680a9cb8SJohn Marino # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER 424680a9cb8SJohn Marino # define gl_recursive_lock_initializer \ 425680a9cb8SJohn Marino PTHREAD_RECURSIVE_MUTEX_INITIALIZER 426680a9cb8SJohn Marino # else 427680a9cb8SJohn Marino # define gl_recursive_lock_initializer \ 428680a9cb8SJohn Marino PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 429680a9cb8SJohn Marino # endif 430680a9cb8SJohn Marino # define glthread_recursive_lock_init(LOCK) \ 431680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) 432680a9cb8SJohn Marino # define glthread_recursive_lock_lock(LOCK) \ 433680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) 434680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(LOCK) \ 435680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) 436680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(LOCK) \ 437680a9cb8SJohn Marino (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) 438680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); 439680a9cb8SJohn Marino 440680a9cb8SJohn Marino # else 441680a9cb8SJohn Marino 442680a9cb8SJohn Marino typedef struct 443680a9cb8SJohn Marino { 444680a9cb8SJohn Marino pthread_mutex_t recmutex; /* recursive mutex */ 445680a9cb8SJohn Marino pthread_mutex_t guard; /* protects the initialization */ 446680a9cb8SJohn Marino int initialized; 447680a9cb8SJohn Marino } 448680a9cb8SJohn Marino gl_recursive_lock_t; 449680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) \ 450680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME; 451680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 452680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; 453680a9cb8SJohn Marino # define gl_recursive_lock_initializer \ 454680a9cb8SJohn Marino { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 } 455680a9cb8SJohn Marino # define glthread_recursive_lock_init(LOCK) \ 456680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) 457680a9cb8SJohn Marino # define glthread_recursive_lock_lock(LOCK) \ 458680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) 459680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(LOCK) \ 460680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) 461680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(LOCK) \ 462680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) 463680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); 464680a9cb8SJohn Marino extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); 465680a9cb8SJohn Marino extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); 466680a9cb8SJohn Marino extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); 467680a9cb8SJohn Marino 468680a9cb8SJohn Marino # endif 469680a9cb8SJohn Marino 470680a9cb8SJohn Marino # else 471680a9cb8SJohn Marino 472680a9cb8SJohn Marino /* Old versions of POSIX threads on Solaris did not have recursive locks. 473680a9cb8SJohn Marino We have to implement them ourselves. */ 474680a9cb8SJohn Marino 475680a9cb8SJohn Marino typedef struct 476680a9cb8SJohn Marino { 477680a9cb8SJohn Marino pthread_mutex_t mutex; 478680a9cb8SJohn Marino pthread_t owner; 479680a9cb8SJohn Marino unsigned long depth; 480680a9cb8SJohn Marino } 481680a9cb8SJohn Marino gl_recursive_lock_t; 482680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) \ 483680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME; 484680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 485680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; 486680a9cb8SJohn Marino # define gl_recursive_lock_initializer \ 487680a9cb8SJohn Marino { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 } 488680a9cb8SJohn Marino # define glthread_recursive_lock_init(LOCK) \ 489680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) 490680a9cb8SJohn Marino # define glthread_recursive_lock_lock(LOCK) \ 491680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) 492680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(LOCK) \ 493680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) 494680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(LOCK) \ 495680a9cb8SJohn Marino (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) 496680a9cb8SJohn Marino extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); 497680a9cb8SJohn Marino extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); 498680a9cb8SJohn Marino extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); 499680a9cb8SJohn Marino extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); 500680a9cb8SJohn Marino 501680a9cb8SJohn Marino # endif 502680a9cb8SJohn Marino 503680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */ 504680a9cb8SJohn Marino 505680a9cb8SJohn Marino typedef pthread_once_t gl_once_t; 506680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \ 507680a9cb8SJohn Marino STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; 508680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 509680a9cb8SJohn Marino (pthread_in_use () \ 510680a9cb8SJohn Marino ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ 511680a9cb8SJohn Marino : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) 512680a9cb8SJohn Marino extern int glthread_once_singlethreaded (pthread_once_t *once_control); 513680a9cb8SJohn Marino 514680a9cb8SJohn Marino # ifdef __cplusplus 515680a9cb8SJohn Marino } 516680a9cb8SJohn Marino # endif 517680a9cb8SJohn Marino 518680a9cb8SJohn Marino #endif 519680a9cb8SJohn Marino 520680a9cb8SJohn Marino /* ========================================================================= */ 521680a9cb8SJohn Marino 522680a9cb8SJohn Marino #if USE_WINDOWS_THREADS 523680a9cb8SJohn Marino 524680a9cb8SJohn Marino # define WIN32_LEAN_AND_MEAN /* avoid including junk */ 525680a9cb8SJohn Marino # include <windows.h> 526680a9cb8SJohn Marino 527*09d4459fSDaniel Fojt # include "windows-mutex.h" 528*09d4459fSDaniel Fojt # include "windows-rwlock.h" 529*09d4459fSDaniel Fojt # include "windows-recmutex.h" 530*09d4459fSDaniel Fojt # include "windows-once.h" 531*09d4459fSDaniel Fojt 532680a9cb8SJohn Marino # ifdef __cplusplus 533680a9cb8SJohn Marino extern "C" { 534680a9cb8SJohn Marino # endif 535680a9cb8SJohn Marino 536680a9cb8SJohn Marino /* We can use CRITICAL_SECTION directly, rather than the native Windows Event, 537680a9cb8SJohn Marino Mutex, Semaphore types, because 538680a9cb8SJohn Marino - we need only to synchronize inside a single process (address space), 539680a9cb8SJohn Marino not inter-process locking, 540680a9cb8SJohn Marino - we don't need to support trylock operations. (TryEnterCriticalSection 541680a9cb8SJohn Marino does not work on Windows 95/98/ME. Packages that need trylock usually 542680a9cb8SJohn Marino define their own mutex type.) */ 543680a9cb8SJohn Marino 544680a9cb8SJohn Marino /* There is no way to statically initialize a CRITICAL_SECTION. It needs 545680a9cb8SJohn Marino to be done lazily, once only. For this we need spinlocks. */ 546680a9cb8SJohn Marino 547680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */ 548680a9cb8SJohn Marino 549*09d4459fSDaniel Fojt typedef glwthread_mutex_t gl_lock_t; 550680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME) \ 551680a9cb8SJohn Marino STORAGECLASS gl_lock_t NAME; 552680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME) \ 553680a9cb8SJohn Marino STORAGECLASS gl_lock_t NAME = gl_lock_initializer; 554680a9cb8SJohn Marino # define gl_lock_initializer \ 555*09d4459fSDaniel Fojt GLWTHREAD_MUTEX_INIT 556680a9cb8SJohn Marino # define glthread_lock_init(LOCK) \ 557*09d4459fSDaniel Fojt (glwthread_mutex_init (LOCK), 0) 558680a9cb8SJohn Marino # define glthread_lock_lock(LOCK) \ 559*09d4459fSDaniel Fojt glwthread_mutex_lock (LOCK) 560680a9cb8SJohn Marino # define glthread_lock_unlock(LOCK) \ 561*09d4459fSDaniel Fojt glwthread_mutex_unlock (LOCK) 562680a9cb8SJohn Marino # define glthread_lock_destroy(LOCK) \ 563*09d4459fSDaniel Fojt glwthread_mutex_destroy (LOCK) 564680a9cb8SJohn Marino 565680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */ 566680a9cb8SJohn Marino 567*09d4459fSDaniel Fojt typedef glwthread_rwlock_t gl_rwlock_t; 568680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) \ 569680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME; 570680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 571680a9cb8SJohn Marino STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; 572680a9cb8SJohn Marino # define gl_rwlock_initializer \ 573*09d4459fSDaniel Fojt GLWTHREAD_RWLOCK_INIT 574680a9cb8SJohn Marino # define glthread_rwlock_init(LOCK) \ 575*09d4459fSDaniel Fojt (glwthread_rwlock_init (LOCK), 0) 576680a9cb8SJohn Marino # define glthread_rwlock_rdlock(LOCK) \ 577*09d4459fSDaniel Fojt glwthread_rwlock_rdlock (LOCK) 578680a9cb8SJohn Marino # define glthread_rwlock_wrlock(LOCK) \ 579*09d4459fSDaniel Fojt glwthread_rwlock_wrlock (LOCK) 580680a9cb8SJohn Marino # define glthread_rwlock_unlock(LOCK) \ 581*09d4459fSDaniel Fojt glwthread_rwlock_unlock (LOCK) 582680a9cb8SJohn Marino # define glthread_rwlock_destroy(LOCK) \ 583*09d4459fSDaniel Fojt glwthread_rwlock_destroy (LOCK) 584680a9cb8SJohn Marino 585680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */ 586680a9cb8SJohn Marino 587*09d4459fSDaniel Fojt typedef glwthread_recmutex_t gl_recursive_lock_t; 588680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) \ 589680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME; 590680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 591680a9cb8SJohn Marino STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; 592680a9cb8SJohn Marino # define gl_recursive_lock_initializer \ 593*09d4459fSDaniel Fojt GLWTHREAD_RECMUTEX_INIT 594680a9cb8SJohn Marino # define glthread_recursive_lock_init(LOCK) \ 595*09d4459fSDaniel Fojt (glwthread_recmutex_init (LOCK), 0) 596680a9cb8SJohn Marino # define glthread_recursive_lock_lock(LOCK) \ 597*09d4459fSDaniel Fojt glwthread_recmutex_lock (LOCK) 598680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(LOCK) \ 599*09d4459fSDaniel Fojt glwthread_recmutex_unlock (LOCK) 600680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(LOCK) \ 601*09d4459fSDaniel Fojt glwthread_recmutex_destroy (LOCK) 602680a9cb8SJohn Marino 603680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */ 604680a9cb8SJohn Marino 605*09d4459fSDaniel Fojt typedef glwthread_once_t gl_once_t; 606680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \ 607*09d4459fSDaniel Fojt STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT; 608680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 609*09d4459fSDaniel Fojt (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0) 610680a9cb8SJohn Marino 611680a9cb8SJohn Marino # ifdef __cplusplus 612680a9cb8SJohn Marino } 613680a9cb8SJohn Marino # endif 614680a9cb8SJohn Marino 615680a9cb8SJohn Marino #endif 616680a9cb8SJohn Marino 617680a9cb8SJohn Marino /* ========================================================================= */ 618680a9cb8SJohn Marino 619*09d4459fSDaniel Fojt #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS) 620680a9cb8SJohn Marino 621680a9cb8SJohn Marino /* Provide dummy implementation if threads are not supported. */ 622680a9cb8SJohn Marino 623680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */ 624680a9cb8SJohn Marino 625680a9cb8SJohn Marino typedef int gl_lock_t; 626680a9cb8SJohn Marino # define gl_lock_define(STORAGECLASS, NAME) 627680a9cb8SJohn Marino # define gl_lock_define_initialized(STORAGECLASS, NAME) 628680a9cb8SJohn Marino # define glthread_lock_init(NAME) 0 629680a9cb8SJohn Marino # define glthread_lock_lock(NAME) 0 630680a9cb8SJohn Marino # define glthread_lock_unlock(NAME) 0 631680a9cb8SJohn Marino # define glthread_lock_destroy(NAME) 0 632680a9cb8SJohn Marino 633680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */ 634680a9cb8SJohn Marino 635680a9cb8SJohn Marino typedef int gl_rwlock_t; 636680a9cb8SJohn Marino # define gl_rwlock_define(STORAGECLASS, NAME) 637680a9cb8SJohn Marino # define gl_rwlock_define_initialized(STORAGECLASS, NAME) 638680a9cb8SJohn Marino # define glthread_rwlock_init(NAME) 0 639680a9cb8SJohn Marino # define glthread_rwlock_rdlock(NAME) 0 640680a9cb8SJohn Marino # define glthread_rwlock_wrlock(NAME) 0 641680a9cb8SJohn Marino # define glthread_rwlock_unlock(NAME) 0 642680a9cb8SJohn Marino # define glthread_rwlock_destroy(NAME) 0 643680a9cb8SJohn Marino 644680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */ 645680a9cb8SJohn Marino 646680a9cb8SJohn Marino typedef int gl_recursive_lock_t; 647680a9cb8SJohn Marino # define gl_recursive_lock_define(STORAGECLASS, NAME) 648680a9cb8SJohn Marino # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) 649680a9cb8SJohn Marino # define glthread_recursive_lock_init(NAME) 0 650680a9cb8SJohn Marino # define glthread_recursive_lock_lock(NAME) 0 651680a9cb8SJohn Marino # define glthread_recursive_lock_unlock(NAME) 0 652680a9cb8SJohn Marino # define glthread_recursive_lock_destroy(NAME) 0 653680a9cb8SJohn Marino 654680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */ 655680a9cb8SJohn Marino 656680a9cb8SJohn Marino typedef int gl_once_t; 657680a9cb8SJohn Marino # define gl_once_define(STORAGECLASS, NAME) \ 658680a9cb8SJohn Marino STORAGECLASS gl_once_t NAME = 0; 659680a9cb8SJohn Marino # define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 660680a9cb8SJohn Marino (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) 661680a9cb8SJohn Marino 662680a9cb8SJohn Marino #endif 663680a9cb8SJohn Marino 664680a9cb8SJohn Marino /* ========================================================================= */ 665680a9cb8SJohn Marino 666680a9cb8SJohn Marino /* Macros with built-in error handling. */ 667680a9cb8SJohn Marino 668680a9cb8SJohn Marino /* -------------------------- gl_lock_t datatype -------------------------- */ 669680a9cb8SJohn Marino 670680a9cb8SJohn Marino #define gl_lock_init(NAME) \ 671680a9cb8SJohn Marino do \ 672680a9cb8SJohn Marino { \ 673680a9cb8SJohn Marino if (glthread_lock_init (&NAME)) \ 674680a9cb8SJohn Marino abort (); \ 675680a9cb8SJohn Marino } \ 676680a9cb8SJohn Marino while (0) 677680a9cb8SJohn Marino #define gl_lock_lock(NAME) \ 678680a9cb8SJohn Marino do \ 679680a9cb8SJohn Marino { \ 680680a9cb8SJohn Marino if (glthread_lock_lock (&NAME)) \ 681680a9cb8SJohn Marino abort (); \ 682680a9cb8SJohn Marino } \ 683680a9cb8SJohn Marino while (0) 684680a9cb8SJohn Marino #define gl_lock_unlock(NAME) \ 685680a9cb8SJohn Marino do \ 686680a9cb8SJohn Marino { \ 687680a9cb8SJohn Marino if (glthread_lock_unlock (&NAME)) \ 688680a9cb8SJohn Marino abort (); \ 689680a9cb8SJohn Marino } \ 690680a9cb8SJohn Marino while (0) 691680a9cb8SJohn Marino #define gl_lock_destroy(NAME) \ 692680a9cb8SJohn Marino do \ 693680a9cb8SJohn Marino { \ 694680a9cb8SJohn Marino if (glthread_lock_destroy (&NAME)) \ 695680a9cb8SJohn Marino abort (); \ 696680a9cb8SJohn Marino } \ 697680a9cb8SJohn Marino while (0) 698680a9cb8SJohn Marino 699680a9cb8SJohn Marino /* ------------------------- gl_rwlock_t datatype ------------------------- */ 700680a9cb8SJohn Marino 701680a9cb8SJohn Marino #define gl_rwlock_init(NAME) \ 702680a9cb8SJohn Marino do \ 703680a9cb8SJohn Marino { \ 704680a9cb8SJohn Marino if (glthread_rwlock_init (&NAME)) \ 705680a9cb8SJohn Marino abort (); \ 706680a9cb8SJohn Marino } \ 707680a9cb8SJohn Marino while (0) 708680a9cb8SJohn Marino #define gl_rwlock_rdlock(NAME) \ 709680a9cb8SJohn Marino do \ 710680a9cb8SJohn Marino { \ 711680a9cb8SJohn Marino if (glthread_rwlock_rdlock (&NAME)) \ 712680a9cb8SJohn Marino abort (); \ 713680a9cb8SJohn Marino } \ 714680a9cb8SJohn Marino while (0) 715680a9cb8SJohn Marino #define gl_rwlock_wrlock(NAME) \ 716680a9cb8SJohn Marino do \ 717680a9cb8SJohn Marino { \ 718680a9cb8SJohn Marino if (glthread_rwlock_wrlock (&NAME)) \ 719680a9cb8SJohn Marino abort (); \ 720680a9cb8SJohn Marino } \ 721680a9cb8SJohn Marino while (0) 722680a9cb8SJohn Marino #define gl_rwlock_unlock(NAME) \ 723680a9cb8SJohn Marino do \ 724680a9cb8SJohn Marino { \ 725680a9cb8SJohn Marino if (glthread_rwlock_unlock (&NAME)) \ 726680a9cb8SJohn Marino abort (); \ 727680a9cb8SJohn Marino } \ 728680a9cb8SJohn Marino while (0) 729680a9cb8SJohn Marino #define gl_rwlock_destroy(NAME) \ 730680a9cb8SJohn Marino do \ 731680a9cb8SJohn Marino { \ 732680a9cb8SJohn Marino if (glthread_rwlock_destroy (&NAME)) \ 733680a9cb8SJohn Marino abort (); \ 734680a9cb8SJohn Marino } \ 735680a9cb8SJohn Marino while (0) 736680a9cb8SJohn Marino 737680a9cb8SJohn Marino /* --------------------- gl_recursive_lock_t datatype --------------------- */ 738680a9cb8SJohn Marino 739680a9cb8SJohn Marino #define gl_recursive_lock_init(NAME) \ 740680a9cb8SJohn Marino do \ 741680a9cb8SJohn Marino { \ 742680a9cb8SJohn Marino if (glthread_recursive_lock_init (&NAME)) \ 743680a9cb8SJohn Marino abort (); \ 744680a9cb8SJohn Marino } \ 745680a9cb8SJohn Marino while (0) 746680a9cb8SJohn Marino #define gl_recursive_lock_lock(NAME) \ 747680a9cb8SJohn Marino do \ 748680a9cb8SJohn Marino { \ 749680a9cb8SJohn Marino if (glthread_recursive_lock_lock (&NAME)) \ 750680a9cb8SJohn Marino abort (); \ 751680a9cb8SJohn Marino } \ 752680a9cb8SJohn Marino while (0) 753680a9cb8SJohn Marino #define gl_recursive_lock_unlock(NAME) \ 754680a9cb8SJohn Marino do \ 755680a9cb8SJohn Marino { \ 756680a9cb8SJohn Marino if (glthread_recursive_lock_unlock (&NAME)) \ 757680a9cb8SJohn Marino abort (); \ 758680a9cb8SJohn Marino } \ 759680a9cb8SJohn Marino while (0) 760680a9cb8SJohn Marino #define gl_recursive_lock_destroy(NAME) \ 761680a9cb8SJohn Marino do \ 762680a9cb8SJohn Marino { \ 763680a9cb8SJohn Marino if (glthread_recursive_lock_destroy (&NAME)) \ 764680a9cb8SJohn Marino abort (); \ 765680a9cb8SJohn Marino } \ 766680a9cb8SJohn Marino while (0) 767680a9cb8SJohn Marino 768680a9cb8SJohn Marino /* -------------------------- gl_once_t datatype -------------------------- */ 769680a9cb8SJohn Marino 770680a9cb8SJohn Marino #define gl_once(NAME, INITFUNCTION) \ 771680a9cb8SJohn Marino do \ 772680a9cb8SJohn Marino { \ 773680a9cb8SJohn Marino if (glthread_once (&NAME, INITFUNCTION)) \ 774680a9cb8SJohn Marino abort (); \ 775680a9cb8SJohn Marino } \ 776680a9cb8SJohn Marino while (0) 777680a9cb8SJohn Marino 778680a9cb8SJohn Marino /* ========================================================================= */ 779680a9cb8SJohn Marino 780680a9cb8SJohn Marino #endif /* _LOCK_H */ 781