summaryrefslogtreecommitdiffstats
path: root/gl/glthread/lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'gl/glthread/lock.h')
-rw-r--r--gl/glthread/lock.h544
1 files changed, 204 insertions, 340 deletions
diff --git a/gl/glthread/lock.h b/gl/glthread/lock.h
index d20bbdef..ae3ee2d6 100644
--- a/gl/glthread/lock.h
+++ b/gl/glthread/lock.h
@@ -1,22 +1,21 @@
1/* Locking in multithreaded situations. 1/* Locking in multithreaded situations.
2 Copyright (C) 2005-2013 Free Software Foundation, Inc. 2 Copyright (C) 2005-2023 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU Lesser General Public License as
6 the Free Software Foundation; either version 3, or (at your option) 6 published by the Free Software Foundation; either version 2.1 of the
7 any later version. 7 License, or (at your option) any later version.
8 8
9 This program is distributed in the hope that it will be useful, 9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details. 12 GNU Lesser General Public License for more details.
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>. */ 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16 16
17/* Written by Bruno Haible <bruno@clisp.org>, 2005. 17/* Written by Bruno Haible <bruno@clisp.org>, 2005.
18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, 18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
19 gthr-win32.h. */
20 19
21/* This file contains locking primitives for use with a given thread library. 20/* This file contains locking primitives for use with a given thread library.
22 It does not contain primitives for creating threads or for other 21 It does not contain primitives for creating threads or for other
@@ -81,6 +80,127 @@
81#include <errno.h> 80#include <errno.h>
82#include <stdlib.h> 81#include <stdlib.h>
83 82
83#if !defined c11_threads_in_use
84# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
85# define c11_threads_in_use() 1
86# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
87# include <threads.h>
88# pragma weak thrd_exit
89# define c11_threads_in_use() (thrd_exit != NULL)
90# else
91# define c11_threads_in_use() 0
92# endif
93#endif
94
95/* ========================================================================= */
96
97#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
98
99/* Use the ISO C threads library. */
100
101# include <threads.h>
102
103# ifdef __cplusplus
104extern "C" {
105# endif
106
107/* -------------------------- gl_lock_t datatype -------------------------- */
108
109typedef struct
110 {
111 int volatile init_needed;
112 once_flag init_once;
113 void (*init_func) (void);
114 mtx_t mutex;
115 }
116 gl_lock_t;
117# define gl_lock_define(STORAGECLASS, NAME) \
118 STORAGECLASS gl_lock_t NAME;
119# define gl_lock_define_initialized(STORAGECLASS, NAME) \
120 static void _atomic_init_##NAME (void); \
121 STORAGECLASS gl_lock_t NAME = \
122 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
123 static void _atomic_init_##NAME (void) \
124 { \
125 if (glthread_lock_init (&(NAME))) \
126 abort (); \
127 }
128extern int glthread_lock_init (gl_lock_t *lock);
129extern int glthread_lock_lock (gl_lock_t *lock);
130extern int glthread_lock_unlock (gl_lock_t *lock);
131extern int glthread_lock_destroy (gl_lock_t *lock);
132
133/* ------------------------- gl_rwlock_t datatype ------------------------- */
134
135typedef struct
136 {
137 int volatile init_needed;
138 once_flag init_once;
139 void (*init_func) (void);
140 mtx_t lock; /* protects the remaining fields */
141 cnd_t waiting_readers; /* waiting readers */
142 cnd_t waiting_writers; /* waiting writers */
143 unsigned int waiting_writers_count; /* number of waiting writers */
144 int runcount; /* number of readers running, or -1 when a writer runs */
145 }
146 gl_rwlock_t;
147# define gl_rwlock_define(STORAGECLASS, NAME) \
148 STORAGECLASS gl_rwlock_t NAME;
149# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
150 static void _atomic_init_##NAME (void); \
151 STORAGECLASS gl_rwlock_t NAME = \
152 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
153 static void _atomic_init_##NAME (void) \
154 { \
155 if (glthread_rwlock_init (&(NAME))) \
156 abort (); \
157 }
158extern int glthread_rwlock_init (gl_rwlock_t *lock);
159extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
160extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
161extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
162extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
163
164/* --------------------- gl_recursive_lock_t datatype --------------------- */
165
166typedef struct
167 {
168 int volatile init_needed;
169 once_flag init_once;
170 void (*init_func) (void);
171 mtx_t mutex;
172 }
173 gl_recursive_lock_t;
174# define gl_recursive_lock_define(STORAGECLASS, NAME) \
175 STORAGECLASS gl_recursive_lock_t NAME;
176# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
177 static void _atomic_init_##NAME (void); \
178 STORAGECLASS gl_recursive_lock_t NAME = \
179 { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
180 static void _atomic_init_##NAME (void) \
181 { \
182 if (glthread_recursive_lock_init (&(NAME))) \
183 abort (); \
184 }
185extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
186extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
187extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
188extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
189
190/* -------------------------- gl_once_t datatype -------------------------- */
191
192typedef once_flag gl_once_t;
193# define gl_once_define(STORAGECLASS, NAME) \
194 STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
195# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
196 (call_once (ONCE_CONTROL, INITFUNCTION), 0)
197
198# ifdef __cplusplus
199}
200# endif
201
202#endif
203
84/* ========================================================================= */ 204/* ========================================================================= */
85 205
86#if USE_POSIX_THREADS 206#if USE_POSIX_THREADS
@@ -139,13 +259,25 @@ extern int glthread_in_use (void);
139# pragma weak pthread_mutexattr_init 259# pragma weak pthread_mutexattr_init
140# pragma weak pthread_mutexattr_settype 260# pragma weak pthread_mutexattr_settype
141# pragma weak pthread_mutexattr_destroy 261# pragma weak pthread_mutexattr_destroy
262# pragma weak pthread_rwlockattr_init
263# if __GNU_LIBRARY__ > 1
264# pragma weak pthread_rwlockattr_setkind_np
265# endif
266# pragma weak pthread_rwlockattr_destroy
142# ifndef pthread_self 267# ifndef pthread_self
143# pragma weak pthread_self 268# pragma weak pthread_self
144# endif 269# endif
145 270
146# if !PTHREAD_IN_USE_DETECTION_HARD 271# if !PTHREAD_IN_USE_DETECTION_HARD
147# pragma weak pthread_cancel 272 /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
148# define pthread_in_use() (pthread_cancel != NULL) 273 can be used to determine whether libpthread is in use. These are:
274 pthread_mutexattr_gettype
275 pthread_rwlockattr_destroy
276 pthread_rwlockattr_init
277 */
278# pragma weak pthread_mutexattr_gettype
279# define pthread_in_use() \
280 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
149# endif 281# endif
150 282
151# else 283# else
@@ -176,19 +308,32 @@ typedef pthread_mutex_t gl_lock_t;
176 308
177/* ------------------------- gl_rwlock_t datatype ------------------------- */ 309/* ------------------------- gl_rwlock_t datatype ------------------------- */
178 310
179# if HAVE_PTHREAD_RWLOCK 311# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
180 312
181# ifdef PTHREAD_RWLOCK_INITIALIZER 313# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
182 314
183typedef pthread_rwlock_t gl_rwlock_t; 315typedef pthread_rwlock_t gl_rwlock_t;
184# define gl_rwlock_define(STORAGECLASS, NAME) \ 316# define gl_rwlock_define(STORAGECLASS, NAME) \
185 STORAGECLASS pthread_rwlock_t NAME; 317 STORAGECLASS pthread_rwlock_t NAME;
186# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 318# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
187 STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; 319 STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
188# define gl_rwlock_initializer \ 320# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
189 PTHREAD_RWLOCK_INITIALIZER 321# if defined PTHREAD_RWLOCK_INITIALIZER
190# define glthread_rwlock_init(LOCK) \ 322# define gl_rwlock_initializer \
191 (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) 323 PTHREAD_RWLOCK_INITIALIZER
324# else
325# define gl_rwlock_initializer \
326 PTHREAD_RWLOCK_INITIALIZER_NP
327# endif
328# define glthread_rwlock_init(LOCK) \
329 (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
330# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
331# define gl_rwlock_initializer \
332 PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
333# define glthread_rwlock_init(LOCK) \
334 (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
335extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
336# endif
192# define glthread_rwlock_rdlock(LOCK) \ 337# define glthread_rwlock_rdlock(LOCK) \
193 (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) 338 (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
194# define glthread_rwlock_wrlock(LOCK) \ 339# define glthread_rwlock_wrlock(LOCK) \
@@ -362,248 +507,20 @@ extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *l
362typedef pthread_once_t gl_once_t; 507typedef pthread_once_t gl_once_t;
363# define gl_once_define(STORAGECLASS, NAME) \ 508# define gl_once_define(STORAGECLASS, NAME) \
364 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; 509 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
365# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 510# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
366 (pthread_in_use () \ 511# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
367 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ 512 (pthread_in_use () \
368 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) 513 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
369extern int glthread_once_singlethreaded (pthread_once_t *once_control); 514 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
370
371# ifdef __cplusplus
372}
373# endif
374
375#endif
376
377/* ========================================================================= */
378
379#if USE_PTH_THREADS
380
381/* Use the GNU Pth threads library. */
382
383# include <pth.h>
384
385# ifdef __cplusplus
386extern "C" {
387# endif
388
389# if USE_PTH_THREADS_WEAK
390
391/* Use weak references to the GNU Pth threads library. */
392
393# pragma weak pth_mutex_init
394# pragma weak pth_mutex_acquire
395# pragma weak pth_mutex_release
396# pragma weak pth_rwlock_init
397# pragma weak pth_rwlock_acquire
398# pragma weak pth_rwlock_release
399# pragma weak pth_once
400
401# pragma weak pth_cancel
402# define pth_in_use() (pth_cancel != NULL)
403
404# else 515# else
405 516# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
406# define pth_in_use() 1 517 (pthread_in_use () \
407 518 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
519 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
520extern int glthread_once_multithreaded (pthread_once_t *once_control,
521 void (*init_function) (void));
408# endif 522# endif
409 523extern int glthread_once_singlethreaded (pthread_once_t *once_control);
410/* -------------------------- gl_lock_t datatype -------------------------- */
411
412typedef pth_mutex_t gl_lock_t;
413# define gl_lock_define(STORAGECLASS, NAME) \
414 STORAGECLASS pth_mutex_t NAME;
415# define gl_lock_define_initialized(STORAGECLASS, NAME) \
416 STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
417# define gl_lock_initializer \
418 PTH_MUTEX_INIT
419# define glthread_lock_init(LOCK) \
420 (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
421# define glthread_lock_lock(LOCK) \
422 (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
423# define glthread_lock_unlock(LOCK) \
424 (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
425# define glthread_lock_destroy(LOCK) \
426 ((void)(LOCK), 0)
427
428/* ------------------------- gl_rwlock_t datatype ------------------------- */
429
430typedef pth_rwlock_t gl_rwlock_t;
431# define gl_rwlock_define(STORAGECLASS, NAME) \
432 STORAGECLASS pth_rwlock_t NAME;
433# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
434 STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
435# define gl_rwlock_initializer \
436 PTH_RWLOCK_INIT
437# define glthread_rwlock_init(LOCK) \
438 (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
439# define glthread_rwlock_rdlock(LOCK) \
440 (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
441# define glthread_rwlock_wrlock(LOCK) \
442 (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
443# define glthread_rwlock_unlock(LOCK) \
444 (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
445# define glthread_rwlock_destroy(LOCK) \
446 ((void)(LOCK), 0)
447
448/* --------------------- gl_recursive_lock_t datatype --------------------- */
449
450/* In Pth, mutexes are recursive by default. */
451typedef pth_mutex_t gl_recursive_lock_t;
452# define gl_recursive_lock_define(STORAGECLASS, NAME) \
453 STORAGECLASS pth_mutex_t NAME;
454# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
455 STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
456# define gl_recursive_lock_initializer \
457 PTH_MUTEX_INIT
458# define glthread_recursive_lock_init(LOCK) \
459 (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
460# define glthread_recursive_lock_lock(LOCK) \
461 (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
462# define glthread_recursive_lock_unlock(LOCK) \
463 (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
464# define glthread_recursive_lock_destroy(LOCK) \
465 ((void)(LOCK), 0)
466
467/* -------------------------- gl_once_t datatype -------------------------- */
468
469typedef pth_once_t gl_once_t;
470# define gl_once_define(STORAGECLASS, NAME) \
471 STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
472# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
473 (pth_in_use () \
474 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
475 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
476extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
477extern int glthread_once_singlethreaded (pth_once_t *once_control);
478
479# ifdef __cplusplus
480}
481# endif
482
483#endif
484
485/* ========================================================================= */
486
487#if USE_SOLARIS_THREADS
488
489/* Use the old Solaris threads library. */
490
491# include <thread.h>
492# include <synch.h>
493
494# ifdef __cplusplus
495extern "C" {
496# endif
497
498# if USE_SOLARIS_THREADS_WEAK
499
500/* Use weak references to the old Solaris threads library. */
501
502# pragma weak mutex_init
503# pragma weak mutex_lock
504# pragma weak mutex_unlock
505# pragma weak mutex_destroy
506# pragma weak rwlock_init
507# pragma weak rw_rdlock
508# pragma weak rw_wrlock
509# pragma weak rw_unlock
510# pragma weak rwlock_destroy
511# pragma weak thr_self
512
513# pragma weak thr_suspend
514# define thread_in_use() (thr_suspend != NULL)
515
516# else
517
518# define thread_in_use() 1
519
520# endif
521
522/* -------------------------- gl_lock_t datatype -------------------------- */
523
524typedef mutex_t gl_lock_t;
525# define gl_lock_define(STORAGECLASS, NAME) \
526 STORAGECLASS mutex_t NAME;
527# define gl_lock_define_initialized(STORAGECLASS, NAME) \
528 STORAGECLASS mutex_t NAME = gl_lock_initializer;
529# define gl_lock_initializer \
530 DEFAULTMUTEX
531# define glthread_lock_init(LOCK) \
532 (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
533# define glthread_lock_lock(LOCK) \
534 (thread_in_use () ? mutex_lock (LOCK) : 0)
535# define glthread_lock_unlock(LOCK) \
536 (thread_in_use () ? mutex_unlock (LOCK) : 0)
537# define glthread_lock_destroy(LOCK) \
538 (thread_in_use () ? mutex_destroy (LOCK) : 0)
539
540/* ------------------------- gl_rwlock_t datatype ------------------------- */
541
542typedef rwlock_t gl_rwlock_t;
543# define gl_rwlock_define(STORAGECLASS, NAME) \
544 STORAGECLASS rwlock_t NAME;
545# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
546 STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
547# define gl_rwlock_initializer \
548 DEFAULTRWLOCK
549# define glthread_rwlock_init(LOCK) \
550 (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
551# define glthread_rwlock_rdlock(LOCK) \
552 (thread_in_use () ? rw_rdlock (LOCK) : 0)
553# define glthread_rwlock_wrlock(LOCK) \
554 (thread_in_use () ? rw_wrlock (LOCK) : 0)
555# define glthread_rwlock_unlock(LOCK) \
556 (thread_in_use () ? rw_unlock (LOCK) : 0)
557# define glthread_rwlock_destroy(LOCK) \
558 (thread_in_use () ? rwlock_destroy (LOCK) : 0)
559
560/* --------------------- gl_recursive_lock_t datatype --------------------- */
561
562/* Old Solaris threads did not have recursive locks.
563 We have to implement them ourselves. */
564
565typedef struct
566 {
567 mutex_t mutex;
568 thread_t owner;
569 unsigned long depth;
570 }
571 gl_recursive_lock_t;
572# define gl_recursive_lock_define(STORAGECLASS, NAME) \
573 STORAGECLASS gl_recursive_lock_t NAME;
574# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
575 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
576# define gl_recursive_lock_initializer \
577 { DEFAULTMUTEX, (thread_t) 0, 0 }
578# define glthread_recursive_lock_init(LOCK) \
579 (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
580# define glthread_recursive_lock_lock(LOCK) \
581 (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
582# define glthread_recursive_lock_unlock(LOCK) \
583 (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
584# define glthread_recursive_lock_destroy(LOCK) \
585 (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
586extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
587extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
588extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
589extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
590
591/* -------------------------- gl_once_t datatype -------------------------- */
592
593typedef struct
594 {
595 volatile int inited;
596 mutex_t mutex;
597 }
598 gl_once_t;
599# define gl_once_define(STORAGECLASS, NAME) \
600 STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
601# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
602 (thread_in_use () \
603 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
604 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
605extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
606extern int glthread_once_singlethreaded (gl_once_t *once_control);
607 524
608# ifdef __cplusplus 525# ifdef __cplusplus
609} 526}
@@ -618,6 +535,11 @@ extern int glthread_once_singlethreaded (gl_once_t *once_control);
618# define WIN32_LEAN_AND_MEAN /* avoid including junk */ 535# define WIN32_LEAN_AND_MEAN /* avoid including junk */
619# include <windows.h> 536# include <windows.h>
620 537
538# include "windows-mutex.h"
539# include "windows-rwlock.h"
540# include "windows-recmutex.h"
541# include "windows-once.h"
542
621# ifdef __cplusplus 543# ifdef __cplusplus
622extern "C" { 544extern "C" {
623# endif 545# endif
@@ -633,127 +555,69 @@ extern "C" {
633/* There is no way to statically initialize a CRITICAL_SECTION. It needs 555/* There is no way to statically initialize a CRITICAL_SECTION. It needs
634 to be done lazily, once only. For this we need spinlocks. */ 556 to be done lazily, once only. For this we need spinlocks. */
635 557
636typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
637
638/* -------------------------- gl_lock_t datatype -------------------------- */ 558/* -------------------------- gl_lock_t datatype -------------------------- */
639 559
640typedef struct 560typedef glwthread_mutex_t gl_lock_t;
641 {
642 gl_spinlock_t guard; /* protects the initialization */
643 CRITICAL_SECTION lock;
644 }
645 gl_lock_t;
646# define gl_lock_define(STORAGECLASS, NAME) \ 561# define gl_lock_define(STORAGECLASS, NAME) \
647 STORAGECLASS gl_lock_t NAME; 562 STORAGECLASS gl_lock_t NAME;
648# define gl_lock_define_initialized(STORAGECLASS, NAME) \ 563# define gl_lock_define_initialized(STORAGECLASS, NAME) \
649 STORAGECLASS gl_lock_t NAME = gl_lock_initializer; 564 STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
650# define gl_lock_initializer \ 565# define gl_lock_initializer \
651 { { 0, -1 } } 566 GLWTHREAD_MUTEX_INIT
652# define glthread_lock_init(LOCK) \ 567# define glthread_lock_init(LOCK) \
653 (glthread_lock_init_func (LOCK), 0) 568 (glwthread_mutex_init (LOCK), 0)
654# define glthread_lock_lock(LOCK) \ 569# define glthread_lock_lock(LOCK) \
655 glthread_lock_lock_func (LOCK) 570 glwthread_mutex_lock (LOCK)
656# define glthread_lock_unlock(LOCK) \ 571# define glthread_lock_unlock(LOCK) \
657 glthread_lock_unlock_func (LOCK) 572 glwthread_mutex_unlock (LOCK)
658# define glthread_lock_destroy(LOCK) \ 573# define glthread_lock_destroy(LOCK) \
659 glthread_lock_destroy_func (LOCK) 574 glwthread_mutex_destroy (LOCK)
660extern void glthread_lock_init_func (gl_lock_t *lock);
661extern int glthread_lock_lock_func (gl_lock_t *lock);
662extern int glthread_lock_unlock_func (gl_lock_t *lock);
663extern int glthread_lock_destroy_func (gl_lock_t *lock);
664 575
665/* ------------------------- gl_rwlock_t datatype ------------------------- */ 576/* ------------------------- gl_rwlock_t datatype ------------------------- */
666 577
667/* It is impossible to implement read-write locks using plain locks, without 578typedef glwthread_rwlock_t gl_rwlock_t;
668 introducing an extra thread dedicated to managing read-write locks.
669 Therefore here we need to use the low-level Event type. */
670
671typedef struct
672 {
673 HANDLE *array; /* array of waiting threads, each represented by an event */
674 unsigned int count; /* number of waiting threads */
675 unsigned int alloc; /* length of allocated array */
676 unsigned int offset; /* index of first waiting thread in array */
677 }
678 gl_carray_waitqueue_t;
679typedef struct
680 {
681 gl_spinlock_t guard; /* protects the initialization */
682 CRITICAL_SECTION lock; /* protects the remaining fields */
683 gl_carray_waitqueue_t waiting_readers; /* waiting readers */
684 gl_carray_waitqueue_t waiting_writers; /* waiting writers */
685 int runcount; /* number of readers running, or -1 when a writer runs */
686 }
687 gl_rwlock_t;
688# define gl_rwlock_define(STORAGECLASS, NAME) \ 579# define gl_rwlock_define(STORAGECLASS, NAME) \
689 STORAGECLASS gl_rwlock_t NAME; 580 STORAGECLASS gl_rwlock_t NAME;
690# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ 581# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
691 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; 582 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
692# define gl_rwlock_initializer \ 583# define gl_rwlock_initializer \
693 { { 0, -1 } } 584 GLWTHREAD_RWLOCK_INIT
694# define glthread_rwlock_init(LOCK) \ 585# define glthread_rwlock_init(LOCK) \
695 (glthread_rwlock_init_func (LOCK), 0) 586 (glwthread_rwlock_init (LOCK), 0)
696# define glthread_rwlock_rdlock(LOCK) \ 587# define glthread_rwlock_rdlock(LOCK) \
697 glthread_rwlock_rdlock_func (LOCK) 588 glwthread_rwlock_rdlock (LOCK)
698# define glthread_rwlock_wrlock(LOCK) \ 589# define glthread_rwlock_wrlock(LOCK) \
699 glthread_rwlock_wrlock_func (LOCK) 590 glwthread_rwlock_wrlock (LOCK)
700# define glthread_rwlock_unlock(LOCK) \ 591# define glthread_rwlock_unlock(LOCK) \
701 glthread_rwlock_unlock_func (LOCK) 592 glwthread_rwlock_unlock (LOCK)
702# define glthread_rwlock_destroy(LOCK) \ 593# define glthread_rwlock_destroy(LOCK) \
703 glthread_rwlock_destroy_func (LOCK) 594 glwthread_rwlock_destroy (LOCK)
704extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
705extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
706extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
707extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
708extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
709 595
710/* --------------------- gl_recursive_lock_t datatype --------------------- */ 596/* --------------------- gl_recursive_lock_t datatype --------------------- */
711 597
712/* The native Windows documentation says that CRITICAL_SECTION already 598typedef glwthread_recmutex_t gl_recursive_lock_t;
713 implements a recursive lock. But we need not rely on it: It's easy to
714 implement a recursive lock without this assumption. */
715
716typedef struct
717 {
718 gl_spinlock_t guard; /* protects the initialization */
719 DWORD owner;
720 unsigned long depth;
721 CRITICAL_SECTION lock;
722 }
723 gl_recursive_lock_t;
724# define gl_recursive_lock_define(STORAGECLASS, NAME) \ 599# define gl_recursive_lock_define(STORAGECLASS, NAME) \
725 STORAGECLASS gl_recursive_lock_t NAME; 600 STORAGECLASS gl_recursive_lock_t NAME;
726# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ 601# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
727 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; 602 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
728# define gl_recursive_lock_initializer \ 603# define gl_recursive_lock_initializer \
729 { { 0, -1 }, 0, 0 } 604 GLWTHREAD_RECMUTEX_INIT
730# define glthread_recursive_lock_init(LOCK) \ 605# define glthread_recursive_lock_init(LOCK) \
731 (glthread_recursive_lock_init_func (LOCK), 0) 606 (glwthread_recmutex_init (LOCK), 0)
732# define glthread_recursive_lock_lock(LOCK) \ 607# define glthread_recursive_lock_lock(LOCK) \
733 glthread_recursive_lock_lock_func (LOCK) 608 glwthread_recmutex_lock (LOCK)
734# define glthread_recursive_lock_unlock(LOCK) \ 609# define glthread_recursive_lock_unlock(LOCK) \
735 glthread_recursive_lock_unlock_func (LOCK) 610 glwthread_recmutex_unlock (LOCK)
736# define glthread_recursive_lock_destroy(LOCK) \ 611# define glthread_recursive_lock_destroy(LOCK) \
737 glthread_recursive_lock_destroy_func (LOCK) 612 glwthread_recmutex_destroy (LOCK)
738extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
739extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
740extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
741extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
742 613
743/* -------------------------- gl_once_t datatype -------------------------- */ 614/* -------------------------- gl_once_t datatype -------------------------- */
744 615
745typedef struct 616typedef glwthread_once_t gl_once_t;
746 {
747 volatile int inited;
748 volatile long started;
749 CRITICAL_SECTION lock;
750 }
751 gl_once_t;
752# define gl_once_define(STORAGECLASS, NAME) \ 617# define gl_once_define(STORAGECLASS, NAME) \
753 STORAGECLASS gl_once_t NAME = { -1, -1 }; 618 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
754# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ 619# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
755 (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) 620 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
756extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
757 621
758# ifdef __cplusplus 622# ifdef __cplusplus
759} 623}
@@ -763,7 +627,7 @@ extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (v
763 627
764/* ========================================================================= */ 628/* ========================================================================= */
765 629
766#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) 630#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
767 631
768/* Provide dummy implementation if threads are not supported. */ 632/* Provide dummy implementation if threads are not supported. */
769 633