1 /* An ISO C 11 compatible <threads.h>.
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <https://www.gnu.org/licenses/>. */
19 @PRAGMA_SYSTEM_HEADER@
23 #ifndef _@GUARD_PREFIX@_THREADS_H
25 /* The include_next requires a split double-inclusion guard. */
27 # @INCLUDE_NEXT@ @NEXT_THREADS_H@
30 #ifndef _@GUARD_PREFIX@_THREADS_H
31 #define _@GUARD_PREFIX@_THREADS_H
37 # if defined _WIN32 && ! defined __CYGWIN__
38 /* Use Windows threads. */
40 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
44 /* Use POSIX threads. */
52 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
54 /* The definition of _Noreturn is copied here. */
56 /* The definition of _GL_ARG_NONNULL is copied here. */
58 /* The definition of _GL_WARN_ON_USE is copied here. */
61 /* Storage class specifier for thread-local storage. */
63 /* The macro definition from AIX 7.1..7.2 <threads.h> is unusable, because
64 its expansion ends in a semicolon. */
67 #if !@HAVE_THREADS_H@ || !defined thread_local
68 # define thread_local _Thread_local
70 /* Define the macro thread_local if and only if it actually works. */
71 #if !@HAVE_THREAD_LOCAL@
76 /* =========== ISO C 11 7.26.5 Thread functions =========== */
90 # if defined _WIN32 && ! defined __CYGWIN__
91 /* Use Windows threads. */
93 # include "windows-thread.h"
95 typedef glwthread_thread_t thrd_t
;
98 /* Use POSIX threads. */
100 typedef pthread_t thrd_t
;
106 #if @BROKEN_THRD_START_T@
107 /* Need to override thrd_start_t, to make thrd_create work. */
108 # define thrd_start_t rpl_thrd_start_t
109 /* Need to override thrd_t, to make thrd_join work. */
110 struct thrd_with_exitcode
113 int volatile detached
;
114 int volatile exitcode
;
116 typedef struct thrd_with_exitcode
*rpl_thrd_t
;
117 # define thrd_t rpl_thrd_t
119 /* Type of the main function of a thread. */
120 #if !@HAVE_THREADS_H@ || @BROKEN_THRD_START_T@
121 typedef int (* thrd_start_t
) (void *);
125 # if @REPLACE_THRD_CREATE@
126 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
127 # define thrd_create rpl_thrd_create
129 _GL_FUNCDECL_RPL (thrd_create
, int, (thrd_t
*, thrd_start_t
, void *)
130 _GL_ARG_NONNULL ((1, 2)));
131 _GL_CXXALIAS_RPL (thrd_create
, int, (thrd_t
*, thrd_start_t
, void *));
133 # if !@HAVE_THREADS_H@
134 _GL_FUNCDECL_SYS (thrd_create
, int, (thrd_t
*, thrd_start_t
, void *)
135 _GL_ARG_NONNULL ((1, 2)));
137 _GL_CXXALIAS_SYS (thrd_create
, int, (thrd_t
*, thrd_start_t
, void *));
139 _GL_CXXALIASWARN (thrd_create
);
140 #elif defined GNULIB_POSIXCHECK
142 # if HAVE_RAW_DECL_THRD_CREATE
143 _GL_WARN_ON_USE (thrd_create
, "thrd_create is unportable - "
144 "use gnulib module thrd for portability");
149 # if @REPLACE_THRD_CURRENT@
150 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
151 # define thrd_current rpl_thrd_current
153 _GL_FUNCDECL_RPL (thrd_current
, thrd_t
, (void) _GL_ATTRIBUTE_PURE
);
154 _GL_CXXALIAS_RPL (thrd_current
, thrd_t
, (void));
156 # if !@HAVE_THREADS_H@
157 _GL_FUNCDECL_SYS (thrd_current
, thrd_t
, (void) _GL_ATTRIBUTE_PURE
);
159 _GL_CXXALIAS_SYS (thrd_current
, thrd_t
, (void));
161 _GL_CXXALIASWARN (thrd_current
);
162 #elif defined GNULIB_POSIXCHECK
164 # if HAVE_RAW_DECL_THRD_CURRENT
165 _GL_WARN_ON_USE (thrd_current
, "thrd_current is unportable - "
166 "use gnulib module thrd for portability");
171 # if @REPLACE_THRD_EQUAL@
172 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
173 # define thrd_equal rpl_thrd_equal
175 _GL_FUNCDECL_RPL (thrd_equal
, int, (thrd_t
, thrd_t
) _GL_ATTRIBUTE_PURE
);
176 _GL_CXXALIAS_RPL (thrd_equal
, int, (thrd_t
, thrd_t
));
178 # if !@HAVE_THREADS_H@
179 _GL_FUNCDECL_SYS (thrd_equal
, int, (thrd_t
, thrd_t
) _GL_ATTRIBUTE_PURE
);
181 _GL_CXXALIAS_SYS (thrd_equal
, int, (thrd_t
, thrd_t
));
183 _GL_CXXALIASWARN (thrd_equal
);
184 #elif defined GNULIB_POSIXCHECK
186 # if HAVE_RAW_DECL_THRD_EQUAL
187 _GL_WARN_ON_USE (thrd_equal
, "thrd_equal is unportable - "
188 "use gnulib module thrd for portability");
193 # if !@HAVE_THREADS_H@
194 _GL_FUNCDECL_SYS (thrd_sleep
, int,
195 (const struct timespec
*, struct timespec
*)
196 _GL_ARG_NONNULL ((1)));
198 _GL_CXXALIAS_SYS (thrd_sleep
, int,
199 (const struct timespec
*, struct timespec
*));
200 _GL_CXXALIASWARN (thrd_sleep
);
201 #elif defined GNULIB_POSIXCHECK
203 # if HAVE_RAW_DECL_THRD_SLEEP
204 _GL_WARN_ON_USE (thrd_sleep
, "thrd_sleep is unportable - "
205 "use gnulib module thrd for portability");
210 # if !@HAVE_THREADS_H@
211 _GL_FUNCDECL_SYS (thrd_yield
, void, (void));
213 _GL_CXXALIAS_SYS (thrd_yield
, void, (void));
214 _GL_CXXALIASWARN (thrd_yield
);
215 #elif defined GNULIB_POSIXCHECK
217 # if HAVE_RAW_DECL_THRD_YIELD
218 _GL_WARN_ON_USE (thrd_yield
, "thrd_yield is unportable - "
219 "use gnulib module thrd for portability");
224 # if @REPLACE_THRD_DETACH@
225 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
226 # define thrd_detach rpl_thrd_detach
228 _GL_FUNCDECL_RPL (thrd_detach
, int, (thrd_t
));
229 _GL_CXXALIAS_RPL (thrd_detach
, int, (thrd_t
));
231 # if !@HAVE_THREADS_H@
232 _GL_FUNCDECL_SYS (thrd_detach
, int, (thrd_t
));
234 _GL_CXXALIAS_SYS (thrd_detach
, int, (thrd_t
));
236 _GL_CXXALIASWARN (thrd_detach
);
237 #elif defined GNULIB_POSIXCHECK
239 # if HAVE_RAW_DECL_THRD_DETACH
240 _GL_WARN_ON_USE (thrd_detach
, "thrd_detach is unportable - "
241 "use gnulib module thrd for portability");
246 # if @REPLACE_THRD_JOIN@
247 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
248 # define thrd_join rpl_thrd_join
250 _GL_FUNCDECL_RPL (thrd_join
, int, (thrd_t
, int *));
251 _GL_CXXALIAS_RPL (thrd_join
, int, (thrd_t
, int *));
253 # if !@HAVE_THREADS_H@
254 _GL_FUNCDECL_SYS (thrd_join
, int, (thrd_t
, int *));
256 _GL_CXXALIAS_SYS (thrd_join
, int, (thrd_t
, int *));
258 _GL_CXXALIASWARN (thrd_join
);
259 #elif defined GNULIB_POSIXCHECK
261 # if HAVE_RAW_DECL_THRD_JOIN
262 _GL_WARN_ON_USE (thrd_join
, "thrd_join is unportable - "
263 "use gnulib module thrd for portability");
268 # if !@HAVE_THREADS_H@
269 _GL_FUNCDECL_SYS (thrd_exit
, _Noreturn
void, (int));
271 /* Need to cast because of AIX with xlclang++. */
272 _GL_CXXALIAS_SYS_CAST (thrd_exit
, void, (int));
273 _GL_CXXALIASWARN (thrd_exit
);
274 #elif defined GNULIB_POSIXCHECK
276 # if HAVE_RAW_DECL_THRD_EXIT
277 _GL_WARN_ON_USE (thrd_exit
, "thrd_exit is unportable - "
278 "use gnulib module thrd for portability");
283 /* =========== ISO C 11 7.26.4 Mutex functions =========== */
285 #if !@HAVE_THREADS_H@
287 /* Types of mutexes. */
295 # if defined _WIN32 && ! defined __CYGWIN__
296 /* Use Windows threads. */
298 # include "windows-mutex.h"
299 # include "windows-recmutex.h"
300 # include "windows-timedmutex.h"
301 # include "windows-timedrecmutex.h"
308 glwthread_mutex_t u_mutex
;
309 glwthread_recmutex_t u_recmutex
;
310 glwthread_timedmutex_t u_timedmutex
;
311 glwthread_timedrecmutex_t u_timedrecmutex
;
318 /* Use POSIX threads. */
320 typedef pthread_mutex_t mtx_t
;
327 # if !@HAVE_THREADS_H@
328 _GL_FUNCDECL_SYS (mtx_init
, int, (mtx_t
*, int) _GL_ARG_NONNULL ((1)));
330 _GL_CXXALIAS_SYS (mtx_init
, int, (mtx_t
*, int));
331 _GL_CXXALIASWARN (mtx_init
);
332 #elif defined GNULIB_POSIXCHECK
334 # if HAVE_RAW_DECL_MTX_INIT
335 _GL_WARN_ON_USE (mtx_init
, "mtx_init is unportable - "
336 "use gnulib module mtx for portability");
341 # if !@HAVE_THREADS_H@
342 _GL_FUNCDECL_SYS (mtx_lock
, int, (mtx_t
*) _GL_ARG_NONNULL ((1)));
344 _GL_CXXALIAS_SYS (mtx_lock
, int, (mtx_t
*));
345 _GL_CXXALIASWARN (mtx_lock
);
346 #elif defined GNULIB_POSIXCHECK
348 # if HAVE_RAW_DECL_MTX_LOCK
349 _GL_WARN_ON_USE (mtx_lock
, "mtx_lock is unportable - "
350 "use gnulib module mtx for portability");
355 # if !@HAVE_THREADS_H@
356 _GL_FUNCDECL_SYS (mtx_trylock
, int, (mtx_t
*) _GL_ARG_NONNULL ((1)));
358 _GL_CXXALIAS_SYS (mtx_trylock
, int, (mtx_t
*));
359 _GL_CXXALIASWARN (mtx_trylock
);
360 #elif defined GNULIB_POSIXCHECK
362 # if HAVE_RAW_DECL_MTX_TRYLOCK
363 _GL_WARN_ON_USE (mtx_trylock
, "mtx_trylock is unportable - "
364 "use gnulib module mtx for portability");
369 # if !@HAVE_THREADS_H@
370 _GL_FUNCDECL_SYS (mtx_timedlock
, int, (mtx_t
*, const struct timespec
*)
371 _GL_ARG_NONNULL ((1, 2)));
373 _GL_CXXALIAS_SYS (mtx_timedlock
, int, (mtx_t
*, const struct timespec
*));
374 _GL_CXXALIASWARN (mtx_timedlock
);
375 #elif defined GNULIB_POSIXCHECK
376 # undef mtx_timedlock
377 # if HAVE_RAW_DECL_MTX_TIMEDLOCK
378 _GL_WARN_ON_USE (mtx_timedlock
, "mtx_timedlock is unportable - "
379 "use gnulib module mtx for portability");
384 # if !@HAVE_THREADS_H@
385 _GL_FUNCDECL_SYS (mtx_unlock
, int, (mtx_t
*) _GL_ARG_NONNULL ((1)));
387 _GL_CXXALIAS_SYS (mtx_unlock
, int, (mtx_t
*));
388 _GL_CXXALIASWARN (mtx_unlock
);
389 #elif defined GNULIB_POSIXCHECK
391 # if HAVE_RAW_DECL_MTX_UNLOCK
392 _GL_WARN_ON_USE (mtx_unlock
, "mtx_unlock is unportable - "
393 "use gnulib module mtx for portability");
398 # if !@HAVE_THREADS_H@
399 _GL_FUNCDECL_SYS (mtx_destroy
, void, (mtx_t
*) _GL_ARG_NONNULL ((1)));
401 _GL_CXXALIAS_SYS (mtx_destroy
, void, (mtx_t
*));
402 _GL_CXXALIASWARN (mtx_destroy
);
403 #elif defined GNULIB_POSIXCHECK
405 # if HAVE_RAW_DECL_MTX_DESTROY
406 _GL_WARN_ON_USE (mtx_destroy
, "mtx_destroy is unportable - "
407 "use gnulib module mtx for portability");
412 /* =========== ISO C 11 7.26.2 Initialization functions =========== */
414 #if !@HAVE_THREADS_H@
416 /* Type that contains a flag for use by call_once. */
417 # if defined _WIN32 && ! defined __CYGWIN__
418 /* Use Windows threads. */
420 # include "windows-once.h"
422 typedef glwthread_once_t once_flag
;
423 # define ONCE_FLAG_INIT GLWTHREAD_ONCE_INIT
426 /* Use POSIX threads. */
428 typedef pthread_once_t once_flag
;
429 # define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
436 # if !@HAVE_THREADS_H@
437 _GL_FUNCDECL_SYS (call_once
, void, (once_flag
*, void (*) (void))
438 _GL_ARG_NONNULL ((1, 2)));
440 _GL_CXXALIAS_SYS_CAST (call_once
, void, (once_flag
*, void (*) (void)));
441 _GL_CXXALIASWARN (call_once
);
442 #elif defined GNULIB_POSIXCHECK
444 # if HAVE_RAW_DECL_CALL_ONCE
445 _GL_WARN_ON_USE (call_once
, "call_once is unportable - "
446 "use gnulib module mtx for portability");
451 /* =========== ISO C 11 7.26.3 Condition variable functions =========== */
453 #if !@HAVE_THREADS_H@
455 # if defined _WIN32 && ! defined __CYGWIN__
456 /* Use Windows threads. */
458 # include "windows-cond.h"
460 typedef glwthread_cond_t cnd_t
;
463 /* Use POSIX threads. */
465 typedef pthread_cond_t cnd_t
;
472 # if !@HAVE_THREADS_H@
473 _GL_FUNCDECL_SYS (cnd_init
, int, (cnd_t
*) _GL_ARG_NONNULL ((1)));
475 _GL_CXXALIAS_SYS (cnd_init
, int, (cnd_t
*));
476 _GL_CXXALIASWARN (cnd_init
);
477 #elif defined GNULIB_POSIXCHECK
479 # if HAVE_RAW_DECL_CND_INIT
480 _GL_WARN_ON_USE (cnd_init
, "cnd_init is unportable - "
481 "use gnulib module cnd for portability");
486 # if !@HAVE_THREADS_H@
487 _GL_FUNCDECL_SYS (cnd_wait
, int, (cnd_t
*, mtx_t
*) _GL_ARG_NONNULL ((1, 2)));
489 _GL_CXXALIAS_SYS (cnd_wait
, int, (cnd_t
*, mtx_t
*));
490 _GL_CXXALIASWARN (cnd_wait
);
491 #elif defined GNULIB_POSIXCHECK
493 # if HAVE_RAW_DECL_CND_WAIT
494 _GL_WARN_ON_USE (cnd_wait
, "cnd_wait is unportable - "
495 "use gnulib module cnd for portability");
500 # if !@HAVE_THREADS_H@
501 _GL_FUNCDECL_SYS (cnd_timedwait
, int,
502 (cnd_t
*, mtx_t
*, const struct timespec
*)
503 _GL_ARG_NONNULL ((1, 2, 3)));
505 _GL_CXXALIAS_SYS (cnd_timedwait
, int,
506 (cnd_t
*, mtx_t
*, const struct timespec
*));
507 _GL_CXXALIASWARN (cnd_timedwait
);
508 #elif defined GNULIB_POSIXCHECK
509 # undef cnd_timedwait
510 # if HAVE_RAW_DECL_CND_TIMEDWAIT
511 _GL_WARN_ON_USE (cnd_timedwait
, "cnd_timedwait is unportable - "
512 "use gnulib module cnd for portability");
517 # if !@HAVE_THREADS_H@
518 _GL_FUNCDECL_SYS (cnd_signal
, int, (cnd_t
*) _GL_ARG_NONNULL ((1)));
520 _GL_CXXALIAS_SYS (cnd_signal
, int, (cnd_t
*));
521 _GL_CXXALIASWARN (cnd_signal
);
522 #elif defined GNULIB_POSIXCHECK
524 # if HAVE_RAW_DECL_CND_SIGNAL
525 _GL_WARN_ON_USE (cnd_signal
, "cnd_signal is unportable - "
526 "use gnulib module cnd for portability");
531 # if !@HAVE_THREADS_H@
532 _GL_FUNCDECL_SYS (cnd_broadcast
, int, (cnd_t
*) _GL_ARG_NONNULL ((1)));
534 _GL_CXXALIAS_SYS (cnd_broadcast
, int, (cnd_t
*));
535 _GL_CXXALIASWARN (cnd_broadcast
);
536 #elif defined GNULIB_POSIXCHECK
537 # undef cnd_broadcast
538 # if HAVE_RAW_DECL_CND_BROADCAST
539 _GL_WARN_ON_USE (cnd_broadcast
, "cnd_broadcast is unportable - "
540 "use gnulib module cnd for portability");
545 # if !@HAVE_THREADS_H@
546 _GL_FUNCDECL_SYS (cnd_destroy
, void, (cnd_t
*) _GL_ARG_NONNULL ((1)));
548 _GL_CXXALIAS_SYS (cnd_destroy
, void, (cnd_t
*));
549 _GL_CXXALIASWARN (cnd_destroy
);
550 #elif defined GNULIB_POSIXCHECK
552 # if HAVE_RAW_DECL_CND_DESTROY
553 _GL_WARN_ON_USE (cnd_destroy
, "cnd_destroy is unportable - "
554 "use gnulib module cnd for portability");
559 /* =========== ISO C 11 7.26.6 Thread-specific storage functions =========== */
561 #if !@HAVE_THREADS_H@
563 # if defined _WIN32 && ! defined __CYGWIN__
564 /* Use Windows threads. */
566 # include "windows-tls.h"
568 typedef glwthread_tls_key_t tss_t
;
569 # define TSS_DTOR_ITERATIONS GLWTHREAD_DESTRUCTOR_ITERATIONS
572 /* Use POSIX threads. */
576 typedef pthread_key_t tss_t
;
580 /* Type for the destructor of a thread-specific storage pointer. */
581 typedef void (*tss_dtor_t
) (void *);
585 /* AIX 7.1 <threads.h> does not define TSS_DTOR_ITERATIONS. */
586 #ifndef TSS_DTOR_ITERATIONS
587 # ifdef PTHREAD_DESTRUCTOR_ITERATIONS
588 # define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
590 /* IRIX 6.5 does not define PTHREAD_DESTRUCTOR_ITERATIONS.
591 This value is a wild guess. */
592 # define TSS_DTOR_ITERATIONS 1
597 # if !@HAVE_THREADS_H@
598 _GL_FUNCDECL_SYS (tss_create
, int, (tss_t
*, tss_dtor_t
) _GL_ARG_NONNULL ((1)));
600 _GL_CXXALIAS_SYS (tss_create
, int, (tss_t
*, tss_dtor_t
));
601 _GL_CXXALIASWARN (tss_create
);
602 #elif defined GNULIB_POSIXCHECK
604 # if HAVE_RAW_DECL_TSS_CREATE
605 _GL_WARN_ON_USE (tss_create
, "tss_create is unportable - "
606 "use gnulib module tss for portability");
611 # if !@HAVE_THREADS_H@
612 _GL_FUNCDECL_SYS (tss_set
, int, (tss_t
, void *));
614 _GL_CXXALIAS_SYS (tss_set
, int, (tss_t
, void *));
615 _GL_CXXALIASWARN (tss_set
);
616 #elif defined GNULIB_POSIXCHECK
618 # if HAVE_RAW_DECL_TSS_SET
619 _GL_WARN_ON_USE (tss_set
, "tss_set is unportable - "
620 "use gnulib module tss for portability");
625 # if !@HAVE_THREADS_H@
626 _GL_FUNCDECL_SYS (tss_get
, void *, (tss_t
));
628 _GL_CXXALIAS_SYS (tss_get
, void *, (tss_t
));
629 _GL_CXXALIASWARN (tss_get
);
630 #elif defined GNULIB_POSIXCHECK
632 # if HAVE_RAW_DECL_TSS_GET
633 _GL_WARN_ON_USE (tss_get
, "tss_get is unportable - "
634 "use gnulib module tss for portability");
639 # if !@HAVE_THREADS_H@
640 _GL_FUNCDECL_SYS (tss_delete
, void, (tss_t
));
642 _GL_CXXALIAS_SYS (tss_delete
, void, (tss_t
));
643 _GL_CXXALIASWARN (tss_delete
);
644 #elif defined GNULIB_POSIXCHECK
646 # if HAVE_RAW_DECL_TSS_DELETE
647 _GL_WARN_ON_USE (tss_delete
, "tss_delete is unportable - "
648 "use gnulib module tss for portability");
653 #endif /* _@GUARD_PREFIX@_THREADS_H */
654 #endif /* _@GUARD_PREFIX@_THREADS_H */