diff options
-rw-r--r-- | Alc/ALc.c | 3 | ||||
-rw-r--r-- | common/threads.c | 97 | ||||
-rw-r--r-- | common/threads.h | 7 | ||||
-rw-r--r-- | router/router.c | 4 |
4 files changed, 53 insertions, 58 deletions
@@ -813,6 +813,7 @@ BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved) break; case DLL_THREAD_DETACH: + althrd_thread_detach(); break; case DLL_PROCESS_DETACH: @@ -1260,6 +1261,8 @@ static void alc_deinit_safe(void) if(LogFile != stderr) fclose(LogFile); LogFile = NULL; + + althrd_deinit(); } static void alc_deinit(void) diff --git a/common/threads.c b/common/threads.c index 88052d7e..2655a244 100644 --- a/common/threads.c +++ b/common/threads.c @@ -64,6 +64,22 @@ extern inline int altss_set(altss_t tss_id, void *val); #include <mmsystem.h> +/* An associative map of uint:void* pairs. The key is the unique Thread ID and + * the value is the thread HANDLE. The thread ID is passed around as the + * althrd_t since there is only one ID per thread, whereas a thread may be + * referenced by multiple different HANDLEs. This map allows retrieving the + * original handle which is needed to join the thread and get its return value. + */ +static UIntMap ThrdIdHandle = UINTMAP_STATIC_INITIALIZE; + +/* An associative map of uint:void* pairs. The key is the TLS index (given by + * TlsAlloc), and the value is the altss_dtor_t callback. When a thread exits, + * we iterate over the TLS indices for their thread-local value and call the + * destructor function with it if they're both not NULL. + */ +static UIntMap TlsDestructors = UINTMAP_STATIC_INITIALIZE; + + void althrd_setname(althrd_t thr, const char *name) { #if defined(_MSC_VER) @@ -94,23 +110,6 @@ void althrd_setname(althrd_t thr, const char *name) } -static UIntMap ThrdIdHandle = UINTMAP_STATIC_INITIALIZE; - -static void NTAPI althrd_callback(void* UNUSED(handle), DWORD reason, void* UNUSED(reserved)) -{ - if(reason == DLL_PROCESS_DETACH) - ResetUIntMap(&ThrdIdHandle); -} -#ifdef _MSC_VER -#pragma section(".CRT$XLC",read) -__declspec(allocate(".CRT$XLC")) PIMAGE_TLS_CALLBACK althrd_callback_ = althrd_callback; -#elif defined(__GNUC__) -PIMAGE_TLS_CALLBACK althrd_callback_ __attribute__((section(".CRT$XLC"))) = althrd_callback; -#else -PIMAGE_TLS_CALLBACK althrd_callback_ = althrd_callback; -#endif - - typedef struct thread_cntr { althrd_start_t func; void *arg; @@ -363,47 +362,6 @@ int alsem_trywait(alsem_t *sem) } -/* An associative map of uint:void* pairs. The key is the TLS index (given by - * TlsAlloc), and the value is the altss_dtor_t callback. When a thread exits, - * we iterate over the TLS indices for their thread-local value and call the - * destructor function with it if they're both not NULL. To avoid using - * DllMain, a PIMAGE_TLS_CALLBACK function pointer is placed in a ".CRT$XLx" - * section (where x is a character A to Z) which will be called by the CRT. - */ -static UIntMap TlsDestructors = UINTMAP_STATIC_INITIALIZE; - -static void NTAPI altss_callback(void* UNUSED(handle), DWORD reason, void* UNUSED(reserved)) -{ - ALsizei i; - - if(reason == DLL_PROCESS_DETACH) - { - ResetUIntMap(&TlsDestructors); - return; - } - if(reason != DLL_THREAD_DETACH) - return; - - LockUIntMapRead(&TlsDestructors); - for(i = 0;i < TlsDestructors.size;i++) - { - void *ptr = altss_get(TlsDestructors.keys[i]); - altss_dtor_t callback = (altss_dtor_t)TlsDestructors.values[i]; - if(ptr && callback) - callback(ptr); - } - UnlockUIntMapRead(&TlsDestructors); -} -#ifdef _MSC_VER -#pragma section(".CRT$XLB",read) -__declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback; -#elif defined(__GNUC__) -PIMAGE_TLS_CALLBACK altss_callback_ __attribute__((section(".CRT$XLB"))) = altss_callback; -#else -#warning "No TLS callback support, thread-local contexts may leak references on poorly written applications." -PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback; -#endif - int altss_create(altss_t *tss_id, altss_dtor_t callback) { DWORD key = TlsAlloc(); @@ -454,6 +412,27 @@ void alcall_once(alonce_flag *once, void (*callback)(void)) InterlockedExchange(once, 2); } + +void althrd_deinit(void) +{ + ResetUIntMap(&ThrdIdHandle); + ResetUIntMap(&TlsDestructors); +} + +void althrd_thread_detach(void) +{ + ALsizei i; + + LockUIntMapRead(&TlsDestructors); + for(i = 0;i < TlsDestructors.size;i++) + { + void *ptr = altss_get(TlsDestructors.keys[i]); + altss_dtor_t callback = (altss_dtor_t)TlsDestructors.values[i]; + if(ptr && callback) callback(ptr); + } + UnlockUIntMapRead(&TlsDestructors); +} + #else #include <sys/time.h> @@ -467,6 +446,8 @@ void alcall_once(alonce_flag *once, void (*callback)(void)) extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem); extern inline void alcall_once(alonce_flag *once, void (*callback)(void)); +extern inline void althrd_deinit(void); +extern inline void althrd_thread_detach(void); void althrd_setname(althrd_t thr, const char *name) { diff --git a/common/threads.h b/common/threads.h index 9a6fe1f7..b0bebd8d 100644 --- a/common/threads.h +++ b/common/threads.h @@ -65,6 +65,9 @@ typedef LONG alonce_flag; int althrd_sleep(const struct timespec *ts, struct timespec *rem); void alcall_once(alonce_flag *once, void (*callback)(void)); +void althrd_deinit(void); +void althrd_thread_detach(void); + inline althrd_t althrd_current(void) { @@ -216,6 +219,10 @@ inline void alcall_once(alonce_flag *once, void (*callback)(void)) pthread_once(once, callback); } + +inline void althrd_deinit(void) { } +inline void althrd_thread_detach(void) { } + #endif diff --git a/router/router.c b/router/router.c index 0497a1d2..a0b554f4 100644 --- a/router/router.c +++ b/router/router.c @@ -64,7 +64,9 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser break; case DLL_THREAD_ATTACH: + break; case DLL_THREAD_DETACH: + althrd_thread_detach(); break; case DLL_PROCESS_DETACH: @@ -84,6 +86,8 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser if(LogFile && LogFile != stderr) fclose(LogFile); LogFile = NULL; + + althrd_deinit(); break; } return TRUE; |