From 4abab5ad6c8465a7528ccdd5f49367da05f78bbd Mon Sep 17 00:00:00 2001 From: Vladimir Azarov Date: Tue, 1 Oct 2024 15:47:05 +0200 Subject: Initial version --- src/thread/pthread_key_create.c | 99 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/thread/pthread_key_create.c (limited to 'src/thread/pthread_key_create.c') diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c new file mode 100644 index 0000000..39770c7 --- /dev/null +++ b/src/thread/pthread_key_create.c @@ -0,0 +1,99 @@ +#include "pthread_impl.h" +#include "fork_impl.h" + +volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX; +void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 }; + +static void (*keys[PTHREAD_KEYS_MAX])(void *); + +static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER; + +static pthread_key_t next_key; + +static void nodtor(void *dummy) +{ +} + +static void dummy_0(void) +{ +} + +weak_alias(dummy_0, __tl_lock); +weak_alias(dummy_0, __tl_unlock); + +void __pthread_key_atfork(int who) +{ + if (who<0) __pthread_rwlock_rdlock(&key_lock); + else if (!who) __pthread_rwlock_unlock(&key_lock); + else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; +} + +int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) +{ + pthread_t self = __pthread_self(); + + /* This can only happen in the main thread before + * pthread_create has been called. */ + if (!self->tsd) self->tsd = __pthread_tsd_main; + + /* Purely a sentinel value since null means slot is free. */ + if (!dtor) dtor = nodtor; + + __pthread_rwlock_wrlock(&key_lock); + pthread_key_t j = next_key; + do { + if (!keys[j]) { + keys[next_key = *k = j] = dtor; + __pthread_rwlock_unlock(&key_lock); + return 0; + } + } while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key); + + __pthread_rwlock_unlock(&key_lock); + return EAGAIN; +} + +int __pthread_key_delete(pthread_key_t k) +{ + sigset_t set; + pthread_t self = __pthread_self(), td=self; + + __block_app_sigs(&set); + __pthread_rwlock_wrlock(&key_lock); + + __tl_lock(); + do td->tsd[k] = 0; + while ((td=td->next)!=self); + __tl_unlock(); + + keys[k] = 0; + + __pthread_rwlock_unlock(&key_lock); + __restore_sigs(&set); + + return 0; +} + +void __pthread_tsd_run_dtors() +{ + pthread_t self = __pthread_self(); + int i, j; + for (j=0; self->tsd_used && jtsd_used = 0; + for (i=0; itsd[i]; + void (*dtor)(void *) = keys[i]; + self->tsd[i] = 0; + if (val && dtor && dtor != nodtor) { + __pthread_rwlock_unlock(&key_lock); + dtor(val); + __pthread_rwlock_rdlock(&key_lock); + } + } + __pthread_rwlock_unlock(&key_lock); + } +} + +weak_alias(__pthread_key_create, pthread_key_create); +weak_alias(__pthread_key_delete, pthread_key_delete); -- cgit v1.2.3