1 /* Locking in multithreaded situations.
2 Copyright (C) 2005 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);
62 /* ========================================================================= */
66 /* Use the POSIX threads library. */
71 # if USE_POSIX_THREADS_WEAK
73 /* Use weak references to the POSIX threads library. */
75 /* Weak references avoid dragging in external libraries if the other parts
76 of the program don't use them. Here we use them, because we don't want
77 every program that uses libintl to depend on libpthread. This assumes
78 that libpthread would not be loaded after libintl; i.e. if libintl is
79 loaded first, by an executable that does not depend on libpthread, and
80 then a module is dynamically loaded that depends on libpthread, libintl
81 will not be multithread-safe. */
83 /* The way to test at runtime whether libpthread is present is to test
84 whether a function pointer's value, such as &pthread_mutex_init, is
85 non-NULL. However, some versions of GCC have a bug through which, in
86 PIC mode, &foo != NULL always evaluates to true if there is a direct
87 call to foo(...) in the same function. To avoid this, we test the
88 address of a function in libpthread that we don't use. */
90 # pragma weak pthread_mutex_init
91 # pragma weak pthread_mutex_lock
92 # pragma weak pthread_mutex_unlock
93 # pragma weak pthread_mutex_destroy
94 # pragma weak pthread_rwlock_init
95 # pragma weak pthread_rwlock_rdlock
96 # pragma weak pthread_rwlock_wrlock
97 # pragma weak pthread_rwlock_unlock
98 # pragma weak pthread_rwlock_destroy
99 # pragma weak pthread_once
100 # pragma weak pthread_cond_init
101 # pragma weak pthread_cond_wait
102 # pragma weak pthread_cond_signal
103 # pragma weak pthread_cond_broadcast
104 # pragma weak pthread_cond_destroy
105 # pragma weak pthread_mutexattr_init
106 # pragma weak pthread_mutexattr_settype
107 # pragma weak pthread_mutexattr_destroy
108 # ifndef pthread_self
109 # pragma weak pthread_self
112 # pragma weak pthread_cancel
113 # define pthread_in_use() (pthread_cancel != NULL)
117 # define pthread_in_use() 1
121 /* -------------------------- gl_lock_t datatype -------------------------- */
123 typedef pthread_mutex_t gl_lock_t;
124 # define gl_lock_define(STORAGECLASS, NAME) \
125 STORAGECLASS pthread_mutex_t NAME;
126 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
127 STORAGECLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
128 # define gl_lock_init(NAME) \
129 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
130 # define gl_lock_lock(NAME) \
131 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
132 # define gl_lock_unlock(NAME) \
133 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
134 # define gl_lock_destroy(NAME) \
135 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
137 /* ------------------------- gl_rwlock_t datatype ------------------------- */
139 # if HAVE_PTHREAD_RWLOCK
141 # ifdef PTHREAD_RWLOCK_INITIALIZER
143 typedef pthread_rwlock_t gl_rwlock_t;
144 # define gl_rwlock_define(STORAGECLASS, NAME) \
145 STORAGECLASS pthread_rwlock_t NAME;
146 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
147 STORAGECLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
148 # define gl_rwlock_init(NAME) \
149 if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
150 # define gl_rwlock_rdlock(NAME) \
151 if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
152 # define gl_rwlock_wrlock(NAME) \
153 if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
154 # define gl_rwlock_unlock(NAME) \
155 if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
156 # define gl_rwlock_destroy(NAME) \
157 if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
164 pthread_mutex_t guard; /* protects the initialization */
165 pthread_rwlock_t rwlock; /* read-write lock */
168 # define gl_rwlock_define(STORAGECLASS, NAME) \
169 STORAGECLASS gl_rwlock_t NAME;
170 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
171 STORAGECLASS gl_rwlock_t NAME = { 0, PTHREAD_MUTEX_INITIALIZER };
172 # define gl_rwlock_init(NAME) \
173 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
174 # define gl_rwlock_rdlock(NAME) \
175 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
176 # define gl_rwlock_wrlock(NAME) \
177 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
178 # define gl_rwlock_unlock(NAME) \
179 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
180 # define gl_rwlock_destroy(NAME) \
181 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
182 extern void glthread_rwlock_init (gl_rwlock_t *lock);
183 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
184 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
185 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
186 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
194 pthread_mutex_t lock; /* protects the remaining fields */
195 pthread_cond_t waiting_readers; /* waiting readers */
196 pthread_cond_t waiting_writers; /* waiting writers */
197 unsigned int waiting_writers_count; /* number of waiting writers */
198 int runcount; /* number of readers running, or -1 when a writer runs */
201 # define gl_rwlock_define(STORAGECLASS, NAME) \
202 STORAGECLASS gl_rwlock_t NAME;
203 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
204 STORAGECLASS gl_rwlock_t NAME = \
205 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 };
206 # define gl_rwlock_init(NAME) \
207 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
208 # define gl_rwlock_rdlock(NAME) \
209 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
210 # define gl_rwlock_wrlock(NAME) \
211 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
212 # define gl_rwlock_unlock(NAME) \
213 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
214 # define gl_rwlock_destroy(NAME) \
215 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
216 extern void glthread_rwlock_init (gl_rwlock_t *lock);
217 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
218 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
219 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
220 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
224 /* --------------------- gl_recursive_lock_t datatype --------------------- */
226 # if HAVE_PTHREAD_MUTEX_RECURSIVE
228 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
230 typedef pthread_mutex_t gl_recursive_lock_t;
231 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
232 STORAGECLASS pthread_mutex_t NAME;
233 # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
234 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
235 STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
237 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
238 STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
240 # define gl_recursive_lock_init(NAME) \
241 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
242 # define gl_recursive_lock_lock(NAME) \
243 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
244 # define gl_recursive_lock_unlock(NAME) \
245 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
246 # define gl_recursive_lock_destroy(NAME) \
247 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
253 pthread_mutex_t recmutex; /* recursive mutex */
254 pthread_mutex_t guard; /* protects the initialization */
258 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
259 STORAGECLASS gl_recursive_lock_t NAME;
260 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
261 STORAGECLASS gl_recursive_lock_t NAME = \
262 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 };
263 # define gl_recursive_lock_init(NAME) \
264 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
265 # define gl_recursive_lock_lock(NAME) \
266 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
267 # define gl_recursive_lock_unlock(NAME) \
268 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
269 # define gl_recursive_lock_destroy(NAME) \
270 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
271 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
272 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
273 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
274 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
280 /* Old versions of POSIX threads on Solaris did not have recursive locks.
281 We have to implement them ourselves. */
285 pthread_mutex_t mutex;
290 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
291 STORAGECLASS gl_recursive_lock_t NAME;
292 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
293 STORAGECLASS gl_recursive_lock_t NAME = \
294 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 };
295 # define gl_recursive_lock_init(NAME) \
296 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
297 # define gl_recursive_lock_lock(NAME) \
298 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
299 # define gl_recursive_lock_unlock(NAME) \
300 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
301 # define gl_recursive_lock_destroy(NAME) \
302 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
303 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
304 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
305 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
306 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
310 /* -------------------------- gl_once_t datatype -------------------------- */
312 typedef pthread_once_t gl_once_t;
313 # define gl_once_define(STORAGECLASS, NAME) \
314 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
315 # define gl_once(NAME, INITFUNCTION) \
318 if (pthread_in_use ()) \
320 if (pthread_once (&NAME, INITFUNCTION) != 0) \
325 if (glthread_once_singlethreaded (&NAME)) \
330 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
334 /* ========================================================================= */
338 /* Use the GNU Pth threads library. */
343 # if USE_PTH_THREADS_WEAK
345 /* Use weak references to the GNU Pth threads library. */
347 # pragma weak pth_mutex_init
348 # pragma weak pth_mutex_acquire
349 # pragma weak pth_mutex_release
350 # pragma weak pth_rwlock_init
351 # pragma weak pth_rwlock_acquire
352 # pragma weak pth_rwlock_release
353 # pragma weak pth_once
355 # pragma weak pth_cancel
356 # define pth_in_use() (pth_cancel != NULL)
360 # define pth_in_use() 1
364 /* -------------------------- gl_lock_t datatype -------------------------- */
366 typedef pth_mutex_t gl_lock_t;
367 # define gl_lock_define(STORAGECLASS, NAME) \
368 STORAGECLASS pth_mutex_t NAME;
369 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
370 STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
371 # define gl_lock_init(NAME) \
372 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
373 # define gl_lock_lock(NAME) \
374 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
375 # define gl_lock_unlock(NAME) \
376 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
377 # define gl_lock_destroy(NAME) \
380 /* ------------------------- gl_rwlock_t datatype ------------------------- */
382 typedef pth_rwlock_t gl_rwlock_t;
383 # define gl_rwlock_define(STORAGECLASS, NAME) \
384 STORAGECLASS pth_rwlock_t NAME;
385 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
386 STORAGECLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
387 # define gl_rwlock_init(NAME) \
388 if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
389 # define gl_rwlock_rdlock(NAME) \
390 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
391 # define gl_rwlock_wrlock(NAME) \
392 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
393 # define gl_rwlock_unlock(NAME) \
394 if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
395 # define gl_rwlock_destroy(NAME) \
398 /* --------------------- gl_recursive_lock_t datatype --------------------- */
400 /* In Pth, mutexes are recursive by default. */
401 typedef pth_mutex_t gl_recursive_lock_t;
402 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
403 STORAGECLASS pth_mutex_t NAME;
404 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
405 STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
406 # define gl_recursive_lock_init(NAME) \
407 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
408 # define gl_recursive_lock_lock(NAME) \
409 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
410 # define gl_recursive_lock_unlock(NAME) \
411 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
412 # define gl_recursive_lock_destroy(NAME) \
415 /* -------------------------- gl_once_t datatype -------------------------- */
417 typedef pth_once_t gl_once_t;
418 # define gl_once_define(STORAGECLASS, NAME) \
419 STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
420 # define gl_once(NAME, INITFUNCTION) \
425 void (*gl_once_temp) (void) = INITFUNCTION; \
426 if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
431 if (glthread_once_singlethreaded (&NAME)) \
436 extern void glthread_once_call (void *arg);
437 extern int glthread_once_singlethreaded (pth_once_t *once_control);
441 /* ========================================================================= */
443 #if USE_SOLARIS_THREADS
445 /* Use the old Solaris threads library. */
451 # if USE_SOLARIS_THREADS_WEAK
453 /* Use weak references to the old Solaris threads library. */
455 # pragma weak mutex_init
456 # pragma weak mutex_lock
457 # pragma weak mutex_unlock
458 # pragma weak mutex_destroy
459 # pragma weak rwlock_init
460 # pragma weak rw_rdlock
461 # pragma weak rw_wrlock
462 # pragma weak rw_unlock
463 # pragma weak rwlock_destroy
464 # pragma weak thr_self
466 # pragma weak thr_suspend
467 # define thread_in_use() (thr_suspend != NULL)
471 # define thread_in_use() 1
475 /* -------------------------- gl_lock_t datatype -------------------------- */
477 typedef mutex_t gl_lock_t;
478 # define gl_lock_define(STORAGECLASS, NAME) \
479 STORAGECLASS mutex_t NAME;
480 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
481 STORAGECLASS mutex_t NAME = DEFAULTMUTEX;
482 # define gl_lock_init(NAME) \
483 if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
484 # define gl_lock_lock(NAME) \
485 if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
486 # define gl_lock_unlock(NAME) \
487 if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
488 # define gl_lock_destroy(NAME) \
489 if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
491 /* ------------------------- gl_rwlock_t datatype ------------------------- */
493 typedef rwlock_t gl_rwlock_t;
494 # define gl_rwlock_define(STORAGECLASS, NAME) \
495 STORAGECLASS rwlock_t NAME;
496 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
497 STORAGECLASS rwlock_t NAME = DEFAULTRWLOCK;
498 # define gl_rwlock_init(NAME) \
499 if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
500 # define gl_rwlock_rdlock(NAME) \
501 if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
502 # define gl_rwlock_wrlock(NAME) \
503 if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
504 # define gl_rwlock_unlock(NAME) \
505 if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
506 # define gl_rwlock_destroy(NAME) \
507 if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
509 /* --------------------- gl_recursive_lock_t datatype --------------------- */
511 /* Old Solaris threads did not have recursive locks.
512 We have to implement them ourselves. */
521 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
522 STORAGECLASS gl_recursive_lock_t NAME;
523 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
524 STORAGECLASS gl_recursive_lock_t NAME = { DEFAULTMUTEX, (thread_t) 0, 0 };
525 # define gl_recursive_lock_init(NAME) \
526 if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
527 # define gl_recursive_lock_lock(NAME) \
528 if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
529 # define gl_recursive_lock_unlock(NAME) \
530 if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
531 # define gl_recursive_lock_destroy(NAME) \
532 if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
533 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
534 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
535 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
536 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
538 /* -------------------------- gl_once_t datatype -------------------------- */
546 # define gl_once_define(STORAGECLASS, NAME) \
547 STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
548 # define gl_once(NAME, INITFUNCTION) \
551 if (thread_in_use ()) \
553 glthread_once (&NAME, INITFUNCTION); \
557 if (glthread_once_singlethreaded (&NAME)) \
562 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
563 extern int glthread_once_singlethreaded (gl_once_t *once_control);
567 /* ========================================================================= */
569 #if USE_WIN32_THREADS
571 # include <windows.h>
573 /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
574 Semaphore types, because
575 - we need only to synchronize inside a single process (address space),
576 not inter-process locking,
577 - we don't need to support trylock operations. (TryEnterCriticalSection
578 does not work on Windows 95/98/ME. Packages that need trylock usually
579 define their own mutex type.) */
581 /* There is no way to statically initialize a CRITICAL_SECTION. It needs
582 to be done lazily, once only. For this we need spinlocks. */
584 typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
586 /* -------------------------- gl_lock_t datatype -------------------------- */
590 gl_spinlock_t guard; /* protects the initialization */
591 CRITICAL_SECTION lock;
594 # define gl_lock_define(STORAGECLASS, NAME) \
595 STORAGECLASS gl_lock_t NAME;
596 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
597 STORAGECLASS gl_lock_t NAME = { { 0, -1 } };
598 # define gl_lock_init(NAME) \
599 glthread_lock_init (&NAME)
600 # define gl_lock_lock(NAME) \
601 glthread_lock_lock (&NAME)
602 # define gl_lock_unlock(NAME) \
603 glthread_lock_unlock (&NAME)
604 # define gl_lock_destroy(NAME) \
605 glthread_lock_destroy (&NAME)
606 extern void glthread_lock_init (gl_lock_t *lock);
607 extern void glthread_lock_lock (gl_lock_t *lock);
608 extern void glthread_lock_unlock (gl_lock_t *lock);
609 extern void glthread_lock_destroy (gl_lock_t *lock);
611 /* ------------------------- gl_rwlock_t datatype ------------------------- */
613 /* It is impossible to implement read-write locks using plain locks, without
614 introducing an extra thread dedicated to managing read-write locks.
615 Therefore here we need to use the low-level Event type. */
619 HANDLE *array; /* array of waiting threads, each represented by an event */
620 unsigned int count; /* number of waiting threads */
621 unsigned int alloc; /* length of allocated array */
622 unsigned int offset; /* index of first waiting thread in array */
627 gl_spinlock_t guard; /* protects the initialization */
628 CRITICAL_SECTION lock; /* protects the remaining fields */
629 gl_waitqueue_t waiting_readers; /* waiting readers */
630 gl_waitqueue_t waiting_writers; /* waiting writers */
631 int runcount; /* number of readers running, or -1 when a writer runs */
634 # define gl_rwlock_define(STORAGECLASS, NAME) \
635 STORAGECLASS gl_rwlock_t NAME;
636 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
637 STORAGECLASS gl_rwlock_t NAME = { { 0, -1 } };
638 # define gl_rwlock_init(NAME) \
639 glthread_rwlock_init (&NAME)
640 # define gl_rwlock_rdlock(NAME) \
641 glthread_rwlock_rdlock (&NAME)
642 # define gl_rwlock_wrlock(NAME) \
643 glthread_rwlock_wrlock (&NAME)
644 # define gl_rwlock_unlock(NAME) \
645 glthread_rwlock_unlock (&NAME)
646 # define gl_rwlock_destroy(NAME) \
647 glthread_rwlock_destroy (&NAME)
648 extern void glthread_rwlock_init (gl_rwlock_t *lock);
649 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
650 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
651 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
652 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
654 /* --------------------- gl_recursive_lock_t datatype --------------------- */
656 /* The Win32 documentation says that CRITICAL_SECTION already implements a
657 recursive lock. But we need not rely on it: It's easy to implement a
658 recursive lock without this assumption. */
662 gl_spinlock_t guard; /* protects the initialization */
665 CRITICAL_SECTION lock;
668 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
669 STORAGECLASS gl_recursive_lock_t NAME;
670 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
671 STORAGECLASS gl_recursive_lock_t NAME = { { 0, -1 }, 0, 0 };
672 # define gl_recursive_lock_init(NAME) \
673 glthread_recursive_lock_init (&NAME)
674 # define gl_recursive_lock_lock(NAME) \
675 glthread_recursive_lock_lock (&NAME)
676 # define gl_recursive_lock_unlock(NAME) \
677 glthread_recursive_lock_unlock (&NAME)
678 # define gl_recursive_lock_destroy(NAME) \
679 glthread_recursive_lock_destroy (&NAME)
680 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
681 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
682 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
683 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
685 /* -------------------------- gl_once_t datatype -------------------------- */
690 volatile long started;
691 CRITICAL_SECTION lock;
694 # define gl_once_define(STORAGECLASS, NAME) \
695 STORAGECLASS gl_once_t NAME = { -1, -1 };
696 # define gl_once(NAME, INITFUNCTION) \
697 glthread_once (&NAME, INITFUNCTION)
698 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
702 /* ========================================================================= */
704 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
706 /* Provide dummy implementation if threads are not supported. */
708 /* -------------------------- gl_lock_t datatype -------------------------- */
710 typedef int gl_lock_t;
711 # define gl_lock_define(STORAGECLASS, NAME)
712 # define gl_lock_define_initialized(STORAGECLASS, NAME)
713 # define gl_lock_init(NAME)
714 # define gl_lock_lock(NAME)
715 # define gl_lock_unlock(NAME)
717 /* ------------------------- gl_rwlock_t datatype ------------------------- */
719 typedef int gl_rwlock_t;
720 # define gl_rwlock_define(STORAGECLASS, NAME)
721 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
722 # define gl_rwlock_init(NAME)
723 # define gl_rwlock_rdlock(NAME)
724 # define gl_rwlock_wrlock(NAME)
725 # define gl_rwlock_unlock(NAME)
727 /* --------------------- gl_recursive_lock_t datatype --------------------- */
729 typedef int gl_recursive_lock_t;
730 # define gl_recursive_lock_define(STORAGECLASS, NAME)
731 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
732 # define gl_recursive_lock_init(NAME)
733 # define gl_recursive_lock_lock(NAME)
734 # define gl_recursive_lock_unlock(NAME)
736 /* -------------------------- gl_once_t datatype -------------------------- */
738 typedef int gl_once_t;
739 # define gl_once_define(STORAGECLASS, NAME) \
740 STORAGECLASS gl_once_t NAME = 0;
741 # define gl_once(NAME, INITFUNCTION) \