Util: Refactor TLS out of platform-specific APIs

This commit is contained in:
Vicki Pfau 2020-07-12 16:57:09 -07:00
parent d02e8a2a87
commit 51c3fca3bf
6 changed files with 71 additions and 17 deletions

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <mgba-util/platform/posix/threading.h>
#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

View File

@ -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);