From 51c3fca3bf79d1c4d200fcb1fd48d24dc03e5d7a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jul 2020 16:57:09 -0700 Subject: [PATCH] Util: Refactor TLS out of platform-specific APIs --- CMakeLists.txt | 2 +- include/mgba-util/platform/posix/threading.h | 13 +++++++++++ include/mgba-util/platform/psp2/threading.h | 16 +++++++++++++ .../mgba-util/platform/windows/threading.h | 13 +++++++++++ include/mgba-util/threading.h | 21 +++++++++++++++++ src/core/thread.c | 23 ++++++------------- 6 files changed, 71 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 24e5b96bd..15f27a1fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_C_STANDARD 99) if(NOT MSVC) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) - if(SWITCH) + if(SWITCH OR 3DS) set(CMAKE_C_STANDARD 11) set(CMAKE_C_EXTENSIONS ON) elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3") diff --git a/include/mgba-util/platform/posix/threading.h b/include/mgba-util/platform/posix/threading.h index 64340c852..32d2ea4b1 100644 --- a/include/mgba-util/platform/posix/threading.h +++ b/include/mgba-util/platform/posix/threading.h @@ -24,6 +24,7 @@ typedef THREAD_ENTRY (*ThreadEntry)(void*); typedef pthread_t Thread; typedef pthread_mutex_t Mutex; typedef pthread_cond_t Condition; +typedef pthread_key_t ThreadLocal; static inline int MutexInit(Mutex* mutex) { return pthread_mutex_init(mutex, 0); @@ -101,6 +102,18 @@ static inline int ThreadSetName(const char* name) { #endif } +static inline void ThreadLocalInitKey(ThreadLocal* key) { + pthread_key_create(key, 0); +} + +static inline void ThreadLocalSetKey(ThreadLocal key, void* value) { + pthread_setspecific(key, value); +} + +static inline void* ThreadLocalGetValue(ThreadLocal key) { + return pthread_getspecific(key); +} + CXX_GUARD_END #endif diff --git a/include/mgba-util/platform/psp2/threading.h b/include/mgba-util/platform/psp2/threading.h index 36364ac95..96e21e851 100644 --- a/include/mgba-util/platform/psp2/threading.h +++ b/include/mgba-util/platform/psp2/threading.h @@ -17,6 +17,7 @@ typedef struct { } Condition; #define THREAD_ENTRY int typedef THREAD_ENTRY (*ThreadEntry)(void*); +typedef int ThreadLocal; static inline int MutexInit(Mutex* mutex) { Mutex id = sceKernelCreateMutex("mutex", 0, 0, 0); @@ -143,4 +144,19 @@ static inline int ThreadSetName(const char* name) { UNUSED(name); return -1; } + +static inline void ThreadLocalInitKey(ThreadLocal* key) { + static int base = 0x90; + *key = __atomic_fetch_add(&base, 1, __ATOMIC_SEQ_CST); +} + +static inline void ThreadLocalSetKey(ThreadLocal key, void* value) { + void** tls = sceKernelGetTLSAddr(key); + *tls = value; +} + +static inline void* ThreadLocalGetValue(ThreadLocal key) { + void** tls = sceKernelGetTLSAddr(key); + return *tls; +} #endif diff --git a/include/mgba-util/platform/windows/threading.h b/include/mgba-util/platform/windows/threading.h index 8ea73d3c1..d7a7b5532 100644 --- a/include/mgba-util/platform/windows/threading.h +++ b/include/mgba-util/platform/windows/threading.h @@ -16,6 +16,7 @@ typedef THREAD_ENTRY ThreadEntry(LPVOID); typedef HANDLE Thread; typedef CRITICAL_SECTION Mutex; typedef CONDITION_VARIABLE Condition; +typedef DWORD ThreadLocal; static inline int MutexInit(Mutex* mutex) { InitializeCriticalSection(mutex); @@ -88,4 +89,16 @@ static inline int ThreadSetName(const char* name) { return -1; } +static inline void ThreadLocalInitKey(ThreadLocal* key) { + *key = TlsAlloc(); +} + +static inline void ThreadLocalSetKey(ThreadLocal key, void* value) { + TlsSetValue(key, value); +} + +static inline void* ThreadLocalGetValue(ThreadLocal key) { + return TlsGetValue(key); +} + #endif diff --git a/include/mgba-util/threading.h b/include/mgba-util/threading.h index 3a2a4102f..779a533a0 100644 --- a/include/mgba-util/threading.h +++ b/include/mgba-util/threading.h @@ -11,6 +11,12 @@ CXX_GUARD_START #ifndef DISABLE_THREADING +#if __STDC_VERSION__ >= 201112L +#define ThreadLocal _Thread_local void* +#define ThreadLocalInitKey(X) +#define ThreadLocalSetKey(K, V) K = V +#define ThreadLocalGetValue(K) K +#endif #ifdef USE_PTHREADS #include #elif defined(_WIN32) @@ -40,6 +46,7 @@ typedef void* Thread; typedef void* Mutex; #endif typedef void* Condition; +typedef int ThreadLocal; static inline int MutexInit(Mutex* mutex) { UNUSED(mutex); @@ -93,6 +100,20 @@ static inline int ConditionWake(Condition* cond) { UNUSED(cond); return 0; } + +static inline void ThreadLocalInitKey(ThreadLocal* key) { + UNUSED(key); +} + +static inline void ThreadLocalSetKey(ThreadLocal key, void* value) { + UNUSED(key); + UNUSED(value); +} + +static inline void* ThreadLocalGetValue(ThreadLocal key) { + UNUSED(key); + return NULL; +} #endif CXX_GUARD_END diff --git a/src/core/thread.c b/src/core/thread.c index 887b7fa3f..218dc92cf 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -16,23 +16,22 @@ #ifndef DISABLE_THREADING static const float _defaultFPSTarget = 60.f; +static ThreadLocal _contextKey; #ifdef USE_PTHREADS -static pthread_key_t _contextKey; static pthread_once_t _contextOnce = PTHREAD_ONCE_INIT; static void _createTLS(void) { - pthread_key_create(&_contextKey, 0); + ThreadLocalInitKey(&_contextKey); } #elif _WIN32 -static DWORD _contextKey; static INIT_ONCE _contextOnce = INIT_ONCE_STATIC_INIT; static BOOL CALLBACK _createTLS(PINIT_ONCE once, PVOID param, PVOID* context) { UNUSED(once); UNUSED(param); UNUSED(context); - _contextKey = TlsAlloc(); + ThreadLocalInitKey(&_contextKey); return TRUE; } #endif @@ -144,12 +143,11 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { struct mCoreThread* threadContext = context; #ifdef USE_PTHREADS pthread_once(&_contextOnce, _createTLS); - pthread_setspecific(_contextKey, threadContext); #elif _WIN32 InitOnceExecuteOnce(&_contextOnce, _createTLS, NULL, 0); - TlsSetValue(_contextKey, threadContext); #endif + ThreadLocalSetKey(_contextKey, threadContext); ThreadSetName("CPU Thread"); #if !defined(_WIN32) && defined(USE_PTHREADS) @@ -620,21 +618,14 @@ void mCoreThreadStopWaiting(struct mCoreThread* threadContext) { MutexUnlock(&threadContext->impl->stateMutex); } +struct mCoreThread* mCoreThreadGet(void) { #ifdef USE_PTHREADS -struct mCoreThread* mCoreThreadGet(void) { pthread_once(&_contextOnce, _createTLS); - return pthread_getspecific(_contextKey); -} #elif _WIN32 -struct mCoreThread* mCoreThreadGet(void) { InitOnceExecuteOnce(&_contextOnce, _createTLS, NULL, 0); - return TlsGetValue(_contextKey); -} -#else -struct mCoreThread* mCoreThreadGet(void) { - return NULL; -} #endif + return ThreadLocalGetValue(_contextKey); +} static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { UNUSED(logger);