Update Gnulib to the latest git version
[deliverable/binutils-gdb.git] / gnulib / import / glthread / lock.h
1 /* Locking in multithreaded situations.
2 Copyright (C) 2005-2019 Free Software Foundation, Inc.
3
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 3, or (at your option)
7 any later version.
8
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.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
19
20 /* This file contains locking primitives for use with a given thread library.
21 It does not contain primitives for creating threads or for other
22 synchronization primitives.
23
24 Normal (non-recursive) locks:
25 Type: gl_lock_t
26 Declaration: gl_lock_define(extern, name)
27 Initializer: gl_lock_define_initialized(, name)
28 Initialization: gl_lock_init (name);
29 Taking the lock: gl_lock_lock (name);
30 Releasing the lock: gl_lock_unlock (name);
31 De-initialization: gl_lock_destroy (name);
32 Equivalent functions with control of error handling:
33 Initialization: err = glthread_lock_init (&name);
34 Taking the lock: err = glthread_lock_lock (&name);
35 Releasing the lock: err = glthread_lock_unlock (&name);
36 De-initialization: err = glthread_lock_destroy (&name);
37
38 Read-Write (non-recursive) locks:
39 Type: gl_rwlock_t
40 Declaration: gl_rwlock_define(extern, name)
41 Initializer: gl_rwlock_define_initialized(, name)
42 Initialization: gl_rwlock_init (name);
43 Taking the lock: gl_rwlock_rdlock (name);
44 gl_rwlock_wrlock (name);
45 Releasing the lock: gl_rwlock_unlock (name);
46 De-initialization: gl_rwlock_destroy (name);
47 Equivalent functions with control of error handling:
48 Initialization: err = glthread_rwlock_init (&name);
49 Taking the lock: err = glthread_rwlock_rdlock (&name);
50 err = glthread_rwlock_wrlock (&name);
51 Releasing the lock: err = glthread_rwlock_unlock (&name);
52 De-initialization: err = glthread_rwlock_destroy (&name);
53
54 Recursive locks:
55 Type: gl_recursive_lock_t
56 Declaration: gl_recursive_lock_define(extern, name)
57 Initializer: gl_recursive_lock_define_initialized(, name)
58 Initialization: gl_recursive_lock_init (name);
59 Taking the lock: gl_recursive_lock_lock (name);
60 Releasing the lock: gl_recursive_lock_unlock (name);
61 De-initialization: gl_recursive_lock_destroy (name);
62 Equivalent functions with control of error handling:
63 Initialization: err = glthread_recursive_lock_init (&name);
64 Taking the lock: err = glthread_recursive_lock_lock (&name);
65 Releasing the lock: err = glthread_recursive_lock_unlock (&name);
66 De-initialization: err = glthread_recursive_lock_destroy (&name);
67
68 Once-only execution:
69 Type: gl_once_t
70 Initializer: gl_once_define(extern, name)
71 Execution: gl_once (name, initfunction);
72 Equivalent functions with control of error handling:
73 Execution: err = glthread_once (&name, initfunction);
74 */
75
76
77 #ifndef _LOCK_H
78 #define _LOCK_H
79
80 #include <errno.h>
81 #include <stdlib.h>
82
83 #if !defined c11_threads_in_use
84 # if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
85 # include <threads.h>
86 # pragma weak thrd_exit
87 # define c11_threads_in_use() (thrd_exit != NULL)
88 # else
89 # define c11_threads_in_use() 0
90 # endif
91 #endif
92
93 /* ========================================================================= */
94
95 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
96
97 /* Use the ISO C threads library. */
98
99 # include <threads.h>
100
101 # ifdef __cplusplus
102 extern "C" {
103 # endif
104
105 /* -------------------------- gl_lock_t datatype -------------------------- */
106
107 typedef struct
108 {
109 int volatile init_needed;
110 once_flag init_once;
111 void (*init_func) (void);
112 mtx_t mutex;
113 }
114 gl_lock_t;
115 # define gl_lock_define(STORAGECLASS, NAME) \
116 STORAGECLASS gl_lock_t NAME;
117 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
118 static void _atomic_init_##NAME (void); \
119 STORAGECLASS gl_lock_t NAME = \
120 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
121 static void _atomic_init_##NAME (void) \
122 { \
123 if (glthread_lock_init (&(NAME))) \
124 abort (); \
125 }
126 extern int glthread_lock_init (gl_lock_t *lock);
127 extern int glthread_lock_lock (gl_lock_t *lock);
128 extern int glthread_lock_unlock (gl_lock_t *lock);
129 extern int glthread_lock_destroy (gl_lock_t *lock);
130
131 /* ------------------------- gl_rwlock_t datatype ------------------------- */
132
133 typedef struct
134 {
135 int volatile init_needed;
136 once_flag init_once;
137 void (*init_func) (void);
138 mtx_t lock; /* protects the remaining fields */
139 cnd_t waiting_readers; /* waiting readers */
140 cnd_t waiting_writers; /* waiting writers */
141 unsigned int waiting_writers_count; /* number of waiting writers */
142 int runcount; /* number of readers running, or -1 when a writer runs */
143 }
144 gl_rwlock_t;
145 # define gl_rwlock_define(STORAGECLASS, NAME) \
146 STORAGECLASS gl_rwlock_t NAME;
147 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
148 static void _atomic_init_##NAME (void); \
149 STORAGECLASS gl_rwlock_t NAME = \
150 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
151 static void _atomic_init_##NAME (void) \
152 { \
153 if (glthread_rwlock_init (&(NAME))) \
154 abort (); \
155 }
156 extern int glthread_rwlock_init (gl_rwlock_t *lock);
157 extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
158 extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
159 extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
160 extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
161
162 /* --------------------- gl_recursive_lock_t datatype --------------------- */
163
164 typedef struct
165 {
166 int volatile init_needed;
167 once_flag init_once;
168 void (*init_func) (void);
169 mtx_t mutex;
170 }
171 gl_recursive_lock_t;
172 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
173 STORAGECLASS gl_recursive_lock_t NAME;
174 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
175 static void _atomic_init_##NAME (void); \
176 STORAGECLASS gl_recursive_lock_t NAME = \
177 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
178 static void _atomic_init_##NAME (void) \
179 { \
180 if (glthread_recursive_lock_init (&(NAME))) \
181 abort (); \
182 }
183 extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
184 extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
185 extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
186 extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
187
188 /* -------------------------- gl_once_t datatype -------------------------- */
189
190 typedef once_flag gl_once_t;
191 # define gl_once_define(STORAGECLASS, NAME) \
192 STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
193 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
194 (call_once (ONCE_CONTROL, INITFUNCTION), 0)
195
196 # ifdef __cplusplus
197 }
198 # endif
199
200 #endif
201
202 /* ========================================================================= */
203
204 #if USE_POSIX_THREADS
205
206 /* Use the POSIX threads library. */
207
208 # include <pthread.h>
209
210 # ifdef __cplusplus
211 extern "C" {
212 # endif
213
214 # if PTHREAD_IN_USE_DETECTION_HARD
215
216 /* The pthread_in_use() detection needs to be done at runtime. */
217 # define pthread_in_use() \
218 glthread_in_use ()
219 extern int glthread_in_use (void);
220
221 # endif
222
223 # if USE_POSIX_THREADS_WEAK
224
225 /* Use weak references to the POSIX threads library. */
226
227 /* Weak references avoid dragging in external libraries if the other parts
228 of the program don't use them. Here we use them, because we don't want
229 every program that uses libintl to depend on libpthread. This assumes
230 that libpthread would not be loaded after libintl; i.e. if libintl is
231 loaded first, by an executable that does not depend on libpthread, and
232 then a module is dynamically loaded that depends on libpthread, libintl
233 will not be multithread-safe. */
234
235 /* The way to test at runtime whether libpthread is present is to test
236 whether a function pointer's value, such as &pthread_mutex_init, is
237 non-NULL. However, some versions of GCC have a bug through which, in
238 PIC mode, &foo != NULL always evaluates to true if there is a direct
239 call to foo(...) in the same function. To avoid this, we test the
240 address of a function in libpthread that we don't use. */
241
242 # pragma weak pthread_mutex_init
243 # pragma weak pthread_mutex_lock
244 # pragma weak pthread_mutex_unlock
245 # pragma weak pthread_mutex_destroy
246 # pragma weak pthread_rwlock_init
247 # pragma weak pthread_rwlock_rdlock
248 # pragma weak pthread_rwlock_wrlock
249 # pragma weak pthread_rwlock_unlock
250 # pragma weak pthread_rwlock_destroy
251 # pragma weak pthread_once
252 # pragma weak pthread_cond_init
253 # pragma weak pthread_cond_wait
254 # pragma weak pthread_cond_signal
255 # pragma weak pthread_cond_broadcast
256 # pragma weak pthread_cond_destroy
257 # pragma weak pthread_mutexattr_init
258 # pragma weak pthread_mutexattr_settype
259 # pragma weak pthread_mutexattr_destroy
260 # pragma weak pthread_rwlockattr_init
261 # if __GNU_LIBRARY__ > 1
262 # pragma weak pthread_rwlockattr_setkind_np
263 # endif
264 # pragma weak pthread_rwlockattr_destroy
265 # ifndef pthread_self
266 # pragma weak pthread_self
267 # endif
268
269 # if !PTHREAD_IN_USE_DETECTION_HARD
270 /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
271 can be used to determine whether libpthread is in use. These are:
272 pthread_mutexattr_gettype
273 pthread_rwlockattr_destroy
274 pthread_rwlockattr_init
275 */
276 # pragma weak pthread_mutexattr_gettype
277 # define pthread_in_use() \
278 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
279 # endif
280
281 # else
282
283 # if !PTHREAD_IN_USE_DETECTION_HARD
284 # define pthread_in_use() 1
285 # endif
286
287 # endif
288
289 /* -------------------------- gl_lock_t datatype -------------------------- */
290
291 typedef pthread_mutex_t gl_lock_t;
292 # define gl_lock_define(STORAGECLASS, NAME) \
293 STORAGECLASS pthread_mutex_t NAME;
294 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
295 STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
296 # define gl_lock_initializer \
297 PTHREAD_MUTEX_INITIALIZER
298 # define glthread_lock_init(LOCK) \
299 (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
300 # define glthread_lock_lock(LOCK) \
301 (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
302 # define glthread_lock_unlock(LOCK) \
303 (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
304 # define glthread_lock_destroy(LOCK) \
305 (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
306
307 /* ------------------------- gl_rwlock_t datatype ------------------------- */
308
309 # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
310
311 # ifdef PTHREAD_RWLOCK_INITIALIZER
312
313 typedef pthread_rwlock_t gl_rwlock_t;
314 # define gl_rwlock_define(STORAGECLASS, NAME) \
315 STORAGECLASS pthread_rwlock_t NAME;
316 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
317 STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
318 # if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
319 # define gl_rwlock_initializer \
320 PTHREAD_RWLOCK_INITIALIZER
321 # define glthread_rwlock_init(LOCK) \
322 (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
323 # else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
324 # define gl_rwlock_initializer \
325 PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
326 # define glthread_rwlock_init(LOCK) \
327 (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
328 extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
329 # endif
330 # define glthread_rwlock_rdlock(LOCK) \
331 (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
332 # define glthread_rwlock_wrlock(LOCK) \
333 (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
334 # define glthread_rwlock_unlock(LOCK) \
335 (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
336 # define glthread_rwlock_destroy(LOCK) \
337 (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
338
339 # else
340
341 typedef struct
342 {
343 int initialized;
344 pthread_mutex_t guard; /* protects the initialization */
345 pthread_rwlock_t rwlock; /* read-write lock */
346 }
347 gl_rwlock_t;
348 # define gl_rwlock_define(STORAGECLASS, NAME) \
349 STORAGECLASS gl_rwlock_t NAME;
350 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
351 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
352 # define gl_rwlock_initializer \
353 { 0, PTHREAD_MUTEX_INITIALIZER }
354 # define glthread_rwlock_init(LOCK) \
355 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
356 # define glthread_rwlock_rdlock(LOCK) \
357 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
358 # define glthread_rwlock_wrlock(LOCK) \
359 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
360 # define glthread_rwlock_unlock(LOCK) \
361 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
362 # define glthread_rwlock_destroy(LOCK) \
363 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
364 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
365 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
366 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
367 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
368 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
369
370 # endif
371
372 # else
373
374 typedef struct
375 {
376 pthread_mutex_t lock; /* protects the remaining fields */
377 pthread_cond_t waiting_readers; /* waiting readers */
378 pthread_cond_t waiting_writers; /* waiting writers */
379 unsigned int waiting_writers_count; /* number of waiting writers */
380 int runcount; /* number of readers running, or -1 when a writer runs */
381 }
382 gl_rwlock_t;
383 # define gl_rwlock_define(STORAGECLASS, NAME) \
384 STORAGECLASS gl_rwlock_t NAME;
385 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
386 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
387 # define gl_rwlock_initializer \
388 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
389 # define glthread_rwlock_init(LOCK) \
390 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
391 # define glthread_rwlock_rdlock(LOCK) \
392 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
393 # define glthread_rwlock_wrlock(LOCK) \
394 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
395 # define glthread_rwlock_unlock(LOCK) \
396 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
397 # define glthread_rwlock_destroy(LOCK) \
398 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
399 extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
400 extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
401 extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
402 extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
403 extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
404
405 # endif
406
407 /* --------------------- gl_recursive_lock_t datatype --------------------- */
408
409 # if HAVE_PTHREAD_MUTEX_RECURSIVE
410
411 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
412
413 typedef pthread_mutex_t gl_recursive_lock_t;
414 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
415 STORAGECLASS pthread_mutex_t NAME;
416 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
417 STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
418 # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
419 # define gl_recursive_lock_initializer \
420 PTHREAD_RECURSIVE_MUTEX_INITIALIZER
421 # else
422 # define gl_recursive_lock_initializer \
423 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
424 # endif
425 # define glthread_recursive_lock_init(LOCK) \
426 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
427 # define glthread_recursive_lock_lock(LOCK) \
428 (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
429 # define glthread_recursive_lock_unlock(LOCK) \
430 (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
431 # define glthread_recursive_lock_destroy(LOCK) \
432 (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
433 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
434
435 # else
436
437 typedef struct
438 {
439 pthread_mutex_t recmutex; /* recursive mutex */
440 pthread_mutex_t guard; /* protects the initialization */
441 int initialized;
442 }
443 gl_recursive_lock_t;
444 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
445 STORAGECLASS gl_recursive_lock_t NAME;
446 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
447 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
448 # define gl_recursive_lock_initializer \
449 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
450 # define glthread_recursive_lock_init(LOCK) \
451 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
452 # define glthread_recursive_lock_lock(LOCK) \
453 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
454 # define glthread_recursive_lock_unlock(LOCK) \
455 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
456 # define glthread_recursive_lock_destroy(LOCK) \
457 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
458 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
459 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
460 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
461 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
462
463 # endif
464
465 # else
466
467 /* Old versions of POSIX threads on Solaris did not have recursive locks.
468 We have to implement them ourselves. */
469
470 typedef struct
471 {
472 pthread_mutex_t mutex;
473 pthread_t owner;
474 unsigned long depth;
475 }
476 gl_recursive_lock_t;
477 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
478 STORAGECLASS gl_recursive_lock_t NAME;
479 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
480 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
481 # define gl_recursive_lock_initializer \
482 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
483 # define glthread_recursive_lock_init(LOCK) \
484 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
485 # define glthread_recursive_lock_lock(LOCK) \
486 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
487 # define glthread_recursive_lock_unlock(LOCK) \
488 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
489 # define glthread_recursive_lock_destroy(LOCK) \
490 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
491 extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
492 extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
493 extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
494 extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
495
496 # endif
497
498 /* -------------------------- gl_once_t datatype -------------------------- */
499
500 typedef pthread_once_t gl_once_t;
501 # define gl_once_define(STORAGECLASS, NAME) \
502 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
503 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
504 (pthread_in_use () \
505 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
506 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
507 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
508
509 # ifdef __cplusplus
510 }
511 # endif
512
513 #endif
514
515 /* ========================================================================= */
516
517 #if USE_WINDOWS_THREADS
518
519 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
520 # include <windows.h>
521
522 # include "windows-mutex.h"
523 # include "windows-rwlock.h"
524 # include "windows-recmutex.h"
525 # include "windows-once.h"
526
527 # ifdef __cplusplus
528 extern "C" {
529 # endif
530
531 /* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
532 Mutex, Semaphore types, because
533 - we need only to synchronize inside a single process (address space),
534 not inter-process locking,
535 - we don't need to support trylock operations. (TryEnterCriticalSection
536 does not work on Windows 95/98/ME. Packages that need trylock usually
537 define their own mutex type.) */
538
539 /* There is no way to statically initialize a CRITICAL_SECTION. It needs
540 to be done lazily, once only. For this we need spinlocks. */
541
542 /* -------------------------- gl_lock_t datatype -------------------------- */
543
544 typedef glwthread_mutex_t gl_lock_t;
545 # define gl_lock_define(STORAGECLASS, NAME) \
546 STORAGECLASS gl_lock_t NAME;
547 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
548 STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
549 # define gl_lock_initializer \
550 GLWTHREAD_MUTEX_INIT
551 # define glthread_lock_init(LOCK) \
552 (glwthread_mutex_init (LOCK), 0)
553 # define glthread_lock_lock(LOCK) \
554 glwthread_mutex_lock (LOCK)
555 # define glthread_lock_unlock(LOCK) \
556 glwthread_mutex_unlock (LOCK)
557 # define glthread_lock_destroy(LOCK) \
558 glwthread_mutex_destroy (LOCK)
559
560 /* ------------------------- gl_rwlock_t datatype ------------------------- */
561
562 typedef glwthread_rwlock_t gl_rwlock_t;
563 # define gl_rwlock_define(STORAGECLASS, NAME) \
564 STORAGECLASS gl_rwlock_t NAME;
565 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
566 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
567 # define gl_rwlock_initializer \
568 GLWTHREAD_RWLOCK_INIT
569 # define glthread_rwlock_init(LOCK) \
570 (glwthread_rwlock_init (LOCK), 0)
571 # define glthread_rwlock_rdlock(LOCK) \
572 glwthread_rwlock_rdlock (LOCK)
573 # define glthread_rwlock_wrlock(LOCK) \
574 glwthread_rwlock_wrlock (LOCK)
575 # define glthread_rwlock_unlock(LOCK) \
576 glwthread_rwlock_unlock (LOCK)
577 # define glthread_rwlock_destroy(LOCK) \
578 glwthread_rwlock_destroy (LOCK)
579
580 /* --------------------- gl_recursive_lock_t datatype --------------------- */
581
582 typedef glwthread_recmutex_t gl_recursive_lock_t;
583 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
584 STORAGECLASS gl_recursive_lock_t NAME;
585 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
586 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
587 # define gl_recursive_lock_initializer \
588 GLWTHREAD_RECMUTEX_INIT
589 # define glthread_recursive_lock_init(LOCK) \
590 (glwthread_recmutex_init (LOCK), 0)
591 # define glthread_recursive_lock_lock(LOCK) \
592 glwthread_recmutex_lock (LOCK)
593 # define glthread_recursive_lock_unlock(LOCK) \
594 glwthread_recmutex_unlock (LOCK)
595 # define glthread_recursive_lock_destroy(LOCK) \
596 glwthread_recmutex_destroy (LOCK)
597
598 /* -------------------------- gl_once_t datatype -------------------------- */
599
600 typedef glwthread_once_t gl_once_t;
601 # define gl_once_define(STORAGECLASS, NAME) \
602 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
603 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
604 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
605
606 # ifdef __cplusplus
607 }
608 # endif
609
610 #endif
611
612 /* ========================================================================= */
613
614 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
615
616 /* Provide dummy implementation if threads are not supported. */
617
618 /* -------------------------- gl_lock_t datatype -------------------------- */
619
620 typedef int gl_lock_t;
621 # define gl_lock_define(STORAGECLASS, NAME)
622 # define gl_lock_define_initialized(STORAGECLASS, NAME)
623 # define glthread_lock_init(NAME) 0
624 # define glthread_lock_lock(NAME) 0
625 # define glthread_lock_unlock(NAME) 0
626 # define glthread_lock_destroy(NAME) 0
627
628 /* ------------------------- gl_rwlock_t datatype ------------------------- */
629
630 typedef int gl_rwlock_t;
631 # define gl_rwlock_define(STORAGECLASS, NAME)
632 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
633 # define glthread_rwlock_init(NAME) 0
634 # define glthread_rwlock_rdlock(NAME) 0
635 # define glthread_rwlock_wrlock(NAME) 0
636 # define glthread_rwlock_unlock(NAME) 0
637 # define glthread_rwlock_destroy(NAME) 0
638
639 /* --------------------- gl_recursive_lock_t datatype --------------------- */
640
641 typedef int gl_recursive_lock_t;
642 # define gl_recursive_lock_define(STORAGECLASS, NAME)
643 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
644 # define glthread_recursive_lock_init(NAME) 0
645 # define glthread_recursive_lock_lock(NAME) 0
646 # define glthread_recursive_lock_unlock(NAME) 0
647 # define glthread_recursive_lock_destroy(NAME) 0
648
649 /* -------------------------- gl_once_t datatype -------------------------- */
650
651 typedef int gl_once_t;
652 # define gl_once_define(STORAGECLASS, NAME) \
653 STORAGECLASS gl_once_t NAME = 0;
654 # define glthread_once(ONCE_CONTROL, INITFUNCTION) \
655 (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
656
657 #endif
658
659 /* ========================================================================= */
660
661 /* Macros with built-in error handling. */
662
663 /* -------------------------- gl_lock_t datatype -------------------------- */
664
665 #define gl_lock_init(NAME) \
666 do \
667 { \
668 if (glthread_lock_init (&NAME)) \
669 abort (); \
670 } \
671 while (0)
672 #define gl_lock_lock(NAME) \
673 do \
674 { \
675 if (glthread_lock_lock (&NAME)) \
676 abort (); \
677 } \
678 while (0)
679 #define gl_lock_unlock(NAME) \
680 do \
681 { \
682 if (glthread_lock_unlock (&NAME)) \
683 abort (); \
684 } \
685 while (0)
686 #define gl_lock_destroy(NAME) \
687 do \
688 { \
689 if (glthread_lock_destroy (&NAME)) \
690 abort (); \
691 } \
692 while (0)
693
694 /* ------------------------- gl_rwlock_t datatype ------------------------- */
695
696 #define gl_rwlock_init(NAME) \
697 do \
698 { \
699 if (glthread_rwlock_init (&NAME)) \
700 abort (); \
701 } \
702 while (0)
703 #define gl_rwlock_rdlock(NAME) \
704 do \
705 { \
706 if (glthread_rwlock_rdlock (&NAME)) \
707 abort (); \
708 } \
709 while (0)
710 #define gl_rwlock_wrlock(NAME) \
711 do \
712 { \
713 if (glthread_rwlock_wrlock (&NAME)) \
714 abort (); \
715 } \
716 while (0)
717 #define gl_rwlock_unlock(NAME) \
718 do \
719 { \
720 if (glthread_rwlock_unlock (&NAME)) \
721 abort (); \
722 } \
723 while (0)
724 #define gl_rwlock_destroy(NAME) \
725 do \
726 { \
727 if (glthread_rwlock_destroy (&NAME)) \
728 abort (); \
729 } \
730 while (0)
731
732 /* --------------------- gl_recursive_lock_t datatype --------------------- */
733
734 #define gl_recursive_lock_init(NAME) \
735 do \
736 { \
737 if (glthread_recursive_lock_init (&NAME)) \
738 abort (); \
739 } \
740 while (0)
741 #define gl_recursive_lock_lock(NAME) \
742 do \
743 { \
744 if (glthread_recursive_lock_lock (&NAME)) \
745 abort (); \
746 } \
747 while (0)
748 #define gl_recursive_lock_unlock(NAME) \
749 do \
750 { \
751 if (glthread_recursive_lock_unlock (&NAME)) \
752 abort (); \
753 } \
754 while (0)
755 #define gl_recursive_lock_destroy(NAME) \
756 do \
757 { \
758 if (glthread_recursive_lock_destroy (&NAME)) \
759 abort (); \
760 } \
761 while (0)
762
763 /* -------------------------- gl_once_t datatype -------------------------- */
764
765 #define gl_once(NAME, INITFUNCTION) \
766 do \
767 { \
768 if (glthread_once (&NAME, INITFUNCTION)) \
769 abort (); \
770 } \
771 while (0)
772
773 /* ========================================================================= */
774
775 #endif /* _LOCK_H */
This page took 0.045601 seconds and 4 git commands to generate.