From 615553be5febf2392c7bc24fc96b12065be562bb Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 7 Dec 2019 15:19:56 +0100 Subject: [PATCH] LibPthread: Implement simple thread-specific keys This patch adds pthread_key_create() and pthread_{get,set}specific(). There's a maximum of 64 thread-specific keys for simplicity. Key destructors are not invoked on thread exit. --- Libraries/LibC/sys/types.h | 2 +- Libraries/LibPthread/pthread.cpp | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Libraries/LibC/sys/types.h b/Libraries/LibC/sys/types.h index 2066f23dfc..c331cf7a16 100644 --- a/Libraries/LibC/sys/types.h +++ b/Libraries/LibC/sys/types.h @@ -61,7 +61,7 @@ struct utimbuf { }; typedef int pthread_t; -typedef void* pthread_key_t; +typedef int pthread_key_t; typedef void* pthread_once_t; typedef uint32_t pthread_mutex_t; typedef void* pthread_attr_t; diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp index 061d19f427..d9845f1478 100644 --- a/Libraries/LibPthread/pthread.cpp +++ b/Libraries/LibPthread/pthread.cpp @@ -465,4 +465,58 @@ int pthread_cond_broadcast(pthread_cond_t* cond) } return 0; } + +static const int max_keys = 64; + +typedef void (*KeyDestructor)(void*); + +struct KeyTable { + // FIXME: Invoke key destructors on thread exit! + KeyDestructor destructors[64] { nullptr }; + int next { 0 }; + pthread_mutex_t mutex { PTHREAD_MUTEX_INITIALIZER }; +}; + +struct SpecificTable { + void* values[64] { nullptr }; +}; + +static KeyTable s_keys; + +__thread SpecificTable t_specifics; + +int pthread_key_create(pthread_key_t* key, KeyDestructor destructor) +{ + int ret = 0; + pthread_mutex_lock(&s_keys.mutex); + if (s_keys.next >= max_keys) { + ret = ENOMEM; + } else { + *key = s_keys.next++; + s_keys.destructors[*key] = destructor; + ret = 0; + } + pthread_mutex_unlock(&s_keys.mutex); + return ret; +} + +void* pthread_getspecific(pthread_key_t key) +{ + if (key < 0) + return nullptr; + if (key >= max_keys) + return nullptr; + return t_specifics.values[key]; +} + +int pthread_setspecific(pthread_key_t key, const void* value) +{ + if (key < 0) + return EINVAL; + if (key >= max_keys) + return EINVAL; + + t_specifics.values[key] = const_cast(value); + return 0; +} }