From 675549474a8ac42e8202d93105182f100c3dec5a Mon Sep 17 00:00:00 2001 From: James Benton Date: Fri, 25 May 2018 18:06:54 +0100 Subject: [PATCH] wutstdc++: Implement gthread keys. --- libraries/wutstdc++/CMakeLists.txt | 1 + libraries/wutstdc++/gthread_keys.cc | 98 +++++++++++++++++++ .../wutstdc++/include/bits/gthr-default.h | 49 +++++----- 3 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 libraries/wutstdc++/gthread_keys.cc diff --git a/libraries/wutstdc++/CMakeLists.txt b/libraries/wutstdc++/CMakeLists.txt index ee9f6fd..0362850 100644 --- a/libraries/wutstdc++/CMakeLists.txt +++ b/libraries/wutstdc++/CMakeLists.txt @@ -3,6 +3,7 @@ project(wutstdc++ CXX) add_library(wutstdc++ thread.cc + gthread_keys.cc include/bits/gthr-default.h) target_compile_definitions(wutstdc++ diff --git a/libraries/wutstdc++/gthread_keys.cc b/libraries/wutstdc++/gthread_keys.cc new file mode 100644 index 0000000..6d654c3 --- /dev/null +++ b/libraries/wutstdc++/gthread_keys.cc @@ -0,0 +1,98 @@ +#include "include/bits/gthr-default.h" + +struct gthread_key +{ + bool in_use; + void (*dtor) (void *); +}; + +static gthread_key key_table[__GTHREAD_MAX_KEYS]; + +static __gthread_mutex_t key_mutex; +static __gthread_once_t init_once_control = __GTHREAD_ONCE_INIT; + +static void init() +{ + __GTHREAD_MUTEX_INIT_FUNCTION(&key_mutex); + memset(key_table, 0, sizeof(key_table)); +} + +int +__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) +{ + int res = EAGAIN; + __gthread_once(&init_once_control, init); + __gthread_mutex_lock(&key_mutex); + + for (int i = 0; i < __GTHREAD_MAX_KEYS; ++i) { + if (key_table[i].in_use) { + continue; + } + + key_table[i].in_use = 1; + key_table[i].dtor = __dtor; + + res = 0; + *__key = (__gthread_key_t)i; + break; + } + + __gthread_mutex_unlock(&key_mutex); + return res; +} + +int +__gthread_key_delete (__gthread_key_t __key) +{ + __gthread_mutex_lock(&key_mutex); + key_table[__key].in_use = 0; + key_table[__key].dtor = NULL; + __gthread_mutex_unlock(&key_mutex); + return -1; +} + +static const void ** +__gthread_get_thread_keys() +{ + const void **keys = (const void **)OSGetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID); + if (!keys) { + MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); + keys = (const void **)MEMAllocFromExpHeapEx(heap, sizeof(void *) * sizeof(__GTHREAD_MAX_KEYS), 4); + memset(keys, 0, sizeof(void *) * sizeof(__GTHREAD_MAX_KEYS)); + OSSetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID, keys); + } + + return keys; +} + +void * +__gthread_getspecific (__gthread_key_t __key) +{ + return (void *)__gthread_get_thread_keys()[__key]; +} + +int +__gthread_setspecific (__gthread_key_t __key, const void *__ptr) +{ + __gthread_get_thread_keys()[__key] = __ptr; + return 0; +} + +void +__gthread_key_cleanup (OSThread *thread) +{ + void **keys = (void **)OSGetThreadSpecific(__GTHREAD_THREAD_SPECIFIC_ID); + if (!keys) { + return; + } + + __gthread_mutex_lock(&key_mutex); + + for (int i = 0; i < __GTHREAD_MAX_KEYS; ++i) { + if (key_table[i].in_use && key_table[i].dtor && keys[i]) { + key_table[i].dtor(keys[i]); + } + } + + __gthread_mutex_unlock(&key_mutex); +} diff --git a/libraries/wutstdc++/include/bits/gthr-default.h b/libraries/wutstdc++/include/bits/gthr-default.h index 8b83b80..737dad7 100644 --- a/libraries/wutstdc++/include/bits/gthr-default.h +++ b/libraries/wutstdc++/include/bits/gthr-default.h @@ -47,11 +47,10 @@ typedef OSMutex __gthread_mutex_t; typedef OSMutex __gthread_recursive_mutex_t; typedef OSCondition __gthread_cond_t; typedef struct timespec __gthread_time_t; - -// Unimplemented -typedef void *__gthread_key_t; +typedef uint32_t __gthread_key_t; #define __GTHREAD_HAS_COND 1 +#define __GTHREAD_MAX_KEYS (128) #define __GTHREAD_ONCE_VALUE_INIT (0) #define __GTHREAD_ONCE_VALUE_STARTED (1) @@ -65,6 +64,8 @@ typedef void *__gthread_key_t; #define __GTHREAD_STACK_SIZE (4096*1024) +#define __GTHREAD_THREAD_SPECIFIC_ID (0) + static inline int __gthread_active_p (void) { @@ -79,6 +80,15 @@ __gthread_thread_deallocator(OSThread *thread, void *stack) MEMFreeToExpHeap(heap, stack); } +void +__gthread_key_cleanup (OSThread *thread); + +static inline void +__gthread_thread_cleanup(OSThread *thread, void *stack) +{ + __gthread_key_cleanup(thread); +} + static inline int __gthread_create (__gthread_t *__threadid, void *(*__func) (void*), void *__args) @@ -102,6 +112,7 @@ __gthread_create (__gthread_t *__threadid, void *(*__func) (void*), *__threadid = thread; OSSetThreadDeallocator(thread, &__gthread_thread_deallocator); + OSSetThreadCleanupCallback(thread, &__gthread_thread_cleanup); OSResumeThread(thread); return 0; } @@ -163,33 +174,17 @@ __gthread_once (__gthread_once_t *__once, void (*__func) (void)) return 0; } -static inline int -__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) -{ - // TODO: Implement __gthread_key_create - return -1; -} +int +__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)); -static inline int -__gthread_key_delete (__gthread_key_t __key) -{ - // TODO: Implement __gthread_key_delete - return -1; -} +int +__gthread_key_delete (__gthread_key_t __key); -static inline void * -__gthread_getspecific (__gthread_key_t __key) -{ - // TODO: Implement __gthread_getspecific - return NULL; -} +void * +__gthread_getspecific (__gthread_key_t __key); -static inline int -__gthread_setspecific (__gthread_key_t __key, const void *__ptr) -{ - // TODO: Implement __gthread_setspecific - return -1; -} +int +__gthread_setspecific (__gthread_key_t __key, const void *__ptr); static inline void __gthread_mutex_init_function (__gthread_mutex_t *__mutex)