gnulib: update to 776af40e0
[deliverable/binutils-gdb.git] / gnulib / import / glthread / lock.h
CommitLineData
5abebf3c 1/* Locking in multithreaded situations.
9c9d63b1 2 Copyright (C) 2005-2021 Free Software Foundation, Inc.
5abebf3c
CB
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
c0c3707f 15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
5abebf3c
CB
16
17/* Written by Bruno Haible <bruno@clisp.org>, 2005.
c0c3707f 18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
5abebf3c
CB
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
c0c3707f
CB
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
102extern "C" {
103# endif
104
105/* -------------------------- gl_lock_t datatype -------------------------- */
106
107typedef 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 }
126extern int glthread_lock_init (gl_lock_t *lock);
127extern int glthread_lock_lock (gl_lock_t *lock);
128extern int glthread_lock_unlock (gl_lock_t *lock);
129extern int glthread_lock_destroy (gl_lock_t *lock);
130
131/* ------------------------- gl_rwlock_t datatype ------------------------- */
132
133typedef 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 }
156extern int glthread_rwlock_init (gl_rwlock_t *lock);
157extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
158extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
159extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
160extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
161
162/* --------------------- gl_recursive_lock_t datatype --------------------- */
163
164typedef 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 }
183extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
184extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
185extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
186extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
187
188/* -------------------------- gl_once_t datatype -------------------------- */
189
190typedef 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
5abebf3c
CB
202/* ========================================================================= */
203
204#if USE_POSIX_THREADS
205
206/* Use the POSIX threads library. */
207
208# include <pthread.h>
209
210# ifdef __cplusplus
211extern "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 ()
219extern 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
c0c3707f
CB
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
5abebf3c
CB
265# ifndef pthread_self
266# pragma weak pthread_self
267# endif
268
269# if !PTHREAD_IN_USE_DETECTION_HARD
c0c3707f
CB
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 ())
5abebf3c
CB
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
291typedef 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
c0c3707f 309# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
5abebf3c 310
5df4cba6 311# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
5abebf3c
CB
312
313typedef 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;
c0c3707f 318# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
5df4cba6
SM
319# if defined PTHREAD_RWLOCK_INITIALIZER
320# define gl_rwlock_initializer \
321 PTHREAD_RWLOCK_INITIALIZER
322# else
323# define gl_rwlock_initializer \
324 PTHREAD_RWLOCK_INITIALIZER_NP
325# endif
c0c3707f
CB
326# define glthread_rwlock_init(LOCK) \
327 (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
328# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
329# define gl_rwlock_initializer \
330 PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
331# define glthread_rwlock_init(LOCK) \
332 (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
333extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
334# endif
5abebf3c
CB
335# define glthread_rwlock_rdlock(LOCK) \
336 (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
337# define glthread_rwlock_wrlock(LOCK) \
338 (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
339# define glthread_rwlock_unlock(LOCK) \
340 (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
341# define glthread_rwlock_destroy(LOCK) \
342 (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
343
344# else
345
346typedef struct
347 {
348 int initialized;
349 pthread_mutex_t guard; /* protects the initialization */
350 pthread_rwlock_t rwlock; /* read-write lock */
351 }
352 gl_rwlock_t;
353# define gl_rwlock_define(STORAGECLASS, NAME) \
354 STORAGECLASS gl_rwlock_t NAME;
355# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
356 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
357# define gl_rwlock_initializer \
358 { 0, PTHREAD_MUTEX_INITIALIZER }
359# define glthread_rwlock_init(LOCK) \
360 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
361# define glthread_rwlock_rdlock(LOCK) \
362 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
363# define glthread_rwlock_wrlock(LOCK) \
364 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
365# define glthread_rwlock_unlock(LOCK) \
366 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
367# define glthread_rwlock_destroy(LOCK) \
368 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
369extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
370extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
371extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
372extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
373extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
374
375# endif
376
377# else
378
379typedef struct
380 {
381 pthread_mutex_t lock; /* protects the remaining fields */
382 pthread_cond_t waiting_readers; /* waiting readers */
383 pthread_cond_t waiting_writers; /* waiting writers */
384 unsigned int waiting_writers_count; /* number of waiting writers */
385 int runcount; /* number of readers running, or -1 when a writer runs */
386 }
387 gl_rwlock_t;
388# define gl_rwlock_define(STORAGECLASS, NAME) \
389 STORAGECLASS gl_rwlock_t NAME;
390# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
391 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
392# define gl_rwlock_initializer \
393 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
394# define glthread_rwlock_init(LOCK) \
395 (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
396# define glthread_rwlock_rdlock(LOCK) \
397 (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
398# define glthread_rwlock_wrlock(LOCK) \
399 (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
400# define glthread_rwlock_unlock(LOCK) \
401 (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
402# define glthread_rwlock_destroy(LOCK) \
403 (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
404extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
405extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
406extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
407extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
408extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
409
410# endif
411
412/* --------------------- gl_recursive_lock_t datatype --------------------- */
413
414# if HAVE_PTHREAD_MUTEX_RECURSIVE
415
416# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
417
418typedef pthread_mutex_t gl_recursive_lock_t;
419# define gl_recursive_lock_define(STORAGECLASS, NAME) \
420 STORAGECLASS pthread_mutex_t NAME;
421# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
422 STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
423# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
424# define gl_recursive_lock_initializer \
425 PTHREAD_RECURSIVE_MUTEX_INITIALIZER
426# else
427# define gl_recursive_lock_initializer \
428 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
429# endif
430# define glthread_recursive_lock_init(LOCK) \
431 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
432# define glthread_recursive_lock_lock(LOCK) \
433 (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
434# define glthread_recursive_lock_unlock(LOCK) \
435 (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
436# define glthread_recursive_lock_destroy(LOCK) \
437 (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
438extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
439
440# else
441
442typedef struct
443 {
444 pthread_mutex_t recmutex; /* recursive mutex */
445 pthread_mutex_t guard; /* protects the initialization */
446 int initialized;
447 }
448 gl_recursive_lock_t;
449# define gl_recursive_lock_define(STORAGECLASS, NAME) \
450 STORAGECLASS gl_recursive_lock_t NAME;
451# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
452 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
453# define gl_recursive_lock_initializer \
454 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
455# define glthread_recursive_lock_init(LOCK) \
456 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
457# define glthread_recursive_lock_lock(LOCK) \
458 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
459# define glthread_recursive_lock_unlock(LOCK) \
460 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
461# define glthread_recursive_lock_destroy(LOCK) \
462 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
463extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
464extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
465extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
466extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
467
468# endif
469
470# else
471
472/* Old versions of POSIX threads on Solaris did not have recursive locks.
473 We have to implement them ourselves. */
474
475typedef struct
476 {
477 pthread_mutex_t mutex;
478 pthread_t owner;
479 unsigned long depth;
480 }
481 gl_recursive_lock_t;
482# define gl_recursive_lock_define(STORAGECLASS, NAME) \
483 STORAGECLASS gl_recursive_lock_t NAME;
484# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
485 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
486# define gl_recursive_lock_initializer \
487 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
488# define glthread_recursive_lock_init(LOCK) \
489 (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
490# define glthread_recursive_lock_lock(LOCK) \
491 (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
492# define glthread_recursive_lock_unlock(LOCK) \
493 (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
494# define glthread_recursive_lock_destroy(LOCK) \
495 (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
496extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
497extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
498extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
499extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
500
501# endif
502
503/* -------------------------- gl_once_t datatype -------------------------- */
504
505typedef pthread_once_t gl_once_t;
506# define gl_once_define(STORAGECLASS, NAME) \
507 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
5df4cba6
SM
508# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
509# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
510 (pthread_in_use () \
511 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
512 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
513# else
514# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
515 (pthread_in_use () \
516 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
517 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
518extern int glthread_once_multithreaded (pthread_once_t *once_control,
519 void (*init_function) (void));
520# endif
5abebf3c
CB
521extern int glthread_once_singlethreaded (pthread_once_t *once_control);
522
523# ifdef __cplusplus
524}
525# endif
526
527#endif
528
529/* ========================================================================= */
530
5abebf3c
CB
531#if USE_WINDOWS_THREADS
532
533# define WIN32_LEAN_AND_MEAN /* avoid including junk */
534# include <windows.h>
535
c0c3707f
CB
536# include "windows-mutex.h"
537# include "windows-rwlock.h"
538# include "windows-recmutex.h"
539# include "windows-once.h"
540
5abebf3c
CB
541# ifdef __cplusplus
542extern "C" {
543# endif
544
545/* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
546 Mutex, Semaphore types, because
547 - we need only to synchronize inside a single process (address space),
548 not inter-process locking,
549 - we don't need to support trylock operations. (TryEnterCriticalSection
550 does not work on Windows 95/98/ME. Packages that need trylock usually
551 define their own mutex type.) */
552
553/* There is no way to statically initialize a CRITICAL_SECTION. It needs
554 to be done lazily, once only. For this we need spinlocks. */
555
5abebf3c
CB
556/* -------------------------- gl_lock_t datatype -------------------------- */
557
c0c3707f 558typedef glwthread_mutex_t gl_lock_t;
5abebf3c
CB
559# define gl_lock_define(STORAGECLASS, NAME) \
560 STORAGECLASS gl_lock_t NAME;
561# define gl_lock_define_initialized(STORAGECLASS, NAME) \
562 STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
563# define gl_lock_initializer \
c0c3707f 564 GLWTHREAD_MUTEX_INIT
5abebf3c 565# define glthread_lock_init(LOCK) \
c0c3707f 566 (glwthread_mutex_init (LOCK), 0)
5abebf3c 567# define glthread_lock_lock(LOCK) \
c0c3707f 568 glwthread_mutex_lock (LOCK)
5abebf3c 569# define glthread_lock_unlock(LOCK) \
c0c3707f 570 glwthread_mutex_unlock (LOCK)
5abebf3c 571# define glthread_lock_destroy(LOCK) \
c0c3707f 572 glwthread_mutex_destroy (LOCK)
5abebf3c
CB
573
574/* ------------------------- gl_rwlock_t datatype ------------------------- */
575
c0c3707f 576typedef glwthread_rwlock_t gl_rwlock_t;
5abebf3c
CB
577# define gl_rwlock_define(STORAGECLASS, NAME) \
578 STORAGECLASS gl_rwlock_t NAME;
579# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
580 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
581# define gl_rwlock_initializer \
c0c3707f 582 GLWTHREAD_RWLOCK_INIT
5abebf3c 583# define glthread_rwlock_init(LOCK) \
c0c3707f 584 (glwthread_rwlock_init (LOCK), 0)
5abebf3c 585# define glthread_rwlock_rdlock(LOCK) \
c0c3707f 586 glwthread_rwlock_rdlock (LOCK)
5abebf3c 587# define glthread_rwlock_wrlock(LOCK) \
c0c3707f 588 glwthread_rwlock_wrlock (LOCK)
5abebf3c 589# define glthread_rwlock_unlock(LOCK) \
c0c3707f 590 glwthread_rwlock_unlock (LOCK)
5abebf3c 591# define glthread_rwlock_destroy(LOCK) \
c0c3707f 592 glwthread_rwlock_destroy (LOCK)
5abebf3c
CB
593
594/* --------------------- gl_recursive_lock_t datatype --------------------- */
595
c0c3707f 596typedef glwthread_recmutex_t gl_recursive_lock_t;
5abebf3c
CB
597# define gl_recursive_lock_define(STORAGECLASS, NAME) \
598 STORAGECLASS gl_recursive_lock_t NAME;
599# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
600 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
601# define gl_recursive_lock_initializer \
c0c3707f 602 GLWTHREAD_RECMUTEX_INIT
5abebf3c 603# define glthread_recursive_lock_init(LOCK) \
c0c3707f 604 (glwthread_recmutex_init (LOCK), 0)
5abebf3c 605# define glthread_recursive_lock_lock(LOCK) \
c0c3707f 606 glwthread_recmutex_lock (LOCK)
5abebf3c 607# define glthread_recursive_lock_unlock(LOCK) \
c0c3707f 608 glwthread_recmutex_unlock (LOCK)
5abebf3c 609# define glthread_recursive_lock_destroy(LOCK) \
c0c3707f 610 glwthread_recmutex_destroy (LOCK)
5abebf3c
CB
611
612/* -------------------------- gl_once_t datatype -------------------------- */
613
c0c3707f 614typedef glwthread_once_t gl_once_t;
5abebf3c 615# define gl_once_define(STORAGECLASS, NAME) \
c0c3707f 616 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
5abebf3c 617# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
c0c3707f 618 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
5abebf3c
CB
619
620# ifdef __cplusplus
621}
622# endif
623
624#endif
625
626/* ========================================================================= */
627
c0c3707f 628#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
5abebf3c
CB
629
630/* Provide dummy implementation if threads are not supported. */
631
632/* -------------------------- gl_lock_t datatype -------------------------- */
633
634typedef int gl_lock_t;
635# define gl_lock_define(STORAGECLASS, NAME)
636# define gl_lock_define_initialized(STORAGECLASS, NAME)
637# define glthread_lock_init(NAME) 0
638# define glthread_lock_lock(NAME) 0
639# define glthread_lock_unlock(NAME) 0
640# define glthread_lock_destroy(NAME) 0
641
642/* ------------------------- gl_rwlock_t datatype ------------------------- */
643
644typedef int gl_rwlock_t;
645# define gl_rwlock_define(STORAGECLASS, NAME)
646# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
647# define glthread_rwlock_init(NAME) 0
648# define glthread_rwlock_rdlock(NAME) 0
649# define glthread_rwlock_wrlock(NAME) 0
650# define glthread_rwlock_unlock(NAME) 0
651# define glthread_rwlock_destroy(NAME) 0
652
653/* --------------------- gl_recursive_lock_t datatype --------------------- */
654
655typedef int gl_recursive_lock_t;
656# define gl_recursive_lock_define(STORAGECLASS, NAME)
657# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
658# define glthread_recursive_lock_init(NAME) 0
659# define glthread_recursive_lock_lock(NAME) 0
660# define glthread_recursive_lock_unlock(NAME) 0
661# define glthread_recursive_lock_destroy(NAME) 0
662
663/* -------------------------- gl_once_t datatype -------------------------- */
664
665typedef int gl_once_t;
666# define gl_once_define(STORAGECLASS, NAME) \
667 STORAGECLASS gl_once_t NAME = 0;
668# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
669 (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
670
671#endif
672
673/* ========================================================================= */
674
675/* Macros with built-in error handling. */
676
677/* -------------------------- gl_lock_t datatype -------------------------- */
678
679#define gl_lock_init(NAME) \
680 do \
681 { \
682 if (glthread_lock_init (&NAME)) \
683 abort (); \
684 } \
685 while (0)
686#define gl_lock_lock(NAME) \
687 do \
688 { \
689 if (glthread_lock_lock (&NAME)) \
690 abort (); \
691 } \
692 while (0)
693#define gl_lock_unlock(NAME) \
694 do \
695 { \
696 if (glthread_lock_unlock (&NAME)) \
697 abort (); \
698 } \
699 while (0)
700#define gl_lock_destroy(NAME) \
701 do \
702 { \
703 if (glthread_lock_destroy (&NAME)) \
704 abort (); \
705 } \
706 while (0)
707
708/* ------------------------- gl_rwlock_t datatype ------------------------- */
709
710#define gl_rwlock_init(NAME) \
711 do \
712 { \
713 if (glthread_rwlock_init (&NAME)) \
714 abort (); \
715 } \
716 while (0)
717#define gl_rwlock_rdlock(NAME) \
718 do \
719 { \
720 if (glthread_rwlock_rdlock (&NAME)) \
721 abort (); \
722 } \
723 while (0)
724#define gl_rwlock_wrlock(NAME) \
725 do \
726 { \
727 if (glthread_rwlock_wrlock (&NAME)) \
728 abort (); \
729 } \
730 while (0)
731#define gl_rwlock_unlock(NAME) \
732 do \
733 { \
734 if (glthread_rwlock_unlock (&NAME)) \
735 abort (); \
736 } \
737 while (0)
738#define gl_rwlock_destroy(NAME) \
739 do \
740 { \
741 if (glthread_rwlock_destroy (&NAME)) \
742 abort (); \
743 } \
744 while (0)
745
746/* --------------------- gl_recursive_lock_t datatype --------------------- */
747
748#define gl_recursive_lock_init(NAME) \
749 do \
750 { \
751 if (glthread_recursive_lock_init (&NAME)) \
752 abort (); \
753 } \
754 while (0)
755#define gl_recursive_lock_lock(NAME) \
756 do \
757 { \
758 if (glthread_recursive_lock_lock (&NAME)) \
759 abort (); \
760 } \
761 while (0)
762#define gl_recursive_lock_unlock(NAME) \
763 do \
764 { \
765 if (glthread_recursive_lock_unlock (&NAME)) \
766 abort (); \
767 } \
768 while (0)
769#define gl_recursive_lock_destroy(NAME) \
770 do \
771 { \
772 if (glthread_recursive_lock_destroy (&NAME)) \
773 abort (); \
774 } \
775 while (0)
776
777/* -------------------------- gl_once_t datatype -------------------------- */
778
779#define gl_once(NAME, INITFUNCTION) \
780 do \
781 { \
782 if (glthread_once (&NAME, INITFUNCTION)) \
783 abort (); \
784 } \
785 while (0)
786
787/* ========================================================================= */
788
789#endif /* _LOCK_H */
This page took 0.112602 seconds and 4 git commands to generate.