1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105 |
- /* Locking in multithreaded situations.
- Copyright (C) 2005-2007 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA. */
- /* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
- gthr-win32.h. */
- /* This file contains locking primitives for use with a given thread library.
- It does not contain primitives for creating threads or for other
- synchronization primitives.
- Normal (non-recursive) locks:
- Type: gl_lock_t
- Declaration: gl_lock_define(extern, name)
- Initializer: gl_lock_define_initialized(, name)
- Initialization: gl_lock_init (name);
- Taking the lock: gl_lock_lock (name);
- Releasing the lock: gl_lock_unlock (name);
- De-initialization: gl_lock_destroy (name);
- Read-Write (non-recursive) locks:
- Type: gl_rwlock_t
- Declaration: gl_rwlock_define(extern, name)
- Initializer: gl_rwlock_define_initialized(, name)
- Initialization: gl_rwlock_init (name);
- Taking the lock: gl_rwlock_rdlock (name);
- gl_rwlock_wrlock (name);
- Releasing the lock: gl_rwlock_unlock (name);
- De-initialization: gl_rwlock_destroy (name);
- Recursive locks:
- Type: gl_recursive_lock_t
- Declaration: gl_recursive_lock_define(extern, name)
- Initializer: gl_recursive_lock_define_initialized(, name)
- Initialization: gl_recursive_lock_init (name);
- Taking the lock: gl_recursive_lock_lock (name);
- Releasing the lock: gl_recursive_lock_unlock (name);
- De-initialization: gl_recursive_lock_destroy (name);
- Once-only execution:
- Type: gl_once_t
- Initializer: gl_once_define(extern, name)
- Execution: gl_once (name, initfunction);
- */
- #ifndef _LOCK_H
- #define _LOCK_H
- /* ========================================================================= */
- #if USE_POSIX_THREADS
- /* Use the POSIX threads library. */
- # include <pthread.h>
- # include <stdlib.h>
- # ifdef __cplusplus
- extern "C" {
- # endif
- # if PTHREAD_IN_USE_DETECTION_HARD
- /* The pthread_in_use() detection needs to be done at runtime. */
- # define pthread_in_use() \
- glthread_in_use ()
- extern int glthread_in_use (void);
- # endif
- # if USE_POSIX_THREADS_WEAK
- /* Use weak references to the POSIX threads library. */
- /* Weak references avoid dragging in external libraries if the other parts
- of the program don't use them. Here we use them, because we don't want
- every program that uses libintl to depend on libpthread. This assumes
- that libpthread would not be loaded after libintl; i.e. if libintl is
- loaded first, by an executable that does not depend on libpthread, and
- then a module is dynamically loaded that depends on libpthread, libintl
- will not be multithread-safe. */
- /* The way to test at runtime whether libpthread is present is to test
- whether a function pointer's value, such as &pthread_mutex_init, is
- non-NULL. However, some versions of GCC have a bug through which, in
- PIC mode, &foo != NULL always evaluates to true if there is a direct
- call to foo(...) in the same function. To avoid this, we test the
- address of a function in libpthread that we don't use. */
- # pragma weak pthread_mutex_init
- # pragma weak pthread_mutex_lock
- # pragma weak pthread_mutex_unlock
- # pragma weak pthread_mutex_destroy
- # pragma weak pthread_rwlock_init
- # pragma weak pthread_rwlock_rdlock
- # pragma weak pthread_rwlock_wrlock
- # pragma weak pthread_rwlock_unlock
- # pragma weak pthread_rwlock_destroy
- # pragma weak pthread_once
- # pragma weak pthread_cond_init
- # pragma weak pthread_cond_wait
- # pragma weak pthread_cond_signal
- # pragma weak pthread_cond_broadcast
- # pragma weak pthread_cond_destroy
- # pragma weak pthread_mutexattr_init
- # pragma weak pthread_mutexattr_settype
- # pragma weak pthread_mutexattr_destroy
- # ifndef pthread_self
- # pragma weak pthread_self
- # endif
- # if !PTHREAD_IN_USE_DETECTION_HARD
- # pragma weak pthread_cancel
- # define pthread_in_use() (pthread_cancel != NULL)
- # endif
- # else
- # if !PTHREAD_IN_USE_DETECTION_HARD
- # define pthread_in_use() 1
- # endif
- # endif
- /* -------------------------- gl_lock_t datatype -------------------------- */
- typedef pthread_mutex_t gl_lock_t;
- # define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME;
- # define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
- # define gl_lock_initializer \
- PTHREAD_MUTEX_INITIALIZER
- # define gl_lock_init(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_lock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- /* ------------------------- gl_rwlock_t datatype ------------------------- */
- # if HAVE_PTHREAD_RWLOCK
- # ifdef PTHREAD_RWLOCK_INITIALIZER
- typedef pthread_rwlock_t gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- PTHREAD_RWLOCK_INITIALIZER
- # define gl_rwlock_init(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # else
- typedef struct
- {
- int initialized;
- pthread_mutex_t guard; /* protects the initialization */
- pthread_rwlock_t rwlock; /* read-write lock */
- }
- gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- { 0, PTHREAD_MUTEX_INITIALIZER }
- # define gl_rwlock_init(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_init (&NAME); \
- } \
- while (0)
- # define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_rdlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_wrlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_unlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_destroy (&NAME); \
- } \
- while (0)
- extern void glthread_rwlock_init (gl_rwlock_t *lock);
- extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
- # endif
- # else
- typedef struct
- {
- pthread_mutex_t lock; /* protects the remaining fields */
- pthread_cond_t waiting_readers; /* waiting readers */
- pthread_cond_t waiting_writers; /* waiting writers */
- unsigned int waiting_writers_count; /* number of waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
- # define gl_rwlock_init(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_init (&NAME); \
- } \
- while (0)
- # define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_rdlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_wrlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_unlock (&NAME); \
- } \
- while (0)
- # define gl_rwlock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_rwlock_destroy (&NAME); \
- } \
- while (0)
- extern void glthread_rwlock_init (gl_rwlock_t *lock);
- extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
- # endif
- /* --------------------- gl_recursive_lock_t datatype --------------------- */
- # if HAVE_PTHREAD_MUTEX_RECURSIVE
- # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
- typedef pthread_mutex_t gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
- # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
- # define gl_recursive_lock_initializer \
- PTHREAD_RECURSIVE_MUTEX_INITIALIZER
- # else
- # define gl_recursive_lock_initializer \
- PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
- # endif
- # define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # else
- typedef struct
- {
- pthread_mutex_t recmutex; /* recursive mutex */
- pthread_mutex_t guard; /* protects the initialization */
- int initialized;
- }
- gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
- # define gl_recursive_lock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
- # define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_init (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_lock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_unlock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_destroy (&NAME); \
- } \
- while (0)
- extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
- # endif
- # else
- /* Old versions of POSIX threads on Solaris did not have recursive locks.
- We have to implement them ourselves. */
- typedef struct
- {
- pthread_mutex_t mutex;
- pthread_t owner;
- unsigned long depth;
- }
- gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
- # define gl_recursive_lock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
- # define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_init (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_lock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_unlock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_destroy(NAME) \
- do \
- { \
- if (pthread_in_use ()) \
- glthread_recursive_lock_destroy (&NAME); \
- } \
- while (0)
- extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
- # endif
- /* -------------------------- gl_once_t datatype -------------------------- */
- typedef pthread_once_t gl_once_t;
- # define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
- # define gl_once(NAME, INITFUNCTION) \
- do \
- { \
- if (pthread_in_use ()) \
- { \
- if (pthread_once (&NAME, INITFUNCTION) != 0) \
- abort (); \
- } \
- else \
- { \
- if (glthread_once_singlethreaded (&NAME)) \
- INITFUNCTION (); \
- } \
- } \
- while (0)
- extern int glthread_once_singlethreaded (pthread_once_t *once_control);
- # ifdef __cplusplus
- }
- # endif
- #endif
- /* ========================================================================= */
- #if USE_PTH_THREADS
- /* Use the GNU Pth threads library. */
- # include <pth.h>
- # include <stdlib.h>
- # ifdef __cplusplus
- extern "C" {
- # endif
- # if USE_PTH_THREADS_WEAK
- /* Use weak references to the GNU Pth threads library. */
- # pragma weak pth_mutex_init
- # pragma weak pth_mutex_acquire
- # pragma weak pth_mutex_release
- # pragma weak pth_rwlock_init
- # pragma weak pth_rwlock_acquire
- # pragma weak pth_rwlock_release
- # pragma weak pth_once
- # pragma weak pth_cancel
- # define pth_in_use() (pth_cancel != NULL)
- # else
- # define pth_in_use() 1
- # endif
- /* -------------------------- gl_lock_t datatype -------------------------- */
- typedef pth_mutex_t gl_lock_t;
- # define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME;
- # define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
- # define gl_lock_initializer \
- PTH_MUTEX_INIT
- # define gl_lock_init(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_init (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_lock_lock(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
- abort (); \
- } \
- while (0)
- # define gl_lock_unlock(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_release (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_lock_destroy(NAME) \
- (void)(&NAME)
- /* ------------------------- gl_rwlock_t datatype ------------------------- */
- typedef pth_rwlock_t gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- PTH_RWLOCK_INIT
- # define gl_rwlock_init(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_rwlock_init (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (pth_in_use() \
- && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (pth_in_use() \
- && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_rwlock_release (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_destroy(NAME) \
- (void)(&NAME)
- /* --------------------- gl_recursive_lock_t datatype --------------------- */
- /* In Pth, mutexes are recursive by default. */
- typedef pth_mutex_t gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
- # define gl_recursive_lock_initializer \
- PTH_MUTEX_INIT
- # define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_init (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (pth_in_use() && !pth_mutex_release (&NAME)) \
- abort (); \
- } \
- while (0)
- # define gl_recursive_lock_destroy(NAME) \
- (void)(&NAME)
- /* -------------------------- gl_once_t datatype -------------------------- */
- typedef pth_once_t gl_once_t;
- # define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
- # define gl_once(NAME, INITFUNCTION) \
- do \
- { \
- if (pth_in_use ()) \
- { \
- void (*gl_once_temp) (void) = INITFUNCTION; \
- if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
- abort (); \
- } \
- else \
- { \
- if (glthread_once_singlethreaded (&NAME)) \
- INITFUNCTION (); \
- } \
- } \
- while (0)
- extern void glthread_once_call (void *arg);
- extern int glthread_once_singlethreaded (pth_once_t *once_control);
- # ifdef __cplusplus
- }
- # endif
- #endif
- /* ========================================================================= */
- #if USE_SOLARIS_THREADS
- /* Use the old Solaris threads library. */
- # include <thread.h>
- # include <synch.h>
- # include <stdlib.h>
- # ifdef __cplusplus
- extern "C" {
- # endif
- # if USE_SOLARIS_THREADS_WEAK
- /* Use weak references to the old Solaris threads library. */
- # pragma weak mutex_init
- # pragma weak mutex_lock
- # pragma weak mutex_unlock
- # pragma weak mutex_destroy
- # pragma weak rwlock_init
- # pragma weak rw_rdlock
- # pragma weak rw_wrlock
- # pragma weak rw_unlock
- # pragma weak rwlock_destroy
- # pragma weak thr_self
- # pragma weak thr_suspend
- # define thread_in_use() (thr_suspend != NULL)
- # else
- # define thread_in_use() 1
- # endif
- /* -------------------------- gl_lock_t datatype -------------------------- */
- typedef mutex_t gl_lock_t;
- # define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS mutex_t NAME;
- # define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS mutex_t NAME = gl_lock_initializer;
- # define gl_lock_initializer \
- DEFAULTMUTEX
- # define gl_lock_init(NAME) \
- do \
- { \
- if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_lock(NAME) \
- do \
- { \
- if (thread_in_use () && mutex_lock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_unlock(NAME) \
- do \
- { \
- if (thread_in_use () && mutex_unlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_lock_destroy(NAME) \
- do \
- { \
- if (thread_in_use () && mutex_destroy (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- /* ------------------------- gl_rwlock_t datatype ------------------------- */
- typedef rwlock_t gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- DEFAULTRWLOCK
- # define gl_rwlock_init(NAME) \
- do \
- { \
- if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (thread_in_use () && rw_rdlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (thread_in_use () && rw_wrlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (thread_in_use () && rw_unlock (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- # define gl_rwlock_destroy(NAME) \
- do \
- { \
- if (thread_in_use () && rwlock_destroy (&NAME) != 0) \
- abort (); \
- } \
- while (0)
- /* --------------------- gl_recursive_lock_t datatype --------------------- */
- /* Old Solaris threads did not have recursive locks.
- We have to implement them ourselves. */
- typedef struct
- {
- mutex_t mutex;
- thread_t owner;
- unsigned long depth;
- }
- gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
- # define gl_recursive_lock_initializer \
- { DEFAULTMUTEX, (thread_t) 0, 0 }
- # define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (thread_in_use ()) \
- glthread_recursive_lock_init (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (thread_in_use ()) \
- glthread_recursive_lock_lock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (thread_in_use ()) \
- glthread_recursive_lock_unlock (&NAME); \
- } \
- while (0)
- # define gl_recursive_lock_destroy(NAME) \
- do \
- { \
- if (thread_in_use ()) \
- glthread_recursive_lock_destroy (&NAME); \
- } \
- while (0)
- extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
- /* -------------------------- gl_once_t datatype -------------------------- */
- typedef struct
- {
- volatile int inited;
- mutex_t mutex;
- }
- gl_once_t;
- # define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
- # define gl_once(NAME, INITFUNCTION) \
- do \
- { \
- if (thread_in_use ()) \
- { \
- glthread_once (&NAME, INITFUNCTION); \
- } \
- else \
- { \
- if (glthread_once_singlethreaded (&NAME)) \
- INITFUNCTION (); \
- } \
- } \
- while (0)
- extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
- extern int glthread_once_singlethreaded (gl_once_t *once_control);
- # ifdef __cplusplus
- }
- # endif
- #endif
- /* ========================================================================= */
- #if USE_WIN32_THREADS
- # include <windows.h>
- # ifdef __cplusplus
- extern "C" {
- # endif
- /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
- Semaphore types, because
- - we need only to synchronize inside a single process (address space),
- not inter-process locking,
- - we don't need to support trylock operations. (TryEnterCriticalSection
- does not work on Windows 95/98/ME. Packages that need trylock usually
- define their own mutex type.) */
- /* There is no way to statically initialize a CRITICAL_SECTION. It needs
- to be done lazily, once only. For this we need spinlocks. */
- typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
- /* -------------------------- gl_lock_t datatype -------------------------- */
- typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- CRITICAL_SECTION lock;
- }
- gl_lock_t;
- # define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_lock_t NAME;
- # define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
- # define gl_lock_initializer \
- { { 0, -1 } }
- # define gl_lock_init(NAME) \
- glthread_lock_init (&NAME)
- # define gl_lock_lock(NAME) \
- glthread_lock_lock (&NAME)
- # define gl_lock_unlock(NAME) \
- glthread_lock_unlock (&NAME)
- # define gl_lock_destroy(NAME) \
- glthread_lock_destroy (&NAME)
- extern void glthread_lock_init (gl_lock_t *lock);
- extern void glthread_lock_lock (gl_lock_t *lock);
- extern void glthread_lock_unlock (gl_lock_t *lock);
- extern void glthread_lock_destroy (gl_lock_t *lock);
- /* ------------------------- gl_rwlock_t datatype ------------------------- */
- /* It is impossible to implement read-write locks using plain locks, without
- introducing an extra thread dedicated to managing read-write locks.
- Therefore here we need to use the low-level Event type. */
- typedef struct
- {
- HANDLE *array; /* array of waiting threads, each represented by an event */
- unsigned int count; /* number of waiting threads */
- unsigned int alloc; /* length of allocated array */
- unsigned int offset; /* index of first waiting thread in array */
- }
- gl_waitqueue_t;
- typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- CRITICAL_SECTION lock; /* protects the remaining fields */
- gl_waitqueue_t waiting_readers; /* waiting readers */
- gl_waitqueue_t waiting_writers; /* waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
- # define gl_rwlock_initializer \
- { { 0, -1 } }
- # define gl_rwlock_init(NAME) \
- glthread_rwlock_init (&NAME)
- # define gl_rwlock_rdlock(NAME) \
- glthread_rwlock_rdlock (&NAME)
- # define gl_rwlock_wrlock(NAME) \
- glthread_rwlock_wrlock (&NAME)
- # define gl_rwlock_unlock(NAME) \
- glthread_rwlock_unlock (&NAME)
- # define gl_rwlock_destroy(NAME) \
- glthread_rwlock_destroy (&NAME)
- extern void glthread_rwlock_init (gl_rwlock_t *lock);
- extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
- extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
- /* --------------------- gl_recursive_lock_t datatype --------------------- */
- /* The Win32 documentation says that CRITICAL_SECTION already implements a
- recursive lock. But we need not rely on it: It's easy to implement a
- recursive lock without this assumption. */
- typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- DWORD owner;
- unsigned long depth;
- CRITICAL_SECTION lock;
- }
- gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
- # define gl_recursive_lock_initializer \
- { { 0, -1 }, 0, 0 }
- # define gl_recursive_lock_init(NAME) \
- glthread_recursive_lock_init (&NAME)
- # define gl_recursive_lock_lock(NAME) \
- glthread_recursive_lock_lock (&NAME)
- # define gl_recursive_lock_unlock(NAME) \
- glthread_recursive_lock_unlock (&NAME)
- # define gl_recursive_lock_destroy(NAME) \
- glthread_recursive_lock_destroy (&NAME)
- extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
- extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
- /* -------------------------- gl_once_t datatype -------------------------- */
- typedef struct
- {
- volatile int inited;
- volatile long started;
- CRITICAL_SECTION lock;
- }
- gl_once_t;
- # define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = { -1, -1 };
- # define gl_once(NAME, INITFUNCTION) \
- glthread_once (&NAME, INITFUNCTION)
- extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
- # ifdef __cplusplus
- }
- # endif
- #endif
- /* ========================================================================= */
- #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
- /* Provide dummy implementation if threads are not supported. */
- /* -------------------------- gl_lock_t datatype -------------------------- */
- typedef int gl_lock_t;
- # define gl_lock_define(STORAGECLASS, NAME)
- # define gl_lock_define_initialized(STORAGECLASS, NAME)
- # define gl_lock_init(NAME)
- # define gl_lock_lock(NAME)
- # define gl_lock_unlock(NAME)
- /* ------------------------- gl_rwlock_t datatype ------------------------- */
- typedef int gl_rwlock_t;
- # define gl_rwlock_define(STORAGECLASS, NAME)
- # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
- # define gl_rwlock_init(NAME)
- # define gl_rwlock_rdlock(NAME)
- # define gl_rwlock_wrlock(NAME)
- # define gl_rwlock_unlock(NAME)
- /* --------------------- gl_recursive_lock_t datatype --------------------- */
- typedef int gl_recursive_lock_t;
- # define gl_recursive_lock_define(STORAGECLASS, NAME)
- # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
- # define gl_recursive_lock_init(NAME)
- # define gl_recursive_lock_lock(NAME)
- # define gl_recursive_lock_unlock(NAME)
- /* -------------------------- gl_once_t datatype -------------------------- */
- typedef int gl_once_t;
- # define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = 0;
- # define gl_once(NAME, INITFUNCTION) \
- do \
- { \
- if (NAME == 0) \
- { \
- NAME = ~ 0; \
- INITFUNCTION (); \
- } \
- } \
- while (0)
- #endif
- /* ========================================================================= */
- #endif /* _LOCK_H */
|