summaryrefslogtreecommitdiffstats
path: root/gl/glthread
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
commitb0afb8fe0ff1d87165af9df61501197a06240dda (patch)
tree274ac6a96c53ef4c19ab4974ce24a06a233128c5 /gl/glthread
parent68fc05381ee5fa0aee1413118fbb3d81ca888b09 (diff)
downloadmonitoring-plugins-b0afb8fe0ff1d87165af9df61501197a06240dda.tar.gz
Sync with Gnulib stable-202507 code (a8ac9f9ce5)
Diffstat (limited to 'gl/glthread')
-rw-r--r--gl/glthread/lock.c46
-rw-r--r--gl/glthread/lock.h153
-rw-r--r--gl/glthread/once.c80
-rw-r--r--gl/glthread/once.h272
-rw-r--r--gl/glthread/threadlib.c2
5 files changed, 360 insertions, 193 deletions
diff --git a/gl/glthread/lock.c b/gl/glthread/lock.c
index 6661ad6a..dace4fda 100644
--- a/gl/glthread/lock.c
+++ b/gl/glthread/lock.c
@@ -1,5 +1,5 @@
1/* Locking in multithreaded situations. 1/* Locking in multithreaded situations.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc. 2 Copyright (C) 2005-2025 Free Software Foundation, Inc.
3 3
4 This file 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 Lesser General Public License as 5 it under the terms of the GNU Lesser General Public License as
@@ -240,8 +240,6 @@ glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
240 return 0; 240 return 0;
241} 241}
242 242
243/* -------------------------- gl_once_t datatype -------------------------- */
244
245#endif 243#endif
246 244
247/* ========================================================================= */ 245/* ========================================================================= */
@@ -271,7 +269,7 @@ glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock)
271 /* Note: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is the only value that 269 /* Note: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is the only value that
272 causes the writer to be preferred. PTHREAD_RWLOCK_PREFER_WRITER_NP does not 270 causes the writer to be preferred. PTHREAD_RWLOCK_PREFER_WRITER_NP does not
273 do this; see 271 do this; see
274 http://man7.org/linux/man-pages/man3/pthread_rwlockattr_setkind_np.3.html */ 272 https://man7.org/linux/man-pages/man3/pthread_rwlockattr_setkind_np.3.html */
275 err = pthread_rwlockattr_setkind_np (&attributes, 273 err = pthread_rwlockattr_setkind_np (&attributes,
276 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 274 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
277 if (err == 0) 275 if (err == 0)
@@ -698,46 +696,6 @@ glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
698 696
699# endif 697# endif
700 698
701/* -------------------------- gl_once_t datatype -------------------------- */
702
703static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
704
705int
706glthread_once_singlethreaded (pthread_once_t *once_control)
707{
708 /* We don't know whether pthread_once_t is an integer type, a floating-point
709 type, a pointer type, or a structure type. */
710 char *firstbyte = (char *)once_control;
711 if (*firstbyte == *(const char *)&fresh_once)
712 {
713 /* First time use of once_control. Invert the first byte. */
714 *firstbyte = ~ *(const char *)&fresh_once;
715 return 1;
716 }
717 else
718 return 0;
719}
720
721# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK)
722
723int
724glthread_once_multithreaded (pthread_once_t *once_control,
725 void (*init_function) (void))
726{
727 int err = pthread_once (once_control, init_function);
728 if (err == ENOSYS)
729 {
730 /* This happens on FreeBSD 11: The pthread_once function in libc returns
731 ENOSYS. */
732 if (glthread_once_singlethreaded (once_control))
733 init_function ();
734 return 0;
735 }
736 return err;
737}
738
739# endif
740
741#endif 699#endif
742 700
743/* ========================================================================= */ 701/* ========================================================================= */
diff --git a/gl/glthread/lock.h b/gl/glthread/lock.h
index 2d5cb320..d6ccc202 100644
--- a/gl/glthread/lock.h
+++ b/gl/glthread/lock.h
@@ -1,5 +1,5 @@
1/* Locking in multithreaded situations. 1/* Locking in multithreaded situations.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc. 2 Copyright (C) 2005-2025 Free Software Foundation, Inc.
3 3
4 This file 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 Lesser General Public License as 5 it under the terms of the GNU Lesser General Public License as
@@ -64,13 +64,6 @@
64 Taking the lock: err = glthread_recursive_lock_lock (&name); 64 Taking the lock: err = glthread_recursive_lock_lock (&name);
65 Releasing the lock: err = glthread_recursive_lock_unlock (&name); 65 Releasing the lock: err = glthread_recursive_lock_unlock (&name);
66 De-initialization: err = glthread_recursive_lock_destroy (&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*/ 67*/
75 68
76 69
@@ -88,17 +81,9 @@
88#include <errno.h> 81#include <errno.h>
89#include <stdlib.h> 82#include <stdlib.h>
90 83
91#if !defined c11_threads_in_use 84#include "glthread/once.h"
92# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC 85
93# define c11_threads_in_use() 1 86/* c11_threads_in_use() is defined in glthread/once.h. */
94# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
95# include <threads.h>
96# pragma weak thrd_exit
97# define c11_threads_in_use() (thrd_exit != NULL)
98# else
99# define c11_threads_in_use() 0
100# endif
101#endif
102 87
103/* ========================================================================= */ 88/* ========================================================================= */
104 89
@@ -195,14 +180,6 @@ extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
195extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); 180extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
196extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); 181extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
197 182
198/* -------------------------- gl_once_t datatype -------------------------- */
199
200typedef once_flag gl_once_t;
201# define gl_once_define(STORAGECLASS, NAME) \
202 STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
203# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
204 (call_once (ONCE_CONTROL, INITFUNCTION), 0)
205
206# ifdef __cplusplus 183# ifdef __cplusplus
207} 184}
208# endif 185# endif
@@ -221,80 +198,7 @@ typedef once_flag gl_once_t;
221extern "C" { 198extern "C" {
222# endif 199# endif
223 200
224# if PTHREAD_IN_USE_DETECTION_HARD 201/* pthread_in_use() is defined in glthread/once.h. */
225
226/* The pthread_in_use() detection needs to be done at runtime. */
227# define pthread_in_use() \
228 glthread_in_use ()
229extern int glthread_in_use (void);
230
231# endif
232
233# if USE_POSIX_THREADS_WEAK
234
235/* Use weak references to the POSIX threads library. */
236
237/* Weak references avoid dragging in external libraries if the other parts
238 of the program don't use them. Here we use them, because we don't want
239 every program that uses libintl to depend on libpthread. This assumes
240 that libpthread would not be loaded after libintl; i.e. if libintl is
241 loaded first, by an executable that does not depend on libpthread, and
242 then a module is dynamically loaded that depends on libpthread, libintl
243 will not be multithread-safe. */
244
245/* The way to test at runtime whether libpthread is present is to test
246 whether a function pointer's value, such as &pthread_mutex_init, is
247 non-NULL. However, some versions of GCC have a bug through which, in
248 PIC mode, &foo != NULL always evaluates to true if there is a direct
249 call to foo(...) in the same function. To avoid this, we test the
250 address of a function in libpthread that we don't use. */
251
252# pragma weak pthread_mutex_init
253# pragma weak pthread_mutex_lock
254# pragma weak pthread_mutex_unlock
255# pragma weak pthread_mutex_destroy
256# pragma weak pthread_rwlock_init
257# pragma weak pthread_rwlock_rdlock
258# pragma weak pthread_rwlock_wrlock
259# pragma weak pthread_rwlock_unlock
260# pragma weak pthread_rwlock_destroy
261# pragma weak pthread_once
262# pragma weak pthread_cond_init
263# pragma weak pthread_cond_wait
264# pragma weak pthread_cond_signal
265# pragma weak pthread_cond_broadcast
266# pragma weak pthread_cond_destroy
267# pragma weak pthread_mutexattr_init
268# pragma weak pthread_mutexattr_settype
269# pragma weak pthread_mutexattr_destroy
270# pragma weak pthread_rwlockattr_init
271# if __GNU_LIBRARY__ > 1
272# pragma weak pthread_rwlockattr_setkind_np
273# endif
274# pragma weak pthread_rwlockattr_destroy
275# ifndef pthread_self
276# pragma weak pthread_self
277# endif
278
279# if !PTHREAD_IN_USE_DETECTION_HARD
280 /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
281 can be used to determine whether libpthread is in use. These are:
282 pthread_mutexattr_gettype
283 pthread_rwlockattr_destroy
284 pthread_rwlockattr_init
285 */
286# pragma weak pthread_mutexattr_gettype
287# define pthread_in_use() \
288 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
289# endif
290
291# else
292
293# if !PTHREAD_IN_USE_DETECTION_HARD
294# define pthread_in_use() 1
295# endif
296
297# endif
298 202
299/* -------------------------- gl_lock_t datatype -------------------------- */ 203/* -------------------------- gl_lock_t datatype -------------------------- */
300 204
@@ -510,26 +414,6 @@ extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *l
510 414
511# endif 415# endif
512 416
513/* -------------------------- gl_once_t datatype -------------------------- */
514
515typedef pthread_once_t gl_once_t;
516# define gl_once_define(STORAGECLASS, NAME) \
517 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
518# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
519# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
520 (pthread_in_use () \
521 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
522 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
523# else
524# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
525 (pthread_in_use () \
526 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
527 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
528extern int glthread_once_multithreaded (pthread_once_t *once_control,
529 void (*init_function) (void));
530# endif
531extern int glthread_once_singlethreaded (pthread_once_t *once_control);
532
533# ifdef __cplusplus 417# ifdef __cplusplus
534} 418}
535# endif 419# endif
@@ -546,7 +430,6 @@ extern int glthread_once_singlethreaded (pthread_once_t *once_control);
546# include "windows-mutex.h" 430# include "windows-mutex.h"
547# include "windows-rwlock.h" 431# include "windows-rwlock.h"
548# include "windows-recmutex.h" 432# include "windows-recmutex.h"
549# include "windows-once.h"
550 433
551# ifdef __cplusplus 434# ifdef __cplusplus
552extern "C" { 435extern "C" {
@@ -619,14 +502,6 @@ typedef glwthread_recmutex_t gl_recursive_lock_t;
619# define glthread_recursive_lock_destroy(LOCK) \ 502# define glthread_recursive_lock_destroy(LOCK) \
620 glwthread_recmutex_destroy (LOCK) 503 glwthread_recmutex_destroy (LOCK)
621 504
622/* -------------------------- gl_once_t datatype -------------------------- */
623
624typedef glwthread_once_t gl_once_t;
625# define gl_once_define(STORAGECLASS, NAME) \
626 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
627# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
628 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
629
630# ifdef __cplusplus 505# ifdef __cplusplus
631} 506}
632# endif 507# endif
@@ -670,14 +545,6 @@ typedef int gl_recursive_lock_t;
670# define glthread_recursive_lock_unlock(NAME) 0 545# define glthread_recursive_lock_unlock(NAME) 0
671# define glthread_recursive_lock_destroy(NAME) 0 546# define glthread_recursive_lock_destroy(NAME) 0
672 547
673/* -------------------------- gl_once_t datatype -------------------------- */
674
675typedef int gl_once_t;
676# define gl_once_define(STORAGECLASS, NAME) \
677 STORAGECLASS gl_once_t NAME = 0;
678# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
679 (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
680
681#endif 548#endif
682 549
683/* ========================================================================= */ 550/* ========================================================================= */
@@ -784,16 +651,6 @@ typedef int gl_once_t;
784 } \ 651 } \
785 while (0) 652 while (0)
786 653
787/* -------------------------- gl_once_t datatype -------------------------- */
788
789#define gl_once(NAME, INITFUNCTION) \
790 do \
791 { \
792 if (glthread_once (&NAME, INITFUNCTION)) \
793 abort (); \
794 } \
795 while (0)
796
797/* ========================================================================= */ 654/* ========================================================================= */
798 655
799#endif /* _LOCK_H */ 656#endif /* _LOCK_H */
diff --git a/gl/glthread/once.c b/gl/glthread/once.c
new file mode 100644
index 00000000..53211af8
--- /dev/null
+++ b/gl/glthread/once.c
@@ -0,0 +1,80 @@
1/* Once-only initialization in multithreaded situations.
2 Copyright (C) 2005-2025 Free Software Foundation, Inc.
3
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 This file 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser 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. */
19
20#include <config.h>
21
22#include "glthread/once.h"
23
24/* ========================================================================= */
25
26#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
27
28#endif
29
30/* ========================================================================= */
31
32#if USE_POSIX_THREADS
33
34static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
35
36int
37glthread_once_singlethreaded (pthread_once_t *once_control)
38{
39 /* We don't know whether pthread_once_t is an integer type, a floating-point
40 type, a pointer type, or a structure type. */
41 char *firstbyte = (char *)once_control;
42 if (*firstbyte == *(const char *)&fresh_once)
43 {
44 /* First time use of once_control. Invert the first byte. */
45 *firstbyte = ~ *(const char *)&fresh_once;
46 return 1;
47 }
48 else
49 return 0;
50}
51
52# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK)
53
54int
55glthread_once_multithreaded (pthread_once_t *once_control,
56 void (*init_function) (void))
57{
58 int err = pthread_once (once_control, init_function);
59 if (err == ENOSYS)
60 {
61 /* This happens on FreeBSD 11: The pthread_once function in libc returns
62 ENOSYS. */
63 if (glthread_once_singlethreaded (once_control))
64 init_function ();
65 return 0;
66 }
67 return err;
68}
69
70# endif
71
72#endif
73
74/* ========================================================================= */
75
76#if USE_WINDOWS_THREADS
77
78#endif
79
80/* ========================================================================= */
diff --git a/gl/glthread/once.h b/gl/glthread/once.h
new file mode 100644
index 00000000..943bd7a2
--- /dev/null
+++ b/gl/glthread/once.h
@@ -0,0 +1,272 @@
1/* Once-only initialization in multithreaded situations.
2 Copyright (C) 2005-2025 Free Software Foundation, Inc.
3
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 This file 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser 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 once-only initialization primitives for use with a given
21 thread library.
22 It does not contain primitives for creating threads or for other
23 synchronization primitives.
24
25 Once-only execution:
26 Type: gl_once_t
27 Initializer: gl_once_define(extern, name)
28 Execution: gl_once (name, initfunction);
29 Equivalent functions with control of error handling:
30 Execution: err = glthread_once (&name, initfunction);
31*/
32
33
34#ifndef _ONCE_H
35#define _ONCE_H
36
37/* This file uses HAVE_THREADS_H. */
38#if !_GL_CONFIG_H_INCLUDED
39 #error "Please include config.h first."
40#endif
41
42#include <errno.h>
43#include <stdlib.h>
44
45#if !defined c11_threads_in_use
46# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
47# define c11_threads_in_use() 1
48# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
49# include <threads.h>
50# pragma weak thrd_exit
51# define c11_threads_in_use() (thrd_exit != NULL)
52# else
53# define c11_threads_in_use() 0
54# endif
55#endif
56
57/* ========================================================================= */
58
59#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
60
61/* Use the ISO C threads library. */
62
63# include <threads.h>
64
65# ifdef __cplusplus
66extern "C" {
67# endif
68
69/* -------------------------- gl_once_t datatype -------------------------- */
70
71typedef once_flag gl_once_t;
72# define gl_once_define(STORAGECLASS, NAME) \
73 STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
74# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
75 (call_once (ONCE_CONTROL, INITFUNCTION), 0)
76
77# ifdef __cplusplus
78}
79# endif
80
81#endif
82
83/* ========================================================================= */
84
85#if USE_POSIX_THREADS
86
87/* Use the POSIX threads library. */
88
89# include <pthread.h>
90
91# ifdef __cplusplus
92extern "C" {
93# endif
94
95# if PTHREAD_IN_USE_DETECTION_HARD
96
97/* The pthread_in_use() detection needs to be done at runtime. */
98# define pthread_in_use() \
99 glthread_in_use ()
100extern int glthread_in_use (void);
101
102# endif
103
104# if USE_POSIX_THREADS_WEAK
105
106/* Use weak references to the POSIX threads library. */
107
108/* Weak references avoid dragging in external libraries if the other parts
109 of the program don't use them. Here we use them, because we don't want
110 every program that uses libintl to depend on libpthread. This assumes
111 that libpthread would not be loaded after libintl; i.e. if libintl is
112 loaded first, by an executable that does not depend on libpthread, and
113 then a module is dynamically loaded that depends on libpthread, libintl
114 will not be multithread-safe. */
115
116/* The way to test at runtime whether libpthread is present is to test
117 whether a function pointer's value, such as &pthread_mutex_init, is
118 non-NULL. However, some versions of GCC have a bug through which, in
119 PIC mode, &foo != NULL always evaluates to true if there is a direct
120 call to foo(...) in the same function. To avoid this, we test the
121 address of a function in libpthread that we don't use. */
122
123# pragma weak pthread_mutex_init
124# pragma weak pthread_mutex_lock
125# pragma weak pthread_mutex_unlock
126# pragma weak pthread_mutex_destroy
127/* Work around clang bug <https://github.com/llvm/llvm-project/issues/104670> */
128# ifndef pthread_rwlock_init
129# pragma weak pthread_rwlock_init
130# endif
131# pragma weak pthread_rwlock_rdlock
132# pragma weak pthread_rwlock_wrlock
133# pragma weak pthread_rwlock_unlock
134# pragma weak pthread_rwlock_destroy
135# pragma weak pthread_once
136# pragma weak pthread_cond_init
137# pragma weak pthread_cond_wait
138# pragma weak pthread_cond_signal
139# pragma weak pthread_cond_broadcast
140# pragma weak pthread_cond_destroy
141# pragma weak pthread_mutexattr_init
142# pragma weak pthread_mutexattr_settype
143# pragma weak pthread_mutexattr_destroy
144/* Work around clang bug <https://github.com/llvm/llvm-project/issues/104670> */
145# ifndef pthread_rwlockattr_init
146# pragma weak pthread_rwlockattr_init
147# endif
148# if __GNU_LIBRARY__ > 1
149# pragma weak pthread_rwlockattr_setkind_np
150# endif
151# pragma weak pthread_rwlockattr_destroy
152# ifndef pthread_self
153# pragma weak pthread_self
154# endif
155
156# if !PTHREAD_IN_USE_DETECTION_HARD
157 /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
158 can be used to determine whether libpthread is in use. These are:
159 pthread_mutexattr_gettype
160 pthread_rwlockattr_destroy
161 pthread_rwlockattr_init
162 */
163# pragma weak pthread_mutexattr_gettype
164# define pthread_in_use() \
165 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
166# endif
167
168# else
169
170# if !PTHREAD_IN_USE_DETECTION_HARD
171# define pthread_in_use() 1
172# endif
173
174# endif
175
176/* -------------------------- gl_once_t datatype -------------------------- */
177
178typedef pthread_once_t gl_once_t;
179# define gl_once_define(STORAGECLASS, NAME) \
180 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
181# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
182# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
183 (pthread_in_use () \
184 ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
185 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
186# else
187# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
188 (pthread_in_use () \
189 ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
190 : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
191extern int glthread_once_multithreaded (pthread_once_t *once_control,
192 void (*init_function) (void));
193# endif
194extern int glthread_once_singlethreaded (pthread_once_t *once_control);
195
196# ifdef __cplusplus
197}
198# endif
199
200#endif
201
202/* ========================================================================= */
203
204#if USE_WINDOWS_THREADS
205
206# define WIN32_LEAN_AND_MEAN /* avoid including junk */
207# include <windows.h>
208
209# include "windows-once.h"
210
211# ifdef __cplusplus
212extern "C" {
213# endif
214
215/* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
216 Mutex, Semaphore types, because
217 - we need only to synchronize inside a single process (address space),
218 not inter-process locking,
219 - we don't need to support trylock operations. (TryEnterCriticalSection
220 does not work on Windows 95/98/ME. Packages that need trylock usually
221 define their own mutex type.) */
222
223/* There is no way to statically initialize a CRITICAL_SECTION. It needs
224 to be done lazily, once only. For this we need spinlocks. */
225
226/* -------------------------- gl_once_t datatype -------------------------- */
227
228typedef glwthread_once_t gl_once_t;
229# define gl_once_define(STORAGECLASS, NAME) \
230 STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
231# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
232 (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
233
234# ifdef __cplusplus
235}
236# endif
237
238#endif
239
240/* ========================================================================= */
241
242#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
243
244/* Provide dummy implementation if threads are not supported. */
245
246/* -------------------------- gl_once_t datatype -------------------------- */
247
248typedef int gl_once_t;
249# define gl_once_define(STORAGECLASS, NAME) \
250 STORAGECLASS gl_once_t NAME = 0;
251# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
252 (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
253
254#endif
255
256/* ========================================================================= */
257
258/* Macros with built-in error handling. */
259
260/* -------------------------- gl_once_t datatype -------------------------- */
261
262#define gl_once(NAME, INITFUNCTION) \
263 do \
264 { \
265 if (glthread_once (&NAME, INITFUNCTION)) \
266 abort (); \
267 } \
268 while (0)
269
270/* ========================================================================= */
271
272#endif /* _ONCE_H */
diff --git a/gl/glthread/threadlib.c b/gl/glthread/threadlib.c
index 7a776768..a6f7688b 100644
--- a/gl/glthread/threadlib.c
+++ b/gl/glthread/threadlib.c
@@ -1,5 +1,5 @@
1/* Multithreading primitives. 1/* Multithreading primitives.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc. 2 Copyright (C) 2005-2025 Free Software Foundation, Inc.
3 3
4 This file 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 Lesser General Public License as 5 it under the terms of the GNU Lesser General Public License as