1
/* -*- buffer-read-only: t -*- vi: set ro: */
2
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3
/* Locking in multithreaded situations.
4
Copyright (C) 2005-2011 Free Software Foundation, Inc.
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3, or (at your option)
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software Foundation,
18
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
21
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
24
/* This file contains locking primitives for use with a given thread library.
25
It does not contain primitives for creating threads or for other
26
synchronization primitives.
28
Normal (non-recursive) locks:
30
Declaration: gl_lock_define(extern, name)
31
Initializer: gl_lock_define_initialized(, name)
32
Initialization: gl_lock_init (name);
33
Taking the lock: gl_lock_lock (name);
34
Releasing the lock: gl_lock_unlock (name);
35
De-initialization: gl_lock_destroy (name);
36
Equivalent functions with control of error handling:
37
Initialization: err = glthread_lock_init (&name);
38
Taking the lock: err = glthread_lock_lock (&name);
39
Releasing the lock: err = glthread_lock_unlock (&name);
40
De-initialization: err = glthread_lock_destroy (&name);
42
Read-Write (non-recursive) locks:
44
Declaration: gl_rwlock_define(extern, name)
45
Initializer: gl_rwlock_define_initialized(, name)
46
Initialization: gl_rwlock_init (name);
47
Taking the lock: gl_rwlock_rdlock (name);
48
gl_rwlock_wrlock (name);
49
Releasing the lock: gl_rwlock_unlock (name);
50
De-initialization: gl_rwlock_destroy (name);
51
Equivalent functions with control of error handling:
52
Initialization: err = glthread_rwlock_init (&name);
53
Taking the lock: err = glthread_rwlock_rdlock (&name);
54
err = glthread_rwlock_wrlock (&name);
55
Releasing the lock: err = glthread_rwlock_unlock (&name);
56
De-initialization: err = glthread_rwlock_destroy (&name);
59
Type: gl_recursive_lock_t
60
Declaration: gl_recursive_lock_define(extern, name)
61
Initializer: gl_recursive_lock_define_initialized(, name)
62
Initialization: gl_recursive_lock_init (name);
63
Taking the lock: gl_recursive_lock_lock (name);
64
Releasing the lock: gl_recursive_lock_unlock (name);
65
De-initialization: gl_recursive_lock_destroy (name);
66
Equivalent functions with control of error handling:
67
Initialization: err = glthread_recursive_lock_init (&name);
68
Taking the lock: err = glthread_recursive_lock_lock (&name);
69
Releasing the lock: err = glthread_recursive_lock_unlock (&name);
70
De-initialization: err = glthread_recursive_lock_destroy (&name);
74
Initializer: gl_once_define(extern, name)
75
Execution: gl_once (name, initfunction);
76
Equivalent functions with control of error handling:
77
Execution: err = glthread_once (&name, initfunction);
87
/* ========================================================================= */
91
/* Use the POSIX threads library. */
99
# if PTHREAD_IN_USE_DETECTION_HARD
101
/* The pthread_in_use() detection needs to be done at runtime. */
102
# define pthread_in_use() \
104
extern int glthread_in_use (void);
108
# if USE_POSIX_THREADS_WEAK
110
/* Use weak references to the POSIX threads library. */
112
/* Weak references avoid dragging in external libraries if the other parts
113
of the program don't use them. Here we use them, because we don't want
114
every program that uses libintl to depend on libpthread. This assumes
115
that libpthread would not be loaded after libintl; i.e. if libintl is
116
loaded first, by an executable that does not depend on libpthread, and
117
then a module is dynamically loaded that depends on libpthread, libintl
118
will not be multithread-safe. */
120
/* The way to test at runtime whether libpthread is present is to test
121
whether a function pointer's value, such as &pthread_mutex_init, is
122
non-NULL. However, some versions of GCC have a bug through which, in
123
PIC mode, &foo != NULL always evaluates to true if there is a direct
124
call to foo(...) in the same function. To avoid this, we test the
125
address of a function in libpthread that we don't use. */
127
# pragma weak pthread_mutex_init
128
# pragma weak pthread_mutex_lock
129
# pragma weak pthread_mutex_unlock
130
# pragma weak pthread_mutex_destroy
131
# pragma weak pthread_rwlock_init
132
# pragma weak pthread_rwlock_rdlock
133
# pragma weak pthread_rwlock_wrlock
134
# pragma weak pthread_rwlock_unlock
135
# pragma weak pthread_rwlock_destroy
136
# pragma weak pthread_once
137
# pragma weak pthread_cond_init
138
# pragma weak pthread_cond_wait
139
# pragma weak pthread_cond_signal
140
# pragma weak pthread_cond_broadcast
141
# pragma weak pthread_cond_destroy
142
# pragma weak pthread_mutexattr_init
143
# pragma weak pthread_mutexattr_settype
144
# pragma weak pthread_mutexattr_destroy
145
# ifndef pthread_self
146
# pragma weak pthread_self
149
# if !PTHREAD_IN_USE_DETECTION_HARD
150
# pragma weak pthread_cancel
151
# define pthread_in_use() (pthread_cancel != NULL)
156
# if !PTHREAD_IN_USE_DETECTION_HARD
157
# define pthread_in_use() 1
162
/* -------------------------- gl_lock_t datatype -------------------------- */
164
typedef pthread_mutex_t gl_lock_t;
165
# define gl_lock_define(STORAGECLASS, NAME) \
166
STORAGECLASS pthread_mutex_t NAME;
167
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
168
STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
169
# define gl_lock_initializer \
170
PTHREAD_MUTEX_INITIALIZER
171
# define glthread_lock_init(LOCK) \
172
(pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
173
# define glthread_lock_lock(LOCK) \
174
(pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
175
# define glthread_lock_unlock(LOCK) \
176
(pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
177
# define glthread_lock_destroy(LOCK) \
178
(pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
180
/* ------------------------- gl_rwlock_t datatype ------------------------- */
182
# if HAVE_PTHREAD_RWLOCK
184
# ifdef PTHREAD_RWLOCK_INITIALIZER
186
typedef pthread_rwlock_t gl_rwlock_t;
187
# define gl_rwlock_define(STORAGECLASS, NAME) \
188
STORAGECLASS pthread_rwlock_t NAME;
189
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
190
STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
191
# define gl_rwlock_initializer \
192
PTHREAD_RWLOCK_INITIALIZER
193
# define glthread_rwlock_init(LOCK) \
194
(pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
195
# define glthread_rwlock_rdlock(LOCK) \
196
(pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
197
# define glthread_rwlock_wrlock(LOCK) \
198
(pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
199
# define glthread_rwlock_unlock(LOCK) \
200
(pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
201
# define glthread_rwlock_destroy(LOCK) \
202
(pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
209
pthread_mutex_t guard; /* protects the initialization */
210
pthread_rwlock_t rwlock; /* read-write lock */
213
# define gl_rwlock_define(STORAGECLASS, NAME) \
214
STORAGECLASS gl_rwlock_t NAME;
215
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
216
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
217
# define gl_rwlock_initializer \
218
{ 0, PTHREAD_MUTEX_INITIALIZER }
219
# define glthread_rwlock_init(LOCK) \
220
(pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
221
# define glthread_rwlock_rdlock(LOCK) \
222
(pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
223
# define glthread_rwlock_wrlock(LOCK) \
224
(pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
225
# define glthread_rwlock_unlock(LOCK) \
226
(pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
227
# define glthread_rwlock_destroy(LOCK) \
228
(pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
229
extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
230
extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
231
extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
232
extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
233
extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
241
pthread_mutex_t lock; /* protects the remaining fields */
242
pthread_cond_t waiting_readers; /* waiting readers */
243
pthread_cond_t waiting_writers; /* waiting writers */
244
unsigned int waiting_writers_count; /* number of waiting writers */
245
int runcount; /* number of readers running, or -1 when a writer runs */
248
# define gl_rwlock_define(STORAGECLASS, NAME) \
249
STORAGECLASS gl_rwlock_t NAME;
250
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
251
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
252
# define gl_rwlock_initializer \
253
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
254
# define glthread_rwlock_init(LOCK) \
255
(pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
256
# define glthread_rwlock_rdlock(LOCK) \
257
(pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
258
# define glthread_rwlock_wrlock(LOCK) \
259
(pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
260
# define glthread_rwlock_unlock(LOCK) \
261
(pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
262
# define glthread_rwlock_destroy(LOCK) \
263
(pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
264
extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
265
extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
266
extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
267
extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
268
extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
272
/* --------------------- gl_recursive_lock_t datatype --------------------- */
274
# if HAVE_PTHREAD_MUTEX_RECURSIVE
276
# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
278
typedef pthread_mutex_t gl_recursive_lock_t;
279
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
280
STORAGECLASS pthread_mutex_t NAME;
281
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
282
STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
283
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
284
# define gl_recursive_lock_initializer \
285
PTHREAD_RECURSIVE_MUTEX_INITIALIZER
287
# define gl_recursive_lock_initializer \
288
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
290
# define glthread_recursive_lock_init(LOCK) \
291
(pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
292
# define glthread_recursive_lock_lock(LOCK) \
293
(pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
294
# define glthread_recursive_lock_unlock(LOCK) \
295
(pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
296
# define glthread_recursive_lock_destroy(LOCK) \
297
(pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
298
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
304
pthread_mutex_t recmutex; /* recursive mutex */
305
pthread_mutex_t guard; /* protects the initialization */
309
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
310
STORAGECLASS gl_recursive_lock_t NAME;
311
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
312
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
313
# define gl_recursive_lock_initializer \
314
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
315
# define glthread_recursive_lock_init(LOCK) \
316
(pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
317
# define glthread_recursive_lock_lock(LOCK) \
318
(pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
319
# define glthread_recursive_lock_unlock(LOCK) \
320
(pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
321
# define glthread_recursive_lock_destroy(LOCK) \
322
(pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
323
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
324
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
325
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
326
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
332
/* Old versions of POSIX threads on Solaris did not have recursive locks.
333
We have to implement them ourselves. */
337
pthread_mutex_t mutex;
342
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
343
STORAGECLASS gl_recursive_lock_t NAME;
344
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
345
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
346
# define gl_recursive_lock_initializer \
347
{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
348
# define glthread_recursive_lock_init(LOCK) \
349
(pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
350
# define glthread_recursive_lock_lock(LOCK) \
351
(pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
352
# define glthread_recursive_lock_unlock(LOCK) \
353
(pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
354
# define glthread_recursive_lock_destroy(LOCK) \
355
(pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
356
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
357
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
358
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
359
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
363
/* -------------------------- gl_once_t datatype -------------------------- */
365
typedef pthread_once_t gl_once_t;
366
# define gl_once_define(STORAGECLASS, NAME) \
367
STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
368
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
370
? pthread_once (ONCE_CONTROL, INITFUNCTION) \
371
: (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
372
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
380
/* ========================================================================= */
384
/* Use the GNU Pth threads library. */
392
# if USE_PTH_THREADS_WEAK
394
/* Use weak references to the GNU Pth threads library. */
396
# pragma weak pth_mutex_init
397
# pragma weak pth_mutex_acquire
398
# pragma weak pth_mutex_release
399
# pragma weak pth_rwlock_init
400
# pragma weak pth_rwlock_acquire
401
# pragma weak pth_rwlock_release
402
# pragma weak pth_once
404
# pragma weak pth_cancel
405
# define pth_in_use() (pth_cancel != NULL)
409
# define pth_in_use() 1
413
/* -------------------------- gl_lock_t datatype -------------------------- */
415
typedef pth_mutex_t gl_lock_t;
416
# define gl_lock_define(STORAGECLASS, NAME) \
417
STORAGECLASS pth_mutex_t NAME;
418
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
419
STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
420
# define gl_lock_initializer \
422
# define glthread_lock_init(LOCK) \
423
(pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
424
# define glthread_lock_lock(LOCK) \
425
(pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
426
# define glthread_lock_unlock(LOCK) \
427
(pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
428
# define glthread_lock_destroy(LOCK) \
431
/* ------------------------- gl_rwlock_t datatype ------------------------- */
433
typedef pth_rwlock_t gl_rwlock_t;
434
# define gl_rwlock_define(STORAGECLASS, NAME) \
435
STORAGECLASS pth_rwlock_t NAME;
436
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
437
STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
438
# define gl_rwlock_initializer \
440
# define glthread_rwlock_init(LOCK) \
441
(pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
442
# define glthread_rwlock_rdlock(LOCK) \
443
(pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
444
# define glthread_rwlock_wrlock(LOCK) \
445
(pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
446
# define glthread_rwlock_unlock(LOCK) \
447
(pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
448
# define glthread_rwlock_destroy(LOCK) \
451
/* --------------------- gl_recursive_lock_t datatype --------------------- */
453
/* In Pth, mutexes are recursive by default. */
454
typedef pth_mutex_t gl_recursive_lock_t;
455
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
456
STORAGECLASS pth_mutex_t NAME;
457
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
458
STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
459
# define gl_recursive_lock_initializer \
461
# define glthread_recursive_lock_init(LOCK) \
462
(pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
463
# define glthread_recursive_lock_lock(LOCK) \
464
(pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
465
# define glthread_recursive_lock_unlock(LOCK) \
466
(pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
467
# define glthread_recursive_lock_destroy(LOCK) \
470
/* -------------------------- gl_once_t datatype -------------------------- */
472
typedef pth_once_t gl_once_t;
473
# define gl_once_define(STORAGECLASS, NAME) \
474
STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
475
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
477
? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
478
: (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
479
extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
480
extern int glthread_once_singlethreaded (pth_once_t *once_control);
488
/* ========================================================================= */
490
#if USE_SOLARIS_THREADS
492
/* Use the old Solaris threads library. */
501
# if USE_SOLARIS_THREADS_WEAK
503
/* Use weak references to the old Solaris threads library. */
505
# pragma weak mutex_init
506
# pragma weak mutex_lock
507
# pragma weak mutex_unlock
508
# pragma weak mutex_destroy
509
# pragma weak rwlock_init
510
# pragma weak rw_rdlock
511
# pragma weak rw_wrlock
512
# pragma weak rw_unlock
513
# pragma weak rwlock_destroy
514
# pragma weak thr_self
516
# pragma weak thr_suspend
517
# define thread_in_use() (thr_suspend != NULL)
521
# define thread_in_use() 1
525
/* -------------------------- gl_lock_t datatype -------------------------- */
527
typedef mutex_t gl_lock_t;
528
# define gl_lock_define(STORAGECLASS, NAME) \
529
STORAGECLASS mutex_t NAME;
530
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
531
STORAGECLASS mutex_t NAME = gl_lock_initializer;
532
# define gl_lock_initializer \
534
# define glthread_lock_init(LOCK) \
535
(thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
536
# define glthread_lock_lock(LOCK) \
537
(thread_in_use () ? mutex_lock (LOCK) : 0)
538
# define glthread_lock_unlock(LOCK) \
539
(thread_in_use () ? mutex_unlock (LOCK) : 0)
540
# define glthread_lock_destroy(LOCK) \
541
(thread_in_use () ? mutex_destroy (LOCK) : 0)
543
/* ------------------------- gl_rwlock_t datatype ------------------------- */
545
typedef rwlock_t gl_rwlock_t;
546
# define gl_rwlock_define(STORAGECLASS, NAME) \
547
STORAGECLASS rwlock_t NAME;
548
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
549
STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
550
# define gl_rwlock_initializer \
552
# define glthread_rwlock_init(LOCK) \
553
(thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
554
# define glthread_rwlock_rdlock(LOCK) \
555
(thread_in_use () ? rw_rdlock (LOCK) : 0)
556
# define glthread_rwlock_wrlock(LOCK) \
557
(thread_in_use () ? rw_wrlock (LOCK) : 0)
558
# define glthread_rwlock_unlock(LOCK) \
559
(thread_in_use () ? rw_unlock (LOCK) : 0)
560
# define glthread_rwlock_destroy(LOCK) \
561
(thread_in_use () ? rwlock_destroy (LOCK) : 0)
563
/* --------------------- gl_recursive_lock_t datatype --------------------- */
565
/* Old Solaris threads did not have recursive locks.
566
We have to implement them ourselves. */
575
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
576
STORAGECLASS gl_recursive_lock_t NAME;
577
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
578
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
579
# define gl_recursive_lock_initializer \
580
{ DEFAULTMUTEX, (thread_t) 0, 0 }
581
# define glthread_recursive_lock_init(LOCK) \
582
(thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
583
# define glthread_recursive_lock_lock(LOCK) \
584
(thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
585
# define glthread_recursive_lock_unlock(LOCK) \
586
(thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
587
# define glthread_recursive_lock_destroy(LOCK) \
588
(thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
589
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
590
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
591
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
592
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
594
/* -------------------------- gl_once_t datatype -------------------------- */
602
# define gl_once_define(STORAGECLASS, NAME) \
603
STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
604
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
606
? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
607
: (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
608
extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
609
extern int glthread_once_singlethreaded (gl_once_t *once_control);
617
/* ========================================================================= */
619
#if USE_WIN32_THREADS
621
# include <windows.h>
627
/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
628
Semaphore types, because
629
- we need only to synchronize inside a single process (address space),
630
not inter-process locking,
631
- we don't need to support trylock operations. (TryEnterCriticalSection
632
does not work on Windows 95/98/ME. Packages that need trylock usually
633
define their own mutex type.) */
635
/* There is no way to statically initialize a CRITICAL_SECTION. It needs
636
to be done lazily, once only. For this we need spinlocks. */
638
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
640
/* -------------------------- gl_lock_t datatype -------------------------- */
644
gl_spinlock_t guard; /* protects the initialization */
645
CRITICAL_SECTION lock;
648
# define gl_lock_define(STORAGECLASS, NAME) \
649
STORAGECLASS gl_lock_t NAME;
650
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
651
STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
652
# define gl_lock_initializer \
654
# define glthread_lock_init(LOCK) \
655
(glthread_lock_init_func (LOCK), 0)
656
# define glthread_lock_lock(LOCK) \
657
glthread_lock_lock_func (LOCK)
658
# define glthread_lock_unlock(LOCK) \
659
glthread_lock_unlock_func (LOCK)
660
# define glthread_lock_destroy(LOCK) \
661
glthread_lock_destroy_func (LOCK)
662
extern void glthread_lock_init_func (gl_lock_t *lock);
663
extern int glthread_lock_lock_func (gl_lock_t *lock);
664
extern int glthread_lock_unlock_func (gl_lock_t *lock);
665
extern int glthread_lock_destroy_func (gl_lock_t *lock);
667
/* ------------------------- gl_rwlock_t datatype ------------------------- */
669
/* It is impossible to implement read-write locks using plain locks, without
670
introducing an extra thread dedicated to managing read-write locks.
671
Therefore here we need to use the low-level Event type. */
675
HANDLE *array; /* array of waiting threads, each represented by an event */
676
unsigned int count; /* number of waiting threads */
677
unsigned int alloc; /* length of allocated array */
678
unsigned int offset; /* index of first waiting thread in array */
680
gl_carray_waitqueue_t;
683
gl_spinlock_t guard; /* protects the initialization */
684
CRITICAL_SECTION lock; /* protects the remaining fields */
685
gl_carray_waitqueue_t waiting_readers; /* waiting readers */
686
gl_carray_waitqueue_t waiting_writers; /* waiting writers */
687
int runcount; /* number of readers running, or -1 when a writer runs */
690
# define gl_rwlock_define(STORAGECLASS, NAME) \
691
STORAGECLASS gl_rwlock_t NAME;
692
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
693
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
694
# define gl_rwlock_initializer \
696
# define glthread_rwlock_init(LOCK) \
697
(glthread_rwlock_init_func (LOCK), 0)
698
# define glthread_rwlock_rdlock(LOCK) \
699
glthread_rwlock_rdlock_func (LOCK)
700
# define glthread_rwlock_wrlock(LOCK) \
701
glthread_rwlock_wrlock_func (LOCK)
702
# define glthread_rwlock_unlock(LOCK) \
703
glthread_rwlock_unlock_func (LOCK)
704
# define glthread_rwlock_destroy(LOCK) \
705
glthread_rwlock_destroy_func (LOCK)
706
extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
707
extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
708
extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
709
extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
710
extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
712
/* --------------------- gl_recursive_lock_t datatype --------------------- */
714
/* The Win32 documentation says that CRITICAL_SECTION already implements a
715
recursive lock. But we need not rely on it: It's easy to implement a
716
recursive lock without this assumption. */
720
gl_spinlock_t guard; /* protects the initialization */
723
CRITICAL_SECTION lock;
726
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
727
STORAGECLASS gl_recursive_lock_t NAME;
728
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
729
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
730
# define gl_recursive_lock_initializer \
732
# define glthread_recursive_lock_init(LOCK) \
733
(glthread_recursive_lock_init_func (LOCK), 0)
734
# define glthread_recursive_lock_lock(LOCK) \
735
glthread_recursive_lock_lock_func (LOCK)
736
# define glthread_recursive_lock_unlock(LOCK) \
737
glthread_recursive_lock_unlock_func (LOCK)
738
# define glthread_recursive_lock_destroy(LOCK) \
739
glthread_recursive_lock_destroy_func (LOCK)
740
extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
741
extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
742
extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
743
extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
745
/* -------------------------- gl_once_t datatype -------------------------- */
750
volatile long started;
751
CRITICAL_SECTION lock;
754
# define gl_once_define(STORAGECLASS, NAME) \
755
STORAGECLASS gl_once_t NAME = { -1, -1 };
756
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
757
(glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0)
758
extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
766
/* ========================================================================= */
768
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
770
/* Provide dummy implementation if threads are not supported. */
772
/* -------------------------- gl_lock_t datatype -------------------------- */
774
typedef int gl_lock_t;
775
# define gl_lock_define(STORAGECLASS, NAME)
776
# define gl_lock_define_initialized(STORAGECLASS, NAME)
777
# define glthread_lock_init(NAME) 0
778
# define glthread_lock_lock(NAME) 0
779
# define glthread_lock_unlock(NAME) 0
780
# define glthread_lock_destroy(NAME) 0
782
/* ------------------------- gl_rwlock_t datatype ------------------------- */
784
typedef int gl_rwlock_t;
785
# define gl_rwlock_define(STORAGECLASS, NAME)
786
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
787
# define glthread_rwlock_init(NAME) 0
788
# define glthread_rwlock_rdlock(NAME) 0
789
# define glthread_rwlock_wrlock(NAME) 0
790
# define glthread_rwlock_unlock(NAME) 0
791
# define glthread_rwlock_destroy(NAME) 0
793
/* --------------------- gl_recursive_lock_t datatype --------------------- */
795
typedef int gl_recursive_lock_t;
796
# define gl_recursive_lock_define(STORAGECLASS, NAME)
797
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
798
# define glthread_recursive_lock_init(NAME) 0
799
# define glthread_recursive_lock_lock(NAME) 0
800
# define glthread_recursive_lock_unlock(NAME) 0
801
# define glthread_recursive_lock_destroy(NAME) 0
803
/* -------------------------- gl_once_t datatype -------------------------- */
805
typedef int gl_once_t;
806
# define gl_once_define(STORAGECLASS, NAME) \
807
STORAGECLASS gl_once_t NAME = 0;
808
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
809
(*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
813
/* ========================================================================= */
815
/* Macros with built-in error handling. */
817
/* -------------------------- gl_lock_t datatype -------------------------- */
819
#define gl_lock_init(NAME) \
822
if (glthread_lock_init (&NAME)) \
826
#define gl_lock_lock(NAME) \
829
if (glthread_lock_lock (&NAME)) \
833
#define gl_lock_unlock(NAME) \
836
if (glthread_lock_unlock (&NAME)) \
840
#define gl_lock_destroy(NAME) \
843
if (glthread_lock_destroy (&NAME)) \
848
/* ------------------------- gl_rwlock_t datatype ------------------------- */
850
#define gl_rwlock_init(NAME) \
853
if (glthread_rwlock_init (&NAME)) \
857
#define gl_rwlock_rdlock(NAME) \
860
if (glthread_rwlock_rdlock (&NAME)) \
864
#define gl_rwlock_wrlock(NAME) \
867
if (glthread_rwlock_wrlock (&NAME)) \
871
#define gl_rwlock_unlock(NAME) \
874
if (glthread_rwlock_unlock (&NAME)) \
878
#define gl_rwlock_destroy(NAME) \
881
if (glthread_rwlock_destroy (&NAME)) \
886
/* --------------------- gl_recursive_lock_t datatype --------------------- */
888
#define gl_recursive_lock_init(NAME) \
891
if (glthread_recursive_lock_init (&NAME)) \
895
#define gl_recursive_lock_lock(NAME) \
898
if (glthread_recursive_lock_lock (&NAME)) \
902
#define gl_recursive_lock_unlock(NAME) \
905
if (glthread_recursive_lock_unlock (&NAME)) \
909
#define gl_recursive_lock_destroy(NAME) \
912
if (glthread_recursive_lock_destroy (&NAME)) \
917
/* -------------------------- gl_once_t datatype -------------------------- */
919
#define gl_once(NAME, INITFUNCTION) \
922
if (glthread_once (&NAME, INITFUNCTION)) \
927
/* ========================================================================= */