1
/* Locking in multithreaded situations.
2
Copyright (C) 2005-2007 Free Software Foundation, Inc.
4
This program is free software; you can redistribute it and/or modify it
5
under the terms of the GNU Library General Public License as published
6
by the Free Software Foundation; either version 2, or (at your option)
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public
15
License along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
20
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
23
/* This file contains locking primitives for use with a given thread library.
24
It does not contain primitives for creating threads or for other
25
synchronization primitives.
27
Normal (non-recursive) locks:
29
Declaration: gl_lock_define(extern, name)
30
Initializer: gl_lock_define_initialized(, name)
31
Initialization: gl_lock_init (name);
32
Taking the lock: gl_lock_lock (name);
33
Releasing the lock: gl_lock_unlock (name);
34
De-initialization: gl_lock_destroy (name);
36
Read-Write (non-recursive) locks:
38
Declaration: gl_rwlock_define(extern, name)
39
Initializer: gl_rwlock_define_initialized(, name)
40
Initialization: gl_rwlock_init (name);
41
Taking the lock: gl_rwlock_rdlock (name);
42
gl_rwlock_wrlock (name);
43
Releasing the lock: gl_rwlock_unlock (name);
44
De-initialization: gl_rwlock_destroy (name);
47
Type: gl_recursive_lock_t
48
Declaration: gl_recursive_lock_define(extern, name)
49
Initializer: gl_recursive_lock_define_initialized(, name)
50
Initialization: gl_recursive_lock_init (name);
51
Taking the lock: gl_recursive_lock_lock (name);
52
Releasing the lock: gl_recursive_lock_unlock (name);
53
De-initialization: gl_recursive_lock_destroy (name);
57
Initializer: gl_once_define(extern, name)
58
Execution: gl_once (name, initfunction);
65
/* ========================================================================= */
69
/* Use the POSIX threads library. */
78
# if PTHREAD_IN_USE_DETECTION_HARD
80
/* The pthread_in_use() detection needs to be done at runtime. */
81
# define pthread_in_use() \
83
extern int glthread_in_use (void);
87
# if USE_POSIX_THREADS_WEAK
89
/* Use weak references to the POSIX threads library. */
91
/* Weak references avoid dragging in external libraries if the other parts
92
of the program don't use them. Here we use them, because we don't want
93
every program that uses libintl to depend on libpthread. This assumes
94
that libpthread would not be loaded after libintl; i.e. if libintl is
95
loaded first, by an executable that does not depend on libpthread, and
96
then a module is dynamically loaded that depends on libpthread, libintl
97
will not be multithread-safe. */
99
/* The way to test at runtime whether libpthread is present is to test
100
whether a function pointer's value, such as &pthread_mutex_init, is
101
non-NULL. However, some versions of GCC have a bug through which, in
102
PIC mode, &foo != NULL always evaluates to true if there is a direct
103
call to foo(...) in the same function. To avoid this, we test the
104
address of a function in libpthread that we don't use. */
106
# pragma weak pthread_mutex_init
107
# pragma weak pthread_mutex_lock
108
# pragma weak pthread_mutex_unlock
109
# pragma weak pthread_mutex_destroy
110
# pragma weak pthread_rwlock_init
111
# pragma weak pthread_rwlock_rdlock
112
# pragma weak pthread_rwlock_wrlock
113
# pragma weak pthread_rwlock_unlock
114
# pragma weak pthread_rwlock_destroy
115
# pragma weak pthread_once
116
# pragma weak pthread_cond_init
117
# pragma weak pthread_cond_wait
118
# pragma weak pthread_cond_signal
119
# pragma weak pthread_cond_broadcast
120
# pragma weak pthread_cond_destroy
121
# pragma weak pthread_mutexattr_init
122
# pragma weak pthread_mutexattr_settype
123
# pragma weak pthread_mutexattr_destroy
124
# ifndef pthread_self
125
# pragma weak pthread_self
128
# if !PTHREAD_IN_USE_DETECTION_HARD
129
# pragma weak pthread_cancel
130
# define pthread_in_use() (pthread_cancel != NULL)
135
# if !PTHREAD_IN_USE_DETECTION_HARD
136
# define pthread_in_use() 1
141
/* -------------------------- gl_lock_t datatype -------------------------- */
143
typedef pthread_mutex_t gl_lock_t;
144
# define gl_lock_define(STORAGECLASS, NAME) \
145
STORAGECLASS pthread_mutex_t NAME;
146
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
147
STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
148
# define gl_lock_initializer \
149
PTHREAD_MUTEX_INITIALIZER
150
# define gl_lock_init(NAME) \
153
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
157
# define gl_lock_lock(NAME) \
160
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
164
# define gl_lock_unlock(NAME) \
167
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
171
# define gl_lock_destroy(NAME) \
174
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
179
/* ------------------------- gl_rwlock_t datatype ------------------------- */
181
# if HAVE_PTHREAD_RWLOCK
183
# ifdef PTHREAD_RWLOCK_INITIALIZER
185
typedef pthread_rwlock_t gl_rwlock_t;
186
# define gl_rwlock_define(STORAGECLASS, NAME) \
187
STORAGECLASS pthread_rwlock_t NAME;
188
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
189
STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
190
# define gl_rwlock_initializer \
191
PTHREAD_RWLOCK_INITIALIZER
192
# define gl_rwlock_init(NAME) \
195
if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \
199
# define gl_rwlock_rdlock(NAME) \
202
if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \
206
# define gl_rwlock_wrlock(NAME) \
209
if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \
213
# define gl_rwlock_unlock(NAME) \
216
if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \
220
# define gl_rwlock_destroy(NAME) \
223
if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \
233
pthread_mutex_t guard; /* protects the initialization */
234
pthread_rwlock_t rwlock; /* read-write lock */
237
# define gl_rwlock_define(STORAGECLASS, NAME) \
238
STORAGECLASS gl_rwlock_t NAME;
239
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
240
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
241
# define gl_rwlock_initializer \
242
{ 0, PTHREAD_MUTEX_INITIALIZER }
243
# define gl_rwlock_init(NAME) \
246
if (pthread_in_use ()) \
247
glthread_rwlock_init (&NAME); \
250
# define gl_rwlock_rdlock(NAME) \
253
if (pthread_in_use ()) \
254
glthread_rwlock_rdlock (&NAME); \
257
# define gl_rwlock_wrlock(NAME) \
260
if (pthread_in_use ()) \
261
glthread_rwlock_wrlock (&NAME); \
264
# define gl_rwlock_unlock(NAME) \
267
if (pthread_in_use ()) \
268
glthread_rwlock_unlock (&NAME); \
271
# define gl_rwlock_destroy(NAME) \
274
if (pthread_in_use ()) \
275
glthread_rwlock_destroy (&NAME); \
278
extern void glthread_rwlock_init (gl_rwlock_t *lock);
279
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
280
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
281
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
282
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
290
pthread_mutex_t lock; /* protects the remaining fields */
291
pthread_cond_t waiting_readers; /* waiting readers */
292
pthread_cond_t waiting_writers; /* waiting writers */
293
unsigned int waiting_writers_count; /* number of waiting writers */
294
int runcount; /* number of readers running, or -1 when a writer runs */
297
# define gl_rwlock_define(STORAGECLASS, NAME) \
298
STORAGECLASS gl_rwlock_t NAME;
299
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
300
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
301
# define gl_rwlock_initializer \
302
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
303
# define gl_rwlock_init(NAME) \
306
if (pthread_in_use ()) \
307
glthread_rwlock_init (&NAME); \
310
# define gl_rwlock_rdlock(NAME) \
313
if (pthread_in_use ()) \
314
glthread_rwlock_rdlock (&NAME); \
317
# define gl_rwlock_wrlock(NAME) \
320
if (pthread_in_use ()) \
321
glthread_rwlock_wrlock (&NAME); \
324
# define gl_rwlock_unlock(NAME) \
327
if (pthread_in_use ()) \
328
glthread_rwlock_unlock (&NAME); \
331
# define gl_rwlock_destroy(NAME) \
334
if (pthread_in_use ()) \
335
glthread_rwlock_destroy (&NAME); \
338
extern void glthread_rwlock_init (gl_rwlock_t *lock);
339
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
340
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
341
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
342
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
346
/* --------------------- gl_recursive_lock_t datatype --------------------- */
348
# if HAVE_PTHREAD_MUTEX_RECURSIVE
350
# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
352
typedef pthread_mutex_t gl_recursive_lock_t;
353
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
354
STORAGECLASS pthread_mutex_t NAME;
355
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
356
STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
357
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
358
# define gl_recursive_lock_initializer \
359
PTHREAD_RECURSIVE_MUTEX_INITIALIZER
361
# define gl_recursive_lock_initializer \
362
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
364
# define gl_recursive_lock_init(NAME) \
367
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
371
# define gl_recursive_lock_lock(NAME) \
374
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
378
# define gl_recursive_lock_unlock(NAME) \
381
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
385
# define gl_recursive_lock_destroy(NAME) \
388
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
397
pthread_mutex_t recmutex; /* recursive mutex */
398
pthread_mutex_t guard; /* protects the initialization */
402
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
403
STORAGECLASS gl_recursive_lock_t NAME;
404
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
405
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
406
# define gl_recursive_lock_initializer \
407
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
408
# define gl_recursive_lock_init(NAME) \
411
if (pthread_in_use ()) \
412
glthread_recursive_lock_init (&NAME); \
415
# define gl_recursive_lock_lock(NAME) \
418
if (pthread_in_use ()) \
419
glthread_recursive_lock_lock (&NAME); \
422
# define gl_recursive_lock_unlock(NAME) \
425
if (pthread_in_use ()) \
426
glthread_recursive_lock_unlock (&NAME); \
429
# define gl_recursive_lock_destroy(NAME) \
432
if (pthread_in_use ()) \
433
glthread_recursive_lock_destroy (&NAME); \
436
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
437
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
438
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
439
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
445
/* Old versions of POSIX threads on Solaris did not have recursive locks.
446
We have to implement them ourselves. */
450
pthread_mutex_t mutex;
455
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
456
STORAGECLASS gl_recursive_lock_t NAME;
457
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
458
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
459
# define gl_recursive_lock_initializer \
460
{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
461
# define gl_recursive_lock_init(NAME) \
464
if (pthread_in_use ()) \
465
glthread_recursive_lock_init (&NAME); \
468
# define gl_recursive_lock_lock(NAME) \
471
if (pthread_in_use ()) \
472
glthread_recursive_lock_lock (&NAME); \
475
# define gl_recursive_lock_unlock(NAME) \
478
if (pthread_in_use ()) \
479
glthread_recursive_lock_unlock (&NAME); \
482
# define gl_recursive_lock_destroy(NAME) \
485
if (pthread_in_use ()) \
486
glthread_recursive_lock_destroy (&NAME); \
489
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
490
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
491
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
492
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
496
/* -------------------------- gl_once_t datatype -------------------------- */
498
typedef pthread_once_t gl_once_t;
499
# define gl_once_define(STORAGECLASS, NAME) \
500
STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
501
# define gl_once(NAME, INITFUNCTION) \
504
if (pthread_in_use ()) \
506
if (pthread_once (&NAME, INITFUNCTION) != 0) \
511
if (glthread_once_singlethreaded (&NAME)) \
516
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
524
/* ========================================================================= */
528
/* Use the GNU Pth threads library. */
537
# if USE_PTH_THREADS_WEAK
539
/* Use weak references to the GNU Pth threads library. */
541
# pragma weak pth_mutex_init
542
# pragma weak pth_mutex_acquire
543
# pragma weak pth_mutex_release
544
# pragma weak pth_rwlock_init
545
# pragma weak pth_rwlock_acquire
546
# pragma weak pth_rwlock_release
547
# pragma weak pth_once
549
# pragma weak pth_cancel
550
# define pth_in_use() (pth_cancel != NULL)
554
# define pth_in_use() 1
558
/* -------------------------- gl_lock_t datatype -------------------------- */
560
typedef pth_mutex_t gl_lock_t;
561
# define gl_lock_define(STORAGECLASS, NAME) \
562
STORAGECLASS pth_mutex_t NAME;
563
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
564
STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
565
# define gl_lock_initializer \
567
# define gl_lock_init(NAME) \
570
if (pth_in_use() && !pth_mutex_init (&NAME)) \
574
# define gl_lock_lock(NAME) \
577
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
581
# define gl_lock_unlock(NAME) \
584
if (pth_in_use() && !pth_mutex_release (&NAME)) \
588
# define gl_lock_destroy(NAME) \
591
/* ------------------------- gl_rwlock_t datatype ------------------------- */
593
typedef pth_rwlock_t gl_rwlock_t;
594
# define gl_rwlock_define(STORAGECLASS, NAME) \
595
STORAGECLASS pth_rwlock_t NAME;
596
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
597
STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
598
# define gl_rwlock_initializer \
600
# define gl_rwlock_init(NAME) \
603
if (pth_in_use() && !pth_rwlock_init (&NAME)) \
607
# define gl_rwlock_rdlock(NAME) \
611
&& !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \
615
# define gl_rwlock_wrlock(NAME) \
619
&& !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \
623
# define gl_rwlock_unlock(NAME) \
626
if (pth_in_use() && !pth_rwlock_release (&NAME)) \
630
# define gl_rwlock_destroy(NAME) \
633
/* --------------------- gl_recursive_lock_t datatype --------------------- */
635
/* In Pth, mutexes are recursive by default. */
636
typedef pth_mutex_t gl_recursive_lock_t;
637
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
638
STORAGECLASS pth_mutex_t NAME;
639
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
640
STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
641
# define gl_recursive_lock_initializer \
643
# define gl_recursive_lock_init(NAME) \
646
if (pth_in_use() && !pth_mutex_init (&NAME)) \
650
# define gl_recursive_lock_lock(NAME) \
653
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
657
# define gl_recursive_lock_unlock(NAME) \
660
if (pth_in_use() && !pth_mutex_release (&NAME)) \
664
# define gl_recursive_lock_destroy(NAME) \
667
/* -------------------------- gl_once_t datatype -------------------------- */
669
typedef pth_once_t gl_once_t;
670
# define gl_once_define(STORAGECLASS, NAME) \
671
STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
672
# define gl_once(NAME, INITFUNCTION) \
677
void (*gl_once_temp) (void) = INITFUNCTION; \
678
if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
683
if (glthread_once_singlethreaded (&NAME)) \
688
extern void glthread_once_call (void *arg);
689
extern int glthread_once_singlethreaded (pth_once_t *once_control);
697
/* ========================================================================= */
699
#if USE_SOLARIS_THREADS
701
/* Use the old Solaris threads library. */
711
# if USE_SOLARIS_THREADS_WEAK
713
/* Use weak references to the old Solaris threads library. */
715
# pragma weak mutex_init
716
# pragma weak mutex_lock
717
# pragma weak mutex_unlock
718
# pragma weak mutex_destroy
719
# pragma weak rwlock_init
720
# pragma weak rw_rdlock
721
# pragma weak rw_wrlock
722
# pragma weak rw_unlock
723
# pragma weak rwlock_destroy
724
# pragma weak thr_self
726
# pragma weak thr_suspend
727
# define thread_in_use() (thr_suspend != NULL)
731
# define thread_in_use() 1
735
/* -------------------------- gl_lock_t datatype -------------------------- */
737
typedef mutex_t gl_lock_t;
738
# define gl_lock_define(STORAGECLASS, NAME) \
739
STORAGECLASS mutex_t NAME;
740
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
741
STORAGECLASS mutex_t NAME = gl_lock_initializer;
742
# define gl_lock_initializer \
744
# define gl_lock_init(NAME) \
747
if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \
751
# define gl_lock_lock(NAME) \
754
if (thread_in_use () && mutex_lock (&NAME) != 0) \
758
# define gl_lock_unlock(NAME) \
761
if (thread_in_use () && mutex_unlock (&NAME) != 0) \
765
# define gl_lock_destroy(NAME) \
768
if (thread_in_use () && mutex_destroy (&NAME) != 0) \
773
/* ------------------------- gl_rwlock_t datatype ------------------------- */
775
typedef rwlock_t gl_rwlock_t;
776
# define gl_rwlock_define(STORAGECLASS, NAME) \
777
STORAGECLASS rwlock_t NAME;
778
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
779
STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
780
# define gl_rwlock_initializer \
782
# define gl_rwlock_init(NAME) \
785
if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \
789
# define gl_rwlock_rdlock(NAME) \
792
if (thread_in_use () && rw_rdlock (&NAME) != 0) \
796
# define gl_rwlock_wrlock(NAME) \
799
if (thread_in_use () && rw_wrlock (&NAME) != 0) \
803
# define gl_rwlock_unlock(NAME) \
806
if (thread_in_use () && rw_unlock (&NAME) != 0) \
810
# define gl_rwlock_destroy(NAME) \
813
if (thread_in_use () && rwlock_destroy (&NAME) != 0) \
818
/* --------------------- gl_recursive_lock_t datatype --------------------- */
820
/* Old Solaris threads did not have recursive locks.
821
We have to implement them ourselves. */
830
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
831
STORAGECLASS gl_recursive_lock_t NAME;
832
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
833
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
834
# define gl_recursive_lock_initializer \
835
{ DEFAULTMUTEX, (thread_t) 0, 0 }
836
# define gl_recursive_lock_init(NAME) \
839
if (thread_in_use ()) \
840
glthread_recursive_lock_init (&NAME); \
843
# define gl_recursive_lock_lock(NAME) \
846
if (thread_in_use ()) \
847
glthread_recursive_lock_lock (&NAME); \
850
# define gl_recursive_lock_unlock(NAME) \
853
if (thread_in_use ()) \
854
glthread_recursive_lock_unlock (&NAME); \
857
# define gl_recursive_lock_destroy(NAME) \
860
if (thread_in_use ()) \
861
glthread_recursive_lock_destroy (&NAME); \
864
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
865
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
866
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
867
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
869
/* -------------------------- gl_once_t datatype -------------------------- */
877
# define gl_once_define(STORAGECLASS, NAME) \
878
STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
879
# define gl_once(NAME, INITFUNCTION) \
882
if (thread_in_use ()) \
884
glthread_once (&NAME, INITFUNCTION); \
888
if (glthread_once_singlethreaded (&NAME)) \
893
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
894
extern int glthread_once_singlethreaded (gl_once_t *once_control);
902
/* ========================================================================= */
904
#if USE_WIN32_THREADS
906
# include <windows.h>
912
/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
913
Semaphore types, because
914
- we need only to synchronize inside a single process (address space),
915
not inter-process locking,
916
- we don't need to support trylock operations. (TryEnterCriticalSection
917
does not work on Windows 95/98/ME. Packages that need trylock usually
918
define their own mutex type.) */
920
/* There is no way to statically initialize a CRITICAL_SECTION. It needs
921
to be done lazily, once only. For this we need spinlocks. */
923
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
925
/* -------------------------- gl_lock_t datatype -------------------------- */
929
gl_spinlock_t guard; /* protects the initialization */
930
CRITICAL_SECTION lock;
933
# define gl_lock_define(STORAGECLASS, NAME) \
934
STORAGECLASS gl_lock_t NAME;
935
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
936
STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
937
# define gl_lock_initializer \
939
# define gl_lock_init(NAME) \
940
glthread_lock_init (&NAME)
941
# define gl_lock_lock(NAME) \
942
glthread_lock_lock (&NAME)
943
# define gl_lock_unlock(NAME) \
944
glthread_lock_unlock (&NAME)
945
# define gl_lock_destroy(NAME) \
946
glthread_lock_destroy (&NAME)
947
extern void glthread_lock_init (gl_lock_t *lock);
948
extern void glthread_lock_lock (gl_lock_t *lock);
949
extern void glthread_lock_unlock (gl_lock_t *lock);
950
extern void glthread_lock_destroy (gl_lock_t *lock);
952
/* ------------------------- gl_rwlock_t datatype ------------------------- */
954
/* It is impossible to implement read-write locks using plain locks, without
955
introducing an extra thread dedicated to managing read-write locks.
956
Therefore here we need to use the low-level Event type. */
960
HANDLE *array; /* array of waiting threads, each represented by an event */
961
unsigned int count; /* number of waiting threads */
962
unsigned int alloc; /* length of allocated array */
963
unsigned int offset; /* index of first waiting thread in array */
968
gl_spinlock_t guard; /* protects the initialization */
969
CRITICAL_SECTION lock; /* protects the remaining fields */
970
gl_waitqueue_t waiting_readers; /* waiting readers */
971
gl_waitqueue_t waiting_writers; /* waiting writers */
972
int runcount; /* number of readers running, or -1 when a writer runs */
975
# define gl_rwlock_define(STORAGECLASS, NAME) \
976
STORAGECLASS gl_rwlock_t NAME;
977
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
978
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
979
# define gl_rwlock_initializer \
981
# define gl_rwlock_init(NAME) \
982
glthread_rwlock_init (&NAME)
983
# define gl_rwlock_rdlock(NAME) \
984
glthread_rwlock_rdlock (&NAME)
985
# define gl_rwlock_wrlock(NAME) \
986
glthread_rwlock_wrlock (&NAME)
987
# define gl_rwlock_unlock(NAME) \
988
glthread_rwlock_unlock (&NAME)
989
# define gl_rwlock_destroy(NAME) \
990
glthread_rwlock_destroy (&NAME)
991
extern void glthread_rwlock_init (gl_rwlock_t *lock);
992
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
993
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
994
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
995
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
997
/* --------------------- gl_recursive_lock_t datatype --------------------- */
999
/* The Win32 documentation says that CRITICAL_SECTION already implements a
1000
recursive lock. But we need not rely on it: It's easy to implement a
1001
recursive lock without this assumption. */
1005
gl_spinlock_t guard; /* protects the initialization */
1007
unsigned long depth;
1008
CRITICAL_SECTION lock;
1010
gl_recursive_lock_t;
1011
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
1012
STORAGECLASS gl_recursive_lock_t NAME;
1013
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
1014
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
1015
# define gl_recursive_lock_initializer \
1017
# define gl_recursive_lock_init(NAME) \
1018
glthread_recursive_lock_init (&NAME)
1019
# define gl_recursive_lock_lock(NAME) \
1020
glthread_recursive_lock_lock (&NAME)
1021
# define gl_recursive_lock_unlock(NAME) \
1022
glthread_recursive_lock_unlock (&NAME)
1023
# define gl_recursive_lock_destroy(NAME) \
1024
glthread_recursive_lock_destroy (&NAME)
1025
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
1026
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
1027
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
1028
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
1030
/* -------------------------- gl_once_t datatype -------------------------- */
1034
volatile int inited;
1035
volatile long started;
1036
CRITICAL_SECTION lock;
1039
# define gl_once_define(STORAGECLASS, NAME) \
1040
STORAGECLASS gl_once_t NAME = { -1, -1 };
1041
# define gl_once(NAME, INITFUNCTION) \
1042
glthread_once (&NAME, INITFUNCTION)
1043
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
1051
/* ========================================================================= */
1053
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
1055
/* Provide dummy implementation if threads are not supported. */
1057
/* -------------------------- gl_lock_t datatype -------------------------- */
1059
typedef int gl_lock_t;
1060
# define gl_lock_define(STORAGECLASS, NAME)
1061
# define gl_lock_define_initialized(STORAGECLASS, NAME)
1062
# define gl_lock_init(NAME)
1063
# define gl_lock_lock(NAME)
1064
# define gl_lock_unlock(NAME)
1066
/* ------------------------- gl_rwlock_t datatype ------------------------- */
1068
typedef int gl_rwlock_t;
1069
# define gl_rwlock_define(STORAGECLASS, NAME)
1070
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
1071
# define gl_rwlock_init(NAME)
1072
# define gl_rwlock_rdlock(NAME)
1073
# define gl_rwlock_wrlock(NAME)
1074
# define gl_rwlock_unlock(NAME)
1076
/* --------------------- gl_recursive_lock_t datatype --------------------- */
1078
typedef int gl_recursive_lock_t;
1079
# define gl_recursive_lock_define(STORAGECLASS, NAME)
1080
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
1081
# define gl_recursive_lock_init(NAME)
1082
# define gl_recursive_lock_lock(NAME)
1083
# define gl_recursive_lock_unlock(NAME)
1085
/* -------------------------- gl_once_t datatype -------------------------- */
1087
typedef int gl_once_t;
1088
# define gl_once_define(STORAGECLASS, NAME) \
1089
STORAGECLASS gl_once_t NAME = 0;
1090
# define gl_once(NAME, INITFUNCTION) \
1103
/* ========================================================================= */
1105
#endif /* _LOCK_H */