Mesa (main): c11: Move the implementation of threads.h into c source code

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 15 18:05:01 UTC 2022


Module: Mesa
Branch: main
Commit: e6392fcf3d8b8dd7e3a8427755d8be2f2332366a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e6392fcf3d8b8dd7e3a8427755d8be2f2332366a

Author: Yonggang Luo <luoyonggang at gmail.com>
Date:   Sat Feb 19 13:19:08 2022 +0800

c11: Move the implementation of threads.h into c source code

By doing this, now the global variable impl_tss_dtor_tbl are only defined one time.
So the memory usage would reduced

Signed-off-by: Yonggang Luo <luoyonggang at gmail.com>
Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15087>

---

 docs/license.rst                                   |   2 +-
 include/c11/threads.h                              |  67 ----------
 {include/c11 => src/c11/impl}/.editorconfig        |   2 +-
 src/c11/impl/meson.build                           |   6 +
 .../c11/impl/threads_posix.c                       |  85 +++++--------
 .../c11/impl/threads_win32.c                       | 130 ++++++++------------
 src/c11/threads.h                                  | 136 +++++++++++++++++++++
 7 files changed, 226 insertions(+), 202 deletions(-)

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 <threads.h> 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 <stdlib.h>
-#ifndef assert
 #include <assert.h>
-#endif
 #include <limits.h>
 #include <errno.h>
 #include <unistd.h>
 #include <sched.h>
 #include <stdint.h> /* for intptr_t */
 
+#include "c11/threads.h"
+
 /*
 Configuration macro:
 
@@ -47,27 +47,7 @@ Configuration macro:
 #define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK
 #endif
 
-
-#include <pthread.h>
-
-/*---------------------------- 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 <assert.h>
-#endif
 #include <limits.h>
 #include <errno.h>
 #include <process.h>  // MSVCRT
 #include <stdlib.h>
 
+#include "c11/threads.h"
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
 /*
 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 <windows.h>
-
 // 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)&param, NULL);
+    InitOnceExecuteOnce((PINIT_ONCE)flag, impl_call_once_callback, (PVOID)&param, 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 <threads.h> emulation library
+ */
+
+#ifndef C11_THREADS_H_INCLUDED_
+#define C11_THREADS_H_INCLUDED_
+
+#include "c11/time.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#  include <io.h> /* close */
+#  include <process.h> /* _exit */
+#elif defined(HAVE_PTHREAD)
+#  include <pthread.h>
+#  include <unistd.h> /* 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_ */



More information about the mesa-commit mailing list