diff --git a/docs/license.rst b/docs/license.rst index 99f8dab3e25..e24cfe5f48b 100644 --- a/docs/license.rst +++ b/docs/license.rst @@ -80,7 +80,7 @@ Mesa Component Licenses +-----------------+------------------------+-----------------------------+ | GLX client code | src/glx/ | SGI Free Software License B | +-----------------+------------------------+-----------------------------+ -| C11 thread | include/c11/threads*.h | Boost (permissive) | +| C11 thread | src/c11/impl/threads* | Boost (permissive) | | emulation | | | +-----------------+------------------------+-----------------------------+ diff --git a/include/c11/threads.h b/include/c11/threads.h deleted file mode 100644 index 75bd445faff..00000000000 --- a/include/c11/threads.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * C11 emulation library - * - * (C) Copyright yohhoy 2012. - * Distributed under the Boost Software License, Version 1.0. - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare [[derivative work]]s of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#ifndef EMULATED_THREADS_H_INCLUDED_ -#define EMULATED_THREADS_H_INCLUDED_ - -#include "c11/time.h" - -/*---------------------------- types ----------------------------*/ -typedef void (*tss_dtor_t)(void*); -typedef int (*thrd_start_t)(void*); - - -/*-------------------- enumeration constants --------------------*/ -enum { - mtx_plain = 0, - mtx_try = 1, - mtx_timed = 2, - mtx_recursive = 4 -}; - -enum { - thrd_success = 0, // succeeded - thrd_timedout, // timed out - thrd_error, // failed - thrd_busy, // resource busy - thrd_nomem // out of memory -}; - -/*-------------------------- functions --------------------------*/ - -#if defined(_WIN32) && !defined(__CYGWIN__) -#include "threads_win32.h" -#elif defined(HAVE_PTHREAD) -#include "threads_posix.h" -#else -#error Not supported on this platform. -#endif - - - -#endif /* EMULATED_THREADS_H_INCLUDED_ */ diff --git a/include/c11/.editorconfig b/src/c11/impl/.editorconfig similarity index 78% rename from include/c11/.editorconfig rename to src/c11/impl/.editorconfig index bdbea000b53..7b12a40ca00 100644 --- a/include/c11/.editorconfig +++ b/src/c11/impl/.editorconfig @@ -1,3 +1,3 @@ -[*.h] +[*.{c,h}] indent_style = space indent_size = 4 diff --git a/src/c11/impl/meson.build b/src/c11/impl/meson.build index ab8f17e33d0..dbd9ecfdd05 100644 --- a/src/c11/impl/meson.build +++ b/src/c11/impl/meson.build @@ -22,6 +22,12 @@ files_mesa_util_c11 = files( 'time.c', ) +if host_machine.system() == 'windows' + files_mesa_util_c11 += 'threads_win32.c' +else + files_mesa_util_c11 += 'threads_posix.c' +endif + _libmesa_util_c11 = static_library( 'mesa_util_c11', [files_mesa_util_c11], diff --git a/include/c11/threads_posix.h b/src/c11/impl/threads_posix.c similarity index 86% rename from include/c11/threads_posix.h rename to src/c11/impl/threads_posix.c index 8e17686d51a..736fc587be2 100644 --- a/include/c11/threads_posix.h +++ b/src/c11/impl/threads_posix.c @@ -27,15 +27,15 @@ * DEALINGS IN THE SOFTWARE. */ #include -#ifndef assert #include -#endif #include #include #include #include #include /* for intptr_t */ +#include "c11/threads.h" + /* Configuration macro: @@ -47,27 +47,7 @@ Configuration macro: #define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK #endif - -#include - -/*---------------------------- macros ----------------------------*/ -#define ONCE_FLAG_INIT PTHREAD_ONCE_INIT -#ifdef INIT_ONCE_STATIC_INIT -#define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS -#else -#define TSS_DTOR_ITERATIONS 1 // assume TSS dtor MAY be called at least once. -#endif - -// FIXME: temporary non-standard hack to ease transition -#define _MTX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER - /*---------------------------- types ----------------------------*/ -typedef pthread_cond_t cnd_t; -typedef pthread_t thrd_t; -typedef pthread_key_t tss_t; -typedef pthread_mutex_t mtx_t; -typedef pthread_once_t once_flag; - /* Implementation limits: @@ -79,7 +59,7 @@ struct impl_thrd_param { void *arg; }; -static inline void * +static void * impl_thrd_routine(void *p) { struct impl_thrd_param pack = *((struct impl_thrd_param *)p); @@ -90,7 +70,7 @@ impl_thrd_routine(void *p) /*--------------- 7.25.2 Initialization functions ---------------*/ // 7.25.2.1 -static inline void +void call_once(once_flag *flag, void (*func)(void)) { pthread_once(flag, func); @@ -99,7 +79,7 @@ call_once(once_flag *flag, void (*func)(void)) /*------------- 7.25.3 Condition variable functions -------------*/ // 7.25.3.1 -static inline int +int cnd_broadcast(cnd_t *cond) { assert(cond != NULL); @@ -107,7 +87,7 @@ cnd_broadcast(cnd_t *cond) } // 7.25.3.2 -static inline void +void cnd_destroy(cnd_t *cond) { assert(cond); @@ -115,7 +95,7 @@ cnd_destroy(cnd_t *cond) } // 7.25.3.3 -static inline int +int cnd_init(cnd_t *cond) { assert(cond != NULL); @@ -123,7 +103,7 @@ cnd_init(cnd_t *cond) } // 7.25.3.4 -static inline int +int cnd_signal(cnd_t *cond) { assert(cond != NULL); @@ -131,7 +111,7 @@ cnd_signal(cnd_t *cond) } // 7.25.3.5 -static inline int +int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time) { int rt; @@ -147,7 +127,7 @@ cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time) } // 7.25.3.6 -static inline int +int cnd_wait(cnd_t *cond, mtx_t *mtx) { assert(mtx != NULL); @@ -158,7 +138,7 @@ cnd_wait(cnd_t *cond, mtx_t *mtx) /*-------------------- 7.25.4 Mutex functions --------------------*/ // 7.25.4.1 -static inline void +void mtx_destroy(mtx_t *mtx) { assert(mtx != NULL); @@ -192,7 +172,7 @@ int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); #endif // 7.25.4.2 -static inline int +int mtx_init(mtx_t *mtx, int type) { pthread_mutexattr_t attr; @@ -216,21 +196,15 @@ mtx_init(mtx_t *mtx, int type) } // 7.25.4.3 -static inline int +int mtx_lock(mtx_t *mtx) { assert(mtx != NULL); return (pthread_mutex_lock(mtx) == 0) ? thrd_success : thrd_error; } -static inline int -mtx_trylock(mtx_t *mtx); - -static inline void -thrd_yield(void); - // 7.25.4.4 -static inline int +int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { assert(mtx != NULL); @@ -259,7 +233,7 @@ mtx_timedlock(mtx_t *mtx, const struct timespec *ts) } // 7.25.4.5 -static inline int +int mtx_trylock(mtx_t *mtx) { assert(mtx != NULL); @@ -267,7 +241,7 @@ mtx_trylock(mtx_t *mtx) } // 7.25.4.6 -static inline int +int mtx_unlock(mtx_t *mtx) { assert(mtx != NULL); @@ -277,7 +251,7 @@ mtx_unlock(mtx_t *mtx) /*------------------- 7.25.5 Thread functions -------------------*/ // 7.25.5.1 -static inline int +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { struct impl_thrd_param *pack; @@ -294,35 +268,36 @@ thrd_create(thrd_t *thr, thrd_start_t func, void *arg) } // 7.25.5.2 -static inline thrd_t +thrd_t thrd_current(void) { return pthread_self(); } // 7.25.5.3 -static inline int +int thrd_detach(thrd_t thr) { return (pthread_detach(thr) == 0) ? thrd_success : thrd_error; } // 7.25.5.4 -static inline int +int thrd_equal(thrd_t thr0, thrd_t thr1) { return pthread_equal(thr0, thr1); } // 7.25.5.5 -static inline void +_Noreturn +void thrd_exit(int res) { pthread_exit((void*)(intptr_t)res); } // 7.25.5.6 -static inline int +int thrd_join(thrd_t thr, int *res) { void *code; @@ -334,15 +309,15 @@ thrd_join(thrd_t thr, int *res) } // 7.25.5.7 -static inline void +int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) { assert(time_point != NULL); - nanosleep(time_point, remaining); + return nanosleep(time_point, remaining); } // 7.25.5.8 -static inline void +void thrd_yield(void) { sched_yield(); @@ -351,7 +326,7 @@ thrd_yield(void) /*----------- 7.25.6 Thread-specific storage functions -----------*/ // 7.25.6.1 -static inline int +int tss_create(tss_t *key, tss_dtor_t dtor) { assert(key != NULL); @@ -359,21 +334,21 @@ tss_create(tss_t *key, tss_dtor_t dtor) } // 7.25.6.2 -static inline void +void tss_delete(tss_t key) { pthread_key_delete(key); } // 7.25.6.3 -static inline void * +void * tss_get(tss_t key) { return pthread_getspecific(key); } // 7.25.6.4 -static inline int +int tss_set(tss_t key, void *val) { return (pthread_setspecific(key, val) == 0) ? thrd_success : thrd_error; diff --git a/include/c11/threads_win32.h b/src/c11/impl/threads_win32.c similarity index 84% rename from include/c11/threads_win32.h rename to src/c11/impl/threads_win32.c index dbda982f7d5..08c9475d81c 100644 --- a/include/c11/threads_win32.h +++ b/src/c11/impl/threads_win32.c @@ -26,14 +26,19 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifndef assert #include -#endif #include #include #include // MSVCRT #include +#include "c11/threads.h" + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include + /* Configuration macro: @@ -54,50 +59,17 @@ Configuration macro: #endif #define EMULATED_THREADS_TSS_DTOR_SLOTNUM 64 // see TLS_MINIMUM_AVAILABLE -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - // check configuration #if defined(EMULATED_THREADS_USE_NATIVE_CALL_ONCE) && (_WIN32_WINNT < 0x0600) #error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600 #endif -/*---------------------------- macros ----------------------------*/ -#ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE -#define ONCE_FLAG_INIT INIT_ONCE_STATIC_INIT -#else -#define ONCE_FLAG_INIT {0} -#endif -#define TSS_DTOR_ITERATIONS 1 -// FIXME: temporary non-standard hack to ease transition -#define _MTX_INITIALIZER_NP {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0} - -/*---------------------------- types ----------------------------*/ -typedef CONDITION_VARIABLE cnd_t; - -typedef HANDLE thrd_t; - -typedef DWORD tss_t; - -typedef CRITICAL_SECTION mtx_t; - -#ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE -typedef INIT_ONCE once_flag; -#else -typedef struct once_flag_t { - volatile LONG status; -} once_flag; -#endif - - -static inline void * tss_get(tss_t key); -static inline void thrd_yield(void); -static inline int mtx_trylock(mtx_t *mtx); -static inline int mtx_lock(mtx_t *mtx); -static inline int mtx_unlock(mtx_t *mtx); +static_assert(sizeof(cnd_t) == sizeof(CONDITION_VARIABLE), "The size of cnd_t must equal to CONDITION_VARIABLE"); +static_assert(sizeof(thrd_t) == sizeof(HANDLE), "The size of thrd_t must equal to HANDLE"); +static_assert(sizeof(tss_t) == sizeof(DWORD), "The size of tss_t must equal to DWORD"); +static_assert(sizeof(mtx_t) == sizeof(CRITICAL_SECTION), "The size of mtx_t must equal to CRITICAL_SECTION"); +static_assert(sizeof(once_flag) == sizeof(INIT_ONCE), "The size of once_flag must equal to INIT_ONCE"); /* Implementation limits: @@ -168,7 +140,7 @@ static int impl_tss_dtor_register(tss_t key, tss_dtor_t dtor) return 0; } -static void impl_tss_dtor_invoke() +static void impl_tss_dtor_invoke(void) { int i; for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { @@ -183,7 +155,7 @@ static void impl_tss_dtor_invoke() /*--------------- 7.25.2 Initialization functions ---------------*/ // 7.25.2.1 -static inline void +void call_once(once_flag *flag, void (*func)(void)) { assert(flag && func); @@ -191,12 +163,12 @@ call_once(once_flag *flag, void (*func)(void)) { struct impl_call_once_param param; param.func = func; - InitOnceExecuteOnce(flag, impl_call_once_callback, (PVOID)¶m, NULL); + InitOnceExecuteOnce((PINIT_ONCE)flag, impl_call_once_callback, (PVOID)¶m, NULL); } #else - if (InterlockedCompareExchange(&flag->status, 1, 0) == 0) { + if (InterlockedCompareExchangePointer((PVOID volatile *)&flag->status, (PVOID)1, (PVOID)0) == 0) { (func)(); - InterlockedExchange(&flag->status, 2); + InterlockedExchangePointer((PVOID volatile *)&flag->status, (PVOID)2); } else { while (flag->status == 1) { // busy loop! @@ -209,16 +181,16 @@ call_once(once_flag *flag, void (*func)(void)) /*------------- 7.25.3 Condition variable functions -------------*/ // 7.25.3.1 -static inline int +int cnd_broadcast(cnd_t *cond) { assert(cond != NULL); - WakeAllConditionVariable(cond); + WakeAllConditionVariable((PCONDITION_VARIABLE)cond); return thrd_success; } // 7.25.3.2 -static inline void +void cnd_destroy(cnd_t *cond) { (void)cond; @@ -227,58 +199,58 @@ cnd_destroy(cnd_t *cond) } // 7.25.3.3 -static inline int +int cnd_init(cnd_t *cond) { assert(cond != NULL); - InitializeConditionVariable(cond); + InitializeConditionVariable((PCONDITION_VARIABLE)cond); return thrd_success; } // 7.25.3.4 -static inline int +int cnd_signal(cnd_t *cond) { assert(cond != NULL); - WakeConditionVariable(cond); + WakeConditionVariable((PCONDITION_VARIABLE)cond); return thrd_success; } // 7.25.3.5 -static inline int +int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time) { assert(cond != NULL); assert(mtx != NULL); assert(abs_time != NULL); const DWORD timeout = impl_abs2relmsec(abs_time); - if (SleepConditionVariableCS(cond, mtx, timeout)) + if (SleepConditionVariableCS((PCONDITION_VARIABLE)cond, (PCRITICAL_SECTION)mtx, timeout)) return thrd_success; return (GetLastError() == ERROR_TIMEOUT) ? thrd_timedout : thrd_error; } // 7.25.3.6 -static inline int +int cnd_wait(cnd_t *cond, mtx_t *mtx) { assert(cond != NULL); assert(mtx != NULL); - SleepConditionVariableCS(cond, mtx, INFINITE); + SleepConditionVariableCS((PCONDITION_VARIABLE)cond, (PCRITICAL_SECTION)mtx, INFINITE); return thrd_success; } /*-------------------- 7.25.4 Mutex functions --------------------*/ // 7.25.4.1 -static inline void +void mtx_destroy(mtx_t *mtx) { assert(mtx); - DeleteCriticalSection(mtx); + DeleteCriticalSection((PCRITICAL_SECTION)mtx); } // 7.25.4.2 -static inline int +int mtx_init(mtx_t *mtx, int type) { assert(mtx != NULL); @@ -287,21 +259,21 @@ mtx_init(mtx_t *mtx, int type) && type != (mtx_timed|mtx_recursive) && type != (mtx_try|mtx_recursive)) return thrd_error; - InitializeCriticalSection(mtx); + InitializeCriticalSection((PCRITICAL_SECTION)mtx); return thrd_success; } // 7.25.4.3 -static inline int +int mtx_lock(mtx_t *mtx) { assert(mtx != NULL); - EnterCriticalSection(mtx); + EnterCriticalSection((PCRITICAL_SECTION)mtx); return thrd_success; } // 7.25.4.4 -static inline int +int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { assert(mtx != NULL); @@ -316,26 +288,26 @@ mtx_timedlock(mtx_t *mtx, const struct timespec *ts) } // 7.25.4.5 -static inline int +int mtx_trylock(mtx_t *mtx) { assert(mtx != NULL); - return TryEnterCriticalSection(mtx) ? thrd_success : thrd_busy; + return TryEnterCriticalSection((PCRITICAL_SECTION)mtx) ? thrd_success : thrd_busy; } // 7.25.4.6 -static inline int +int mtx_unlock(mtx_t *mtx) { assert(mtx != NULL); - LeaveCriticalSection(mtx); + LeaveCriticalSection((PCRITICAL_SECTION)mtx); return thrd_success; } /*------------------- 7.25.5 Thread functions -------------------*/ // 7.25.5.1 -static inline int +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { struct impl_thrd_param *pack; @@ -397,7 +369,7 @@ thrd_current(void) #endif // 7.25.5.3 -static inline int +int thrd_detach(thrd_t thr) { CloseHandle(thr); @@ -405,14 +377,15 @@ thrd_detach(thrd_t thr) } // 7.25.5.4 -static inline int +int thrd_equal(thrd_t thr0, thrd_t thr1) { return GetThreadId(thr0) == GetThreadId(thr1); } // 7.25.5.5 -static inline void +_Noreturn +void thrd_exit(int res) { impl_tss_dtor_invoke(); @@ -420,7 +393,7 @@ thrd_exit(int res) } // 7.25.5.6 -static inline int +int thrd_join(thrd_t thr, int *res) { DWORD w, code; @@ -439,17 +412,18 @@ thrd_join(thrd_t thr, int *res) } // 7.25.5.7 -static inline void +int thrd_sleep(const struct timespec *time_point, struct timespec *remaining) { (void)remaining; assert(time_point); assert(!remaining); /* not implemented */ Sleep((DWORD)impl_timespec2msec(time_point)); + return 0; } // 7.25.5.8 -static inline void +void thrd_yield(void) { SwitchToThread(); @@ -458,7 +432,7 @@ thrd_yield(void) /*----------- 7.25.6 Thread-specific storage functions -----------*/ // 7.25.6.1 -static inline int +int tss_create(tss_t *key, tss_dtor_t dtor) { assert(key != NULL); @@ -473,21 +447,21 @@ tss_create(tss_t *key, tss_dtor_t dtor) } // 7.25.6.2 -static inline void +void tss_delete(tss_t key) { TlsFree(key); } // 7.25.6.3 -static inline void * +void * tss_get(tss_t key) { return TlsGetValue(key); } // 7.25.6.4 -static inline int +int tss_set(tss_t key, void *val) { return TlsSetValue(key, val) ? thrd_success : thrd_error; diff --git a/src/c11/threads.h b/src/c11/threads.h new file mode 100644 index 00000000000..23495cd197c --- /dev/null +++ b/src/c11/threads.h @@ -0,0 +1,136 @@ +/* + * Copyright 2022 Yonggang Luo + * SPDX-License-Identifier: MIT + * + * C11 emulation library + */ + +#ifndef C11_THREADS_H_INCLUDED_ +#define C11_THREADS_H_INCLUDED_ + +#include "c11/time.h" + +#include +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include /* close */ +# include /* _exit */ +#elif defined(HAVE_PTHREAD) +# include +# include /* close, _exit */ +#else +# error Not supported on this platform. +#endif + +/*---------------------------- macros ---------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------- types ----------------------------*/ +typedef void (*tss_dtor_t)(void *); +typedef int (*thrd_start_t)(void *); + +#if defined(_WIN32) && !defined(__CYGWIN__) +typedef struct +{ + void *Ptr; +} cnd_t; +typedef void *thrd_t; +typedef unsigned long tss_t; +typedef struct +{ + void *DebugInfo; + long LockCount; + long RecursionCount; + void *OwningThread; + void *LockSemaphore; + uintptr_t SpinCount; +} mtx_t; /* Mock of CRITICAL_SECTION */ +typedef struct +{ + volatile uintptr_t status; +} once_flag; +// FIXME: temporary non-standard hack to ease transition +# define _MTX_INITIALIZER_NP {(void*)-1, -1, 0, 0, 0, 0} +# define ONCE_FLAG_INIT {0} +# define TSS_DTOR_ITERATIONS 1 +#elif defined(HAVE_PTHREAD) +typedef pthread_cond_t cnd_t; +typedef pthread_t thrd_t; +typedef pthread_key_t tss_t; +typedef pthread_mutex_t mtx_t; +typedef pthread_once_t once_flag; +// FIXME: temporary non-standard hack to ease transition +# define _MTX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER +# define ONCE_FLAG_INIT PTHREAD_ONCE_INIT +# ifdef INIT_ONCE_STATIC_INIT +# define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS +# else +# define TSS_DTOR_ITERATIONS 1 // assume TSS dtor MAY be called at least once. +# endif +#else +# error Not supported on this platform. +#endif + +/*-------------------- enumeration constants --------------------*/ +enum +{ + mtx_plain = 0, + mtx_try = 1, + mtx_timed = 2, + mtx_recursive = 4 +}; + +enum +{ + thrd_success = 0, // succeeded + thrd_timedout, // timed out + thrd_error, // failed + thrd_busy, // resource busy + thrd_nomem // out of memory +}; + +/*-------------------------- functions --------------------------*/ + +void call_once(once_flag *, void (*)(void)); +int cnd_broadcast(cnd_t *); +void cnd_destroy(cnd_t *); +int cnd_init(cnd_t *); +int cnd_signal(cnd_t *); +int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict __mtx, + const struct timespec *__restrict); +int cnd_wait(cnd_t *, mtx_t *__mtx); +void mtx_destroy(mtx_t *__mtx); +int mtx_init(mtx_t *__mtx, int); +int mtx_lock(mtx_t *__mtx); +int mtx_timedlock(mtx_t *__restrict __mtx, + const struct timespec *__restrict); +int mtx_trylock(mtx_t *__mtx); +int mtx_unlock(mtx_t *__mtx); +int thrd_create(thrd_t *, thrd_start_t, void *); +thrd_t thrd_current(void); +int thrd_detach(thrd_t); +int thrd_equal(thrd_t, thrd_t); +#if defined(__cplusplus) +[[ noreturn ]] +#else +_Noreturn +#endif +void thrd_exit(int); +int thrd_join(thrd_t, int *); +int thrd_sleep(const struct timespec *, struct timespec *); +void thrd_yield(void); +int tss_create(tss_t *, tss_dtor_t); +void tss_delete(tss_t); +void *tss_get(tss_t); +int tss_set(tss_t, void *); + +#ifdef __cplusplus +} +#endif + +#endif /* C11_THREADS_H_INCLUDED_ */