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
5
it under the terms of the GNU General Public License as published by
6
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
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software Foundation,
16
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
19
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
22
/* This file contains locking primitives for use with a given thread library.
23
It does not contain primitives for creating threads or for other
24
synchronization primitives.
26
Normal (non-recursive) locks:
28
Declaration: gl_lock_define(extern, name)
29
Initializer: gl_lock_define_initialized(, name)
30
Initialization: gl_lock_init (name);
31
Taking the lock: gl_lock_lock (name);
32
Releasing the lock: gl_lock_unlock (name);
33
De-initialization: gl_lock_destroy (name);
35
Read-Write (non-recursive) locks:
37
Declaration: gl_rwlock_define(extern, name)
38
Initializer: gl_rwlock_define_initialized(, name)
39
Initialization: gl_rwlock_init (name);
40
Taking the lock: gl_rwlock_rdlock (name);
41
gl_rwlock_wrlock (name);
42
Releasing the lock: gl_rwlock_unlock (name);
43
De-initialization: gl_rwlock_destroy (name);
46
Type: gl_recursive_lock_t
47
Declaration: gl_recursive_lock_define(extern, name)
48
Initializer: gl_recursive_lock_define_initialized(, name)
49
Initialization: gl_recursive_lock_init (name);
50
Taking the lock: gl_recursive_lock_lock (name);
51
Releasing the lock: gl_recursive_lock_unlock (name);
52
De-initialization: gl_recursive_lock_destroy (name);
56
Initializer: gl_once_define(extern, name)
57
Execution: gl_once (name, initfunction);
64
/* ========================================================================= */
68
/* Use the POSIX threads library. */
77
# if PTHREAD_IN_USE_DETECTION_HARD
79
/* The pthread_in_use() detection needs to be done at runtime. */
80
# define pthread_in_use() \
82
extern int glthread_in_use (void);
86
# if USE_POSIX_THREADS_WEAK
88
/* Use weak references to the POSIX threads library. */
90
/* Weak references avoid dragging in external libraries if the other parts
91
of the program don't use them. Here we use them, because we don't want
92
every program that uses libintl to depend on libpthread. This assumes
93
that libpthread would not be loaded after libintl; i.e. if libintl is
94
loaded first, by an executable that does not depend on libpthread, and
95
then a module is dynamically loaded that depends on libpthread, libintl
96
will not be multithread-safe. */
98
/* The way to test at runtime whether libpthread is present is to test
99
whether a function pointer's value, such as &pthread_mutex_init, is
100
non-NULL. However, some versions of GCC have a bug through which, in
101
PIC mode, &foo != NULL always evaluates to true if there is a direct
102
call to foo(...) in the same function. To avoid this, we test the
103
address of a function in libpthread that we don't use. */
105
# pragma weak pthread_mutex_init
106
# pragma weak pthread_mutex_lock
107
# pragma weak pthread_mutex_unlock
108
# pragma weak pthread_mutex_destroy
109
# pragma weak pthread_rwlock_init
110
# pragma weak pthread_rwlock_rdlock
111
# pragma weak pthread_rwlock_wrlock
112
# pragma weak pthread_rwlock_unlock
113
# pragma weak pthread_rwlock_destroy
114
# pragma weak pthread_once
115
# pragma weak pthread_cond_init
116
# pragma weak pthread_cond_wait
117
# pragma weak pthread_cond_signal
118
# pragma weak pthread_cond_broadcast
119
# pragma weak pthread_cond_destroy
120
# pragma weak pthread_mutexattr_init
121
# pragma weak pthread_mutexattr_settype
122
# pragma weak pthread_mutexattr_destroy
123
# ifndef pthread_self
124
# pragma weak pthread_self
127
# if !PTHREAD_IN_USE_DETECTION_HARD
128
# pragma weak pthread_cancel
129
# define pthread_in_use() (pthread_cancel != NULL)
134
# if !PTHREAD_IN_USE_DETECTION_HARD
135
# define pthread_in_use() 1
140
/* -------------------------- gl_lock_t datatype -------------------------- */
142
typedef pthread_mutex_t gl_lock_t;
143
# define gl_lock_define(STORAGECLASS, NAME) \
144
STORAGECLASS pthread_mutex_t NAME;
145
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
146
STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
147
# define gl_lock_initializer \
148
PTHREAD_MUTEX_INITIALIZER
149
# define gl_lock_init(NAME) \
152
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
156
# define gl_lock_lock(NAME) \
159
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
163
# define gl_lock_unlock(NAME) \
166
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
170
# define gl_lock_destroy(NAME) \
173
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
178
/* ------------------------- gl_rwlock_t datatype ------------------------- */
180
# if HAVE_PTHREAD_RWLOCK
182
# ifdef PTHREAD_RWLOCK_INITIALIZER
184
typedef pthread_rwlock_t gl_rwlock_t;
185
# define gl_rwlock_define(STORAGECLASS, NAME) \
186
STORAGECLASS pthread_rwlock_t NAME;
187
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
188
STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
189
# define gl_rwlock_initializer \
190
PTHREAD_RWLOCK_INITIALIZER
191
# define gl_rwlock_init(NAME) \
194
if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \
198
# define gl_rwlock_rdlock(NAME) \
201
if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \
205
# define gl_rwlock_wrlock(NAME) \
208
if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \
212
# define gl_rwlock_unlock(NAME) \
215
if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \
219
# define gl_rwlock_destroy(NAME) \
222
if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \
232
pthread_mutex_t guard; /* protects the initialization */
233
pthread_rwlock_t rwlock; /* read-write lock */
236
# define gl_rwlock_define(STORAGECLASS, NAME) \
237
STORAGECLASS gl_rwlock_t NAME;
238
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
239
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
240
# define gl_rwlock_initializer \
241
{ 0, PTHREAD_MUTEX_INITIALIZER }
242
# define gl_rwlock_init(NAME) \
245
if (pthread_in_use ()) \
246
glthread_rwlock_init (&NAME); \
249
# define gl_rwlock_rdlock(NAME) \
252
if (pthread_in_use ()) \
253
glthread_rwlock_rdlock (&NAME); \
256
# define gl_rwlock_wrlock(NAME) \
259
if (pthread_in_use ()) \
260
glthread_rwlock_wrlock (&NAME); \
263
# define gl_rwlock_unlock(NAME) \
266
if (pthread_in_use ()) \
267
glthread_rwlock_unlock (&NAME); \
270
# define gl_rwlock_destroy(NAME) \
273
if (pthread_in_use ()) \
274
glthread_rwlock_destroy (&NAME); \
277
extern void glthread_rwlock_init (gl_rwlock_t *lock);
278
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
279
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
280
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
281
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
289
pthread_mutex_t lock; /* protects the remaining fields */
290
pthread_cond_t waiting_readers; /* waiting readers */
291
pthread_cond_t waiting_writers; /* waiting writers */
292
unsigned int waiting_writers_count; /* number of waiting writers */
293
int runcount; /* number of readers running, or -1 when a writer runs */
296
# define gl_rwlock_define(STORAGECLASS, NAME) \
297
STORAGECLASS gl_rwlock_t NAME;
298
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
299
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
300
# define gl_rwlock_initializer \
301
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
302
# define gl_rwlock_init(NAME) \
305
if (pthread_in_use ()) \
306
glthread_rwlock_init (&NAME); \
309
# define gl_rwlock_rdlock(NAME) \
312
if (pthread_in_use ()) \
313
glthread_rwlock_rdlock (&NAME); \
316
# define gl_rwlock_wrlock(NAME) \
319
if (pthread_in_use ()) \
320
glthread_rwlock_wrlock (&NAME); \
323
# define gl_rwlock_unlock(NAME) \
326
if (pthread_in_use ()) \
327
glthread_rwlock_unlock (&NAME); \
330
# define gl_rwlock_destroy(NAME) \
333
if (pthread_in_use ()) \
334
glthread_rwlock_destroy (&NAME); \
337
extern void glthread_rwlock_init (gl_rwlock_t *lock);
338
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
339
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
340
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
341
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
345
/* --------------------- gl_recursive_lock_t datatype --------------------- */
347
# if HAVE_PTHREAD_MUTEX_RECURSIVE
349
# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
351
typedef pthread_mutex_t gl_recursive_lock_t;
352
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
353
STORAGECLASS pthread_mutex_t NAME;
354
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
355
STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
356
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
357
# define gl_recursive_lock_initializer \
358
PTHREAD_RECURSIVE_MUTEX_INITIALIZER
360
# define gl_recursive_lock_initializer \
361
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
363
# define gl_recursive_lock_init(NAME) \
366
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
370
# define gl_recursive_lock_lock(NAME) \
373
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
377
# define gl_recursive_lock_unlock(NAME) \
380
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
384
# define gl_recursive_lock_destroy(NAME) \
387
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
396
pthread_mutex_t recmutex; /* recursive mutex */
397
pthread_mutex_t guard; /* protects the initialization */
401
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
402
STORAGECLASS gl_recursive_lock_t NAME;
403
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
404
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
405
# define gl_recursive_lock_initializer \
406
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
407
# define gl_recursive_lock_init(NAME) \
410
if (pthread_in_use ()) \
411
glthread_recursive_lock_init (&NAME); \
414
# define gl_recursive_lock_lock(NAME) \
417
if (pthread_in_use ()) \
418
glthread_recursive_lock_lock (&NAME); \
421
# define gl_recursive_lock_unlock(NAME) \
424
if (pthread_in_use ()) \
425
glthread_recursive_lock_unlock (&NAME); \
428
# define gl_recursive_lock_destroy(NAME) \
431
if (pthread_in_use ()) \
432
glthread_recursive_lock_destroy (&NAME); \
435
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
436
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
437
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
438
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
444
/* Old versions of POSIX threads on Solaris did not have recursive locks.
445
We have to implement them ourselves. */
449
pthread_mutex_t mutex;
454
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
455
STORAGECLASS gl_recursive_lock_t NAME;
456
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
457
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
458
# define gl_recursive_lock_initializer \
459
{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
460
# define gl_recursive_lock_init(NAME) \
463
if (pthread_in_use ()) \
464
glthread_recursive_lock_init (&NAME); \
467
# define gl_recursive_lock_lock(NAME) \
470
if (pthread_in_use ()) \
471
glthread_recursive_lock_lock (&NAME); \
474
# define gl_recursive_lock_unlock(NAME) \
477
if (pthread_in_use ()) \
478
glthread_recursive_lock_unlock (&NAME); \
481
# define gl_recursive_lock_destroy(NAME) \
484
if (pthread_in_use ()) \
485
glthread_recursive_lock_destroy (&NAME); \
488
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
489
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
490
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
491
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
495
/* -------------------------- gl_once_t datatype -------------------------- */
497
typedef pthread_once_t gl_once_t;
498
# define gl_once_define(STORAGECLASS, NAME) \
499
STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
500
# define gl_once(NAME, INITFUNCTION) \
503
if (pthread_in_use ()) \
505
if (pthread_once (&NAME, INITFUNCTION) != 0) \
510
if (glthread_once_singlethreaded (&NAME)) \
515
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
523
/* ========================================================================= */
527
/* Use the GNU Pth threads library. */
536
# if USE_PTH_THREADS_WEAK
538
/* Use weak references to the GNU Pth threads library. */
540
# pragma weak pth_mutex_init
541
# pragma weak pth_mutex_acquire
542
# pragma weak pth_mutex_release
543
# pragma weak pth_rwlock_init
544
# pragma weak pth_rwlock_acquire
545
# pragma weak pth_rwlock_release
546
# pragma weak pth_once
548
# pragma weak pth_cancel
549
# define pth_in_use() (pth_cancel != NULL)
553
# define pth_in_use() 1
557
/* -------------------------- gl_lock_t datatype -------------------------- */
559
typedef pth_mutex_t gl_lock_t;
560
# define gl_lock_define(STORAGECLASS, NAME) \
561
STORAGECLASS pth_mutex_t NAME;
562
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
563
STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
564
# define gl_lock_initializer \
566
# define gl_lock_init(NAME) \
569
if (pth_in_use() && !pth_mutex_init (&NAME)) \
573
# define gl_lock_lock(NAME) \
576
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
580
# define gl_lock_unlock(NAME) \
583
if (pth_in_use() && !pth_mutex_release (&NAME)) \
587
# define gl_lock_destroy(NAME) \
590
/* ------------------------- gl_rwlock_t datatype ------------------------- */
592
typedef pth_rwlock_t gl_rwlock_t;
593
# define gl_rwlock_define(STORAGECLASS, NAME) \
594
STORAGECLASS pth_rwlock_t NAME;
595
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
596
STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
597
# define gl_rwlock_initializer \
599
# define gl_rwlock_init(NAME) \
602
if (pth_in_use() && !pth_rwlock_init (&NAME)) \
606
# define gl_rwlock_rdlock(NAME) \
610
&& !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \
614
# define gl_rwlock_wrlock(NAME) \
618
&& !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \
622
# define gl_rwlock_unlock(NAME) \
625
if (pth_in_use() && !pth_rwlock_release (&NAME)) \
629
# define gl_rwlock_destroy(NAME) \
632
/* --------------------- gl_recursive_lock_t datatype --------------------- */
634
/* In Pth, mutexes are recursive by default. */
635
typedef pth_mutex_t gl_recursive_lock_t;
636
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
637
STORAGECLASS pth_mutex_t NAME;
638
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
639
STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
640
# define gl_recursive_lock_initializer \
642
# define gl_recursive_lock_init(NAME) \
645
if (pth_in_use() && !pth_mutex_init (&NAME)) \
649
# define gl_recursive_lock_lock(NAME) \
652
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
656
# define gl_recursive_lock_unlock(NAME) \
659
if (pth_in_use() && !pth_mutex_release (&NAME)) \
663
# define gl_recursive_lock_destroy(NAME) \
666
/* -------------------------- gl_once_t datatype -------------------------- */
668
typedef pth_once_t gl_once_t;
669
# define gl_once_define(STORAGECLASS, NAME) \
670
STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
671
# define gl_once(NAME, INITFUNCTION) \
676
void (*gl_once_temp) (void) = INITFUNCTION; \
677
if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
682
if (glthread_once_singlethreaded (&NAME)) \
687
extern void glthread_once_call (void *arg);
688
extern int glthread_once_singlethreaded (pth_once_t *once_control);
696
/* ========================================================================= */
698
#if USE_SOLARIS_THREADS
700
/* Use the old Solaris threads library. */
710
# if USE_SOLARIS_THREADS_WEAK
712
/* Use weak references to the old Solaris threads library. */
714
# pragma weak mutex_init
715
# pragma weak mutex_lock
716
# pragma weak mutex_unlock
717
# pragma weak mutex_destroy
718
# pragma weak rwlock_init
719
# pragma weak rw_rdlock
720
# pragma weak rw_wrlock
721
# pragma weak rw_unlock
722
# pragma weak rwlock_destroy
723
# pragma weak thr_self
725
# pragma weak thr_suspend
726
# define thread_in_use() (thr_suspend != NULL)
730
# define thread_in_use() 1
734
/* -------------------------- gl_lock_t datatype -------------------------- */
736
typedef mutex_t gl_lock_t;
737
# define gl_lock_define(STORAGECLASS, NAME) \
738
STORAGECLASS mutex_t NAME;
739
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
740
STORAGECLASS mutex_t NAME = gl_lock_initializer;
741
# define gl_lock_initializer \
743
# define gl_lock_init(NAME) \
746
if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \
750
# define gl_lock_lock(NAME) \
753
if (thread_in_use () && mutex_lock (&NAME) != 0) \
757
# define gl_lock_unlock(NAME) \
760
if (thread_in_use () && mutex_unlock (&NAME) != 0) \
764
# define gl_lock_destroy(NAME) \
767
if (thread_in_use () && mutex_destroy (&NAME) != 0) \
772
/* ------------------------- gl_rwlock_t datatype ------------------------- */
774
typedef rwlock_t gl_rwlock_t;
775
# define gl_rwlock_define(STORAGECLASS, NAME) \
776
STORAGECLASS rwlock_t NAME;
777
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
778
STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
779
# define gl_rwlock_initializer \
781
# define gl_rwlock_init(NAME) \
784
if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \
788
# define gl_rwlock_rdlock(NAME) \
791
if (thread_in_use () && rw_rdlock (&NAME) != 0) \
795
# define gl_rwlock_wrlock(NAME) \
798
if (thread_in_use () && rw_wrlock (&NAME) != 0) \
802
# define gl_rwlock_unlock(NAME) \
805
if (thread_in_use () && rw_unlock (&NAME) != 0) \
809
# define gl_rwlock_destroy(NAME) \
812
if (thread_in_use () && rwlock_destroy (&NAME) != 0) \
817
/* --------------------- gl_recursive_lock_t datatype --------------------- */
819
/* Old Solaris threads did not have recursive locks.
820
We have to implement them ourselves. */
829
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
830
STORAGECLASS gl_recursive_lock_t NAME;
831
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
832
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
833
# define gl_recursive_lock_initializer \
834
{ DEFAULTMUTEX, (thread_t) 0, 0 }
835
# define gl_recursive_lock_init(NAME) \
838
if (thread_in_use ()) \
839
glthread_recursive_lock_init (&NAME); \
842
# define gl_recursive_lock_lock(NAME) \
845
if (thread_in_use ()) \
846
glthread_recursive_lock_lock (&NAME); \
849
# define gl_recursive_lock_unlock(NAME) \
852
if (thread_in_use ()) \
853
glthread_recursive_lock_unlock (&NAME); \
856
# define gl_recursive_lock_destroy(NAME) \
859
if (thread_in_use ()) \
860
glthread_recursive_lock_destroy (&NAME); \
863
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
864
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
865
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
866
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
868
/* -------------------------- gl_once_t datatype -------------------------- */
876
# define gl_once_define(STORAGECLASS, NAME) \
877
STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
878
# define gl_once(NAME, INITFUNCTION) \
881
if (thread_in_use ()) \
883
glthread_once (&NAME, INITFUNCTION); \
887
if (glthread_once_singlethreaded (&NAME)) \
892
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
893
extern int glthread_once_singlethreaded (gl_once_t *once_control);
901
/* ========================================================================= */
903
#if USE_WIN32_THREADS
905
# include <windows.h>
911
/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
912
Semaphore types, because
913
- we need only to synchronize inside a single process (address space),
914
not inter-process locking,
915
- we don't need to support trylock operations. (TryEnterCriticalSection
916
does not work on Windows 95/98/ME. Packages that need trylock usually
917
define their own mutex type.) */
919
/* There is no way to statically initialize a CRITICAL_SECTION. It needs
920
to be done lazily, once only. For this we need spinlocks. */
922
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
924
/* -------------------------- gl_lock_t datatype -------------------------- */
928
gl_spinlock_t guard; /* protects the initialization */
929
CRITICAL_SECTION lock;
932
# define gl_lock_define(STORAGECLASS, NAME) \
933
STORAGECLASS gl_lock_t NAME;
934
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
935
STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
936
# define gl_lock_initializer \
938
# define gl_lock_init(NAME) \
939
glthread_lock_init (&NAME)
940
# define gl_lock_lock(NAME) \
941
glthread_lock_lock (&NAME)
942
# define gl_lock_unlock(NAME) \
943
glthread_lock_unlock (&NAME)
944
# define gl_lock_destroy(NAME) \
945
glthread_lock_destroy (&NAME)
946
extern void glthread_lock_init (gl_lock_t *lock);
947
extern void glthread_lock_lock (gl_lock_t *lock);
948
extern void glthread_lock_unlock (gl_lock_t *lock);
949
extern void glthread_lock_destroy (gl_lock_t *lock);
951
/* ------------------------- gl_rwlock_t datatype ------------------------- */
953
/* It is impossible to implement read-write locks using plain locks, without
954
introducing an extra thread dedicated to managing read-write locks.
955
Therefore here we need to use the low-level Event type. */
959
HANDLE *array; /* array of waiting threads, each represented by an event */
960
unsigned int count; /* number of waiting threads */
961
unsigned int alloc; /* length of allocated array */
962
unsigned int offset; /* index of first waiting thread in array */
967
gl_spinlock_t guard; /* protects the initialization */
968
CRITICAL_SECTION lock; /* protects the remaining fields */
969
gl_waitqueue_t waiting_readers; /* waiting readers */
970
gl_waitqueue_t waiting_writers; /* waiting writers */
971
int runcount; /* number of readers running, or -1 when a writer runs */
974
# define gl_rwlock_define(STORAGECLASS, NAME) \
975
STORAGECLASS gl_rwlock_t NAME;
976
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
977
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
978
# define gl_rwlock_initializer \
980
# define gl_rwlock_init(NAME) \
981
glthread_rwlock_init (&NAME)
982
# define gl_rwlock_rdlock(NAME) \
983
glthread_rwlock_rdlock (&NAME)
984
# define gl_rwlock_wrlock(NAME) \
985
glthread_rwlock_wrlock (&NAME)
986
# define gl_rwlock_unlock(NAME) \
987
glthread_rwlock_unlock (&NAME)
988
# define gl_rwlock_destroy(NAME) \
989
glthread_rwlock_destroy (&NAME)
990
extern void glthread_rwlock_init (gl_rwlock_t *lock);
991
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
992
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
993
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
994
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
996
/* --------------------- gl_recursive_lock_t datatype --------------------- */
998
/* The Win32 documentation says that CRITICAL_SECTION already implements a
999
recursive lock. But we need not rely on it: It's easy to implement a
1000
recursive lock without this assumption. */
1004
gl_spinlock_t guard; /* protects the initialization */
1006
unsigned long depth;
1007
CRITICAL_SECTION lock;
1009
gl_recursive_lock_t;
1010
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
1011
STORAGECLASS gl_recursive_lock_t NAME;
1012
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
1013
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
1014
# define gl_recursive_lock_initializer \
1016
# define gl_recursive_lock_init(NAME) \
1017
glthread_recursive_lock_init (&NAME)
1018
# define gl_recursive_lock_lock(NAME) \
1019
glthread_recursive_lock_lock (&NAME)
1020
# define gl_recursive_lock_unlock(NAME) \
1021
glthread_recursive_lock_unlock (&NAME)
1022
# define gl_recursive_lock_destroy(NAME) \
1023
glthread_recursive_lock_destroy (&NAME)
1024
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
1025
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
1026
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
1027
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
1029
/* -------------------------- gl_once_t datatype -------------------------- */
1033
volatile int inited;
1034
volatile long started;
1035
CRITICAL_SECTION lock;
1038
# define gl_once_define(STORAGECLASS, NAME) \
1039
STORAGECLASS gl_once_t NAME = { -1, -1 };
1040
# define gl_once(NAME, INITFUNCTION) \
1041
glthread_once (&NAME, INITFUNCTION)
1042
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
1050
/* ========================================================================= */
1052
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
1054
/* Provide dummy implementation if threads are not supported. */
1056
/* -------------------------- gl_lock_t datatype -------------------------- */
1058
typedef int gl_lock_t;
1059
# define gl_lock_define(STORAGECLASS, NAME)
1060
# define gl_lock_define_initialized(STORAGECLASS, NAME)
1061
# define gl_lock_init(NAME)
1062
# define gl_lock_lock(NAME)
1063
# define gl_lock_unlock(NAME)
1065
/* ------------------------- gl_rwlock_t datatype ------------------------- */
1067
typedef int gl_rwlock_t;
1068
# define gl_rwlock_define(STORAGECLASS, NAME)
1069
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
1070
# define gl_rwlock_init(NAME)
1071
# define gl_rwlock_rdlock(NAME)
1072
# define gl_rwlock_wrlock(NAME)
1073
# define gl_rwlock_unlock(NAME)
1075
/* --------------------- gl_recursive_lock_t datatype --------------------- */
1077
typedef int gl_recursive_lock_t;
1078
# define gl_recursive_lock_define(STORAGECLASS, NAME)
1079
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
1080
# define gl_recursive_lock_init(NAME)
1081
# define gl_recursive_lock_lock(NAME)
1082
# define gl_recursive_lock_unlock(NAME)
1084
/* -------------------------- gl_once_t datatype -------------------------- */
1086
typedef int gl_once_t;
1087
# define gl_once_define(STORAGECLASS, NAME) \
1088
STORAGECLASS gl_once_t NAME = 0;
1089
# define gl_once(NAME, INITFUNCTION) \
1102
/* ========================================================================= */
1104
#endif /* _LOCK_H */