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 /* ========================================================================= */
61 /* Use the POSIX threads library. */
66 # if USE_POSIX_THREADS_WEAK
68 /* Use weak references to the POSIX threads library. */
70 /* Weak references avoid dragging in external libraries if the other parts
71 of the program don't use them. Here we use them, because we don't want
72 every program that uses libintl to depend on libpthread. This assumes
73 that libpthread would not be loaded after libintl; i.e. if libintl is
74 loaded first, by an executable that does not depend on libpthread, and
75 then a module is dynamically loaded that depends on libpthread, libintl
76 will not be multithread-safe. */
78 /* The way to test at runtime whether libpthread is present is to test
79 whether a function pointer's value, such as &pthread_mutex_init, is
80 non-NULL. However, some versions of GCC have a bug through which, in
81 PIC mode, &foo != NULL always evaluates to true if there is a direct
82 call to foo(...) in the same function. To avoid this, we test the
83 address of a function in libpthread that we don't use. */
85 # pragma weak pthread_mutex_init
86 # pragma weak pthread_mutex_lock
87 # pragma weak pthread_mutex_unlock
88 # pragma weak pthread_mutex_destroy
89 # pragma weak pthread_rwlock_init
90 # pragma weak pthread_rwlock_rdlock
91 # pragma weak pthread_rwlock_wrlock
92 # pragma weak pthread_rwlock_unlock
93 # pragma weak pthread_rwlock_destroy
94 # pragma weak pthread_cond_init
95 # pragma weak pthread_cond_wait
96 # pragma weak pthread_cond_signal
97 # pragma weak pthread_cond_broadcast
98 # pragma weak pthread_cond_destroy
99 # pragma weak pthread_mutexattr_init
100 # pragma weak pthread_mutexattr_settype
101 # pragma weak pthread_mutexattr_destroy
102 # ifndef pthread_self
103 # pragma weak pthread_self
106 # pragma weak pthread_cancel
107 # define pthread_in_use() (pthread_cancel != NULL)
111 # define pthread_in_use() 1
115 /* -------------------------- gl_lock_t datatype -------------------------- */
117 typedef pthread_mutex_t gl_lock_t;
118 # define gl_lock_define(STORAGECLASS, NAME) \
119 STORAGECLASS pthread_mutex_t NAME;
120 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
121 STORAGECLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
122 # define gl_lock_init(NAME) \
123 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
124 # define gl_lock_lock(NAME) \
125 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
126 # define gl_lock_unlock(NAME) \
127 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
128 # define gl_lock_destroy(NAME) \
129 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
131 /* ------------------------- gl_rwlock_t datatype ------------------------- */
133 # if HAVE_PTHREAD_RWLOCK
135 # ifdef PTHREAD_RWLOCK_INITIALIZER
137 typedef pthread_rwlock_t gl_rwlock_t;
138 # define gl_rwlock_define(STORAGECLASS, NAME) \
139 STORAGECLASS pthread_rwlock_t NAME;
140 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
141 STORAGECLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
142 # define gl_rwlock_init(NAME) \
143 if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
144 # define gl_rwlock_rdlock(NAME) \
145 if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
146 # define gl_rwlock_wrlock(NAME) \
147 if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
148 # define gl_rwlock_unlock(NAME) \
149 if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
150 # define gl_rwlock_destroy(NAME) \
151 if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
158 pthread_mutex_t guard; /* protects the initialization */
159 pthread_rwlock_t rwlock; /* read-write lock */
162 # define gl_rwlock_define(STORAGECLASS, NAME) \
163 STORAGECLASS gl_rwlock_t NAME;
164 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
165 STORAGECLASS gl_rwlock_t NAME = { 0, PTHREAD_MUTEX_INITIALIZER };
166 # define gl_rwlock_init(NAME) \
167 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
168 # define gl_rwlock_rdlock(NAME) \
169 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
170 # define gl_rwlock_wrlock(NAME) \
171 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
172 # define gl_rwlock_unlock(NAME) \
173 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
174 # define gl_rwlock_destroy(NAME) \
175 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
176 extern void glthread_rwlock_init (gl_rwlock_t *lock);
177 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
178 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
179 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
180 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
188 pthread_mutex_t lock; /* protects the remaining fields */
189 pthread_cond_t waiting_readers; /* waiting readers */
190 pthread_cond_t waiting_writers; /* waiting writers */
191 unsigned int waiting_writers_count; /* number of waiting writers */
192 int runcount; /* number of readers running, or -1 when a writer runs */
195 # define gl_rwlock_define(STORAGECLASS, NAME) \
196 STORAGECLASS gl_rwlock_t NAME;
197 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
198 STORAGECLASS gl_rwlock_t NAME = \
199 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 };
200 # define gl_rwlock_init(NAME) \
201 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
202 # define gl_rwlock_rdlock(NAME) \
203 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
204 # define gl_rwlock_wrlock(NAME) \
205 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
206 # define gl_rwlock_unlock(NAME) \
207 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
208 # define gl_rwlock_destroy(NAME) \
209 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
210 extern void glthread_rwlock_init (gl_rwlock_t *lock);
211 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
212 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
213 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
214 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
218 /* --------------------- gl_recursive_lock_t datatype --------------------- */
220 # if HAVE_PTHREAD_MUTEX_RECURSIVE
222 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
224 typedef pthread_mutex_t gl_recursive_lock_t;
225 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
226 STORAGECLASS pthread_mutex_t NAME;
227 # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
228 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
229 STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
231 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
232 STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
234 # define gl_recursive_lock_init(NAME) \
235 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
236 # define gl_recursive_lock_lock(NAME) \
237 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
238 # define gl_recursive_lock_unlock(NAME) \
239 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
240 # define gl_recursive_lock_destroy(NAME) \
241 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
247 pthread_mutex_t recmutex; /* recursive mutex */
248 pthread_mutex_t guard; /* protects the initialization */
252 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
253 STORAGECLASS gl_recursive_lock_t NAME;
254 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
255 STORAGECLASS gl_recursive_lock_t NAME = \
256 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 };
257 # define gl_recursive_lock_init(NAME) \
258 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
259 # define gl_recursive_lock_lock(NAME) \
260 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
261 # define gl_recursive_lock_unlock(NAME) \
262 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
263 # define gl_recursive_lock_destroy(NAME) \
264 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
265 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
266 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
267 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
268 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
274 /* Old versions of POSIX threads on Solaris did not have recursive locks.
275 We have to implement them ourselves. */
279 pthread_mutex_t mutex;
284 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
285 STORAGECLASS gl_recursive_lock_t NAME;
286 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
287 STORAGECLASS gl_recursive_lock_t NAME = \
288 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 };
289 # define gl_recursive_lock_init(NAME) \
290 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
291 # define gl_recursive_lock_lock(NAME) \
292 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
293 # define gl_recursive_lock_unlock(NAME) \
294 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
295 # define gl_recursive_lock_destroy(NAME) \
296 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
297 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
298 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
299 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
300 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
306 /* ========================================================================= */
310 /* Use the GNU Pth threads library. */
315 # if USE_PTH_THREADS_WEAK
317 /* Use weak references to the GNU Pth threads library. */
319 # pragma weak pth_mutex_init
320 # pragma weak pth_mutex_acquire
321 # pragma weak pth_mutex_release
322 # pragma weak pth_rwlock_init
323 # pragma weak pth_rwlock_acquire
324 # pragma weak pth_rwlock_release
326 # pragma weak pth_cancel
327 # define pth_in_use() (pth_cancel != NULL)
331 # define pth_in_use() 1
335 /* -------------------------- gl_lock_t datatype -------------------------- */
337 typedef pth_mutex_t gl_lock_t;
338 # define gl_lock_define(STORAGECLASS, NAME) \
339 STORAGECLASS pth_mutex_t NAME;
340 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
341 STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
342 # define gl_lock_init(NAME) \
343 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
344 # define gl_lock_lock(NAME) \
345 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
346 # define gl_lock_unlock(NAME) \
347 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
348 # define gl_lock_destroy(NAME) \
351 /* ------------------------- gl_rwlock_t datatype ------------------------- */
353 typedef pth_rwlock_t gl_rwlock_t;
354 # define gl_rwlock_define(STORAGECLASS, NAME) \
355 STORAGECLASS pth_rwlock_t NAME;
356 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
357 STORAGECLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
358 # define gl_rwlock_init(NAME) \
359 if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
360 # define gl_rwlock_rdlock(NAME) \
361 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
362 # define gl_rwlock_wrlock(NAME) \
363 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
364 # define gl_rwlock_unlock(NAME) \
365 if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
366 # define gl_rwlock_destroy(NAME) \
369 /* --------------------- gl_recursive_lock_t datatype --------------------- */
371 /* In Pth, mutexes are recursive by default. */
372 typedef pth_mutex_t gl_recursive_lock_t;
373 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
374 STORAGECLASS pth_mutex_t NAME;
375 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
376 STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
377 # define gl_recursive_lock_init(NAME) \
378 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
379 # define gl_recursive_lock_lock(NAME) \
380 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
381 # define gl_recursive_lock_unlock(NAME) \
382 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
383 # define gl_recursive_lock_destroy(NAME) \
388 /* ========================================================================= */
390 #if USE_SOLARIS_THREADS
392 /* Use the old Solaris threads library. */
398 # if USE_SOLARIS_THREADS_WEAK
400 /* Use weak references to the old Solaris threads library. */
402 # pragma weak mutex_init
403 # pragma weak mutex_lock
404 # pragma weak mutex_unlock
405 # pragma weak mutex_destroy
406 # pragma weak rwlock_init
407 # pragma weak rw_rdlock
408 # pragma weak rw_wrlock
409 # pragma weak rw_unlock
410 # pragma weak rwlock_destroy
411 # pragma weak thr_self
413 # pragma weak thr_suspend
414 # define thread_in_use() (thr_suspend != NULL)
418 # define thread_in_use() 1
422 /* -------------------------- gl_lock_t datatype -------------------------- */
424 typedef mutex_t gl_lock_t;
425 # define gl_lock_define(STORAGECLASS, NAME) \
426 STORAGECLASS mutex_t NAME;
427 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
428 STORAGECLASS mutex_t NAME = DEFAULTMUTEX;
429 # define gl_lock_init(NAME) \
430 if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
431 # define gl_lock_lock(NAME) \
432 if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
433 # define gl_lock_unlock(NAME) \
434 if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
435 # define gl_lock_destroy(NAME) \
436 if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
438 /* ------------------------- gl_rwlock_t datatype ------------------------- */
440 typedef rwlock_t gl_rwlock_t;
441 # define gl_rwlock_define(STORAGECLASS, NAME) \
442 STORAGECLASS rwlock_t NAME;
443 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
444 STORAGECLASS rwlock_t NAME = DEFAULTRWLOCK;
445 # define gl_rwlock_init(NAME) \
446 if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
447 # define gl_rwlock_rdlock(NAME) \
448 if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
449 # define gl_rwlock_wrlock(NAME) \
450 if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
451 # define gl_rwlock_unlock(NAME) \
452 if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
453 # define gl_rwlock_destroy(NAME) \
454 if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
456 /* --------------------- gl_recursive_lock_t datatype --------------------- */
458 /* Old Solaris threads did not have recursive locks.
459 We have to implement them ourselves. */
468 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
469 STORAGECLASS gl_recursive_lock_t NAME;
470 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
471 STORAGECLASS gl_recursive_lock_t NAME = { DEFAULTMUTEX, (thread_t) 0, 0 };
472 # define gl_recursive_lock_init(NAME) \
473 if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
474 # define gl_recursive_lock_lock(NAME) \
475 if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
476 # define gl_recursive_lock_unlock(NAME) \
477 if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
478 # define gl_recursive_lock_destroy(NAME) \
479 if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
480 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
481 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
482 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
483 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
487 /* ========================================================================= */
489 #if USE_WIN32_THREADS
491 # include <windows.h>
493 /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
494 Semaphore types, because
495 - we need only to synchronize inside a single process (address space),
496 not inter-process locking,
497 - we don't need to support trylock operations. (TryEnterCriticalSection
498 does not work on Windows 95/98/ME. Packages that need trylock usually
499 define their own mutex type.) */
501 /* There is no way to statically initialize a CRITICAL_SECTION. It needs
502 to be done lazily, once only. For this we need spinlocks. */
504 typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
506 /* -------------------------- gl_lock_t datatype -------------------------- */
510 gl_spinlock_t guard; /* protects the initialization */
511 CRITICAL_SECTION lock;
514 # define gl_lock_define(STORAGECLASS, NAME) \
515 STORAGECLASS gl_lock_t NAME;
516 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
517 STORAGECLASS gl_lock_t NAME = { { 0, -1 } };
518 # define gl_lock_init(NAME) \
519 glthread_lock_init (&NAME)
520 # define gl_lock_lock(NAME) \
521 glthread_lock_lock (&NAME)
522 # define gl_lock_unlock(NAME) \
523 glthread_lock_unlock (&NAME)
524 # define gl_lock_destroy(NAME) \
525 glthread_lock_destroy (&NAME)
526 extern void glthread_lock_init (gl_lock_t *lock);
527 extern void glthread_lock_lock (gl_lock_t *lock);
528 extern void glthread_lock_unlock (gl_lock_t *lock);
529 extern void glthread_lock_destroy (gl_lock_t *lock);
531 /* ------------------------- gl_rwlock_t datatype ------------------------- */
533 /* It is impossible to implement read-write locks using plain locks, without
534 introducing an extra thread dedicated to managing read-write locks.
535 Therefore here we need to use the low-level Event type. */
539 HANDLE *array; /* array of waiting threads, each represented by an event */
540 unsigned int count; /* number of waiting threads */
541 unsigned int alloc; /* length of allocated array */
542 unsigned int offset; /* index of first waiting thread in array */
547 gl_spinlock_t guard; /* protects the initialization */
548 CRITICAL_SECTION lock; /* protects the remaining fields */
549 gl_waitqueue_t waiting_readers; /* waiting readers */
550 gl_waitqueue_t waiting_writers; /* waiting writers */
551 int runcount; /* number of readers running, or -1 when a writer runs */
554 # define gl_rwlock_define(STORAGECLASS, NAME) \
555 STORAGECLASS gl_rwlock_t NAME;
556 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
557 STORAGECLASS gl_rwlock_t NAME = { { 0, -1 } };
558 # define gl_rwlock_init(NAME) \
559 glthread_rwlock_init (&NAME)
560 # define gl_rwlock_rdlock(NAME) \
561 glthread_rwlock_rdlock (&NAME)
562 # define gl_rwlock_wrlock(NAME) \
563 glthread_rwlock_wrlock (&NAME)
564 # define gl_rwlock_unlock(NAME) \
565 glthread_rwlock_unlock (&NAME)
566 # define gl_rwlock_destroy(NAME) \
567 glthread_rwlock_destroy (&NAME)
568 extern void glthread_rwlock_init (gl_rwlock_t *lock);
569 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
570 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
571 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
572 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
574 /* --------------------- gl_recursive_lock_t datatype --------------------- */
576 /* The Win32 documentation says that CRITICAL_SECTION already implements a
577 recursive lock. But we need not rely on it: It's easy to implement a
578 recursive lock without this assumption. */
582 gl_spinlock_t guard; /* protects the initialization */
585 CRITICAL_SECTION lock;
588 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
589 STORAGECLASS gl_recursive_lock_t NAME;
590 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
591 STORAGECLASS gl_recursive_lock_t NAME = { { 0, -1 }, 0, 0 };
592 # define gl_recursive_lock_init(NAME) \
593 glthread_recursive_lock_init (&NAME)
594 # define gl_recursive_lock_lock(NAME) \
595 glthread_recursive_lock_lock (&NAME)
596 # define gl_recursive_lock_unlock(NAME) \
597 glthread_recursive_lock_unlock (&NAME)
598 # define gl_recursive_lock_destroy(NAME) \
599 glthread_recursive_lock_destroy (&NAME)
600 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
601 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
602 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
603 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
607 /* ========================================================================= */
609 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
611 /* Provide dummy implementation if threads are not supported. */
613 /* -------------------------- gl_lock_t datatype -------------------------- */
615 typedef int gl_lock_t;
616 # define gl_lock_define(STORAGECLASS, NAME)
617 # define gl_lock_define_initialized(STORAGECLASS, NAME)
618 # define gl_lock_init(NAME)
619 # define gl_lock_lock(NAME)
620 # define gl_lock_unlock(NAME)
622 /* ------------------------- gl_rwlock_t datatype ------------------------- */
624 typedef int gl_rwlock_t;
625 # define gl_rwlock_define(STORAGECLASS, NAME)
626 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
627 # define gl_rwlock_init(NAME)
628 # define gl_rwlock_rdlock(NAME)
629 # define gl_rwlock_wrlock(NAME)
630 # define gl_rwlock_unlock(NAME)
632 /* --------------------- gl_recursive_lock_t datatype --------------------- */
634 typedef int gl_recursive_lock_t;
635 # define gl_recursive_lock_define(STORAGECLASS, NAME)
636 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
637 # define gl_recursive_lock_init(NAME)
638 # define gl_recursive_lock_lock(NAME)
639 # define gl_recursive_lock_unlock(NAME)