1570af302Sopenharmony_ci#include "pthread_impl.h" 2570af302Sopenharmony_ci#include "fork_impl.h" 3570af302Sopenharmony_ci#include "pthread_ffrt.h" 4570af302Sopenharmony_ci#include <stdbool.h> 5570af302Sopenharmony_ci 6570af302Sopenharmony_civolatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX; 7570af302Sopenharmony_civoid *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 }; 8570af302Sopenharmony_ci 9570af302Sopenharmony_cistatic void (*keys[PTHREAD_KEYS_MAX])(void *); 10570af302Sopenharmony_ci 11570af302Sopenharmony_cistatic pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER; 12570af302Sopenharmony_ci 13570af302Sopenharmony_cistatic pthread_key_t next_key; 14570af302Sopenharmony_ci 15570af302Sopenharmony_cistatic void nodtor(void *dummy) 16570af302Sopenharmony_ci{ 17570af302Sopenharmony_ci} 18570af302Sopenharmony_ci 19570af302Sopenharmony_cistatic void dummy_0(void) 20570af302Sopenharmony_ci{ 21570af302Sopenharmony_ci} 22570af302Sopenharmony_ci 23570af302Sopenharmony_ciweak_alias(dummy_0, __tl_lock); 24570af302Sopenharmony_ciweak_alias(dummy_0, __tl_unlock); 25570af302Sopenharmony_ci 26570af302Sopenharmony_civoid __pthread_key_atfork(int who) 27570af302Sopenharmony_ci{ 28570af302Sopenharmony_ci if (who<0) __pthread_rwlock_rdlock(&key_lock); 29570af302Sopenharmony_ci else if (!who) __pthread_rwlock_unlock(&key_lock); 30570af302Sopenharmony_ci else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; 31570af302Sopenharmony_ci} 32570af302Sopenharmony_ci 33570af302Sopenharmony_ciint __pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) 34570af302Sopenharmony_ci{ 35570af302Sopenharmony_ci pthread_t self = __pthread_self(); 36570af302Sopenharmony_ci 37570af302Sopenharmony_ci /* This can only happen in the main thread before 38570af302Sopenharmony_ci * pthread_create has been called. */ 39570af302Sopenharmony_ci if (!self->tsd) self->tsd = __pthread_tsd_main; 40570af302Sopenharmony_ci 41570af302Sopenharmony_ci /* Purely a sentinel value since null means slot is free. */ 42570af302Sopenharmony_ci if (!dtor) dtor = nodtor; 43570af302Sopenharmony_ci 44570af302Sopenharmony_ci __pthread_rwlock_wrlock(&key_lock); 45570af302Sopenharmony_ci pthread_key_t j = next_key; 46570af302Sopenharmony_ci do { 47570af302Sopenharmony_ci if (!keys[j]) { 48570af302Sopenharmony_ci keys[next_key = *k = j] = dtor; 49570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 50570af302Sopenharmony_ci return 0; 51570af302Sopenharmony_ci } 52570af302Sopenharmony_ci } while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key); 53570af302Sopenharmony_ci 54570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 55570af302Sopenharmony_ci return EAGAIN; 56570af302Sopenharmony_ci} 57570af302Sopenharmony_ci 58570af302Sopenharmony_ciint __pthread_key_delete(pthread_key_t k) 59570af302Sopenharmony_ci{ 60570af302Sopenharmony_ci sigset_t set; 61570af302Sopenharmony_ci pthread_t self = __pthread_self(), td=self; 62570af302Sopenharmony_ci 63570af302Sopenharmony_ci __block_app_sigs(&set); 64570af302Sopenharmony_ci __pthread_rwlock_wrlock(&key_lock); 65570af302Sopenharmony_ci 66570af302Sopenharmony_ci __tl_lock(); 67570af302Sopenharmony_ci do td->tsd[k] = 0; 68570af302Sopenharmony_ci while ((td=td->next)!=self); 69570af302Sopenharmony_ci __tl_unlock(); 70570af302Sopenharmony_ci 71570af302Sopenharmony_ci keys[k] = 0; 72570af302Sopenharmony_ci 73570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 74570af302Sopenharmony_ci __restore_sigs(&set); 75570af302Sopenharmony_ci 76570af302Sopenharmony_ci return 0; 77570af302Sopenharmony_ci} 78570af302Sopenharmony_ci 79570af302Sopenharmony_civoid __pthread_tsd_run_dtors() 80570af302Sopenharmony_ci{ 81570af302Sopenharmony_ci pthread_t self = __pthread_self(); 82570af302Sopenharmony_ci int i, j; 83570af302Sopenharmony_ci for (j=0; self->tsd_used && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) { 84570af302Sopenharmony_ci __pthread_rwlock_rdlock(&key_lock); 85570af302Sopenharmony_ci self->tsd_used = 0; 86570af302Sopenharmony_ci for (i=0; i<PTHREAD_KEYS_MAX; i++) { 87570af302Sopenharmony_ci void *val = self->tsd[i]; 88570af302Sopenharmony_ci void (*dtor)(void *) = keys[i]; 89570af302Sopenharmony_ci self->tsd[i] = 0; 90570af302Sopenharmony_ci if (val && dtor && dtor != nodtor) { 91570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 92570af302Sopenharmony_ci dtor(val); 93570af302Sopenharmony_ci __pthread_rwlock_rdlock(&key_lock); 94570af302Sopenharmony_ci } 95570af302Sopenharmony_ci } 96570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 97570af302Sopenharmony_ci } 98570af302Sopenharmony_ci} 99570af302Sopenharmony_ci 100570af302Sopenharmony_civoid __pthread_tsd_run_dtors_ex1() 101570af302Sopenharmony_ci{ 102570af302Sopenharmony_ci pthread_t self = __pthread_self(); 103570af302Sopenharmony_ci int i, j; 104570af302Sopenharmony_ci bool tsd_used = true; 105570af302Sopenharmony_ci for (j=0; tsd_used && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) { 106570af302Sopenharmony_ci __pthread_rwlock_rdlock(&key_lock); 107570af302Sopenharmony_ci tsd_used = false; 108570af302Sopenharmony_ci for (i=0; i<PTHREAD_KEYS_MAX; i++) { 109570af302Sopenharmony_ci void *val = self->tsd[i]; 110570af302Sopenharmony_ci void (*dtor)(void *) = keys[i]; 111570af302Sopenharmony_ci self->tsd[i] = 0; 112570af302Sopenharmony_ci if (val && dtor && dtor != nodtor) { 113570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 114570af302Sopenharmony_ci dtor(val); 115570af302Sopenharmony_ci tsd_used = true; 116570af302Sopenharmony_ci __pthread_rwlock_rdlock(&key_lock); 117570af302Sopenharmony_ci } 118570af302Sopenharmony_ci } 119570af302Sopenharmony_ci __pthread_rwlock_unlock(&key_lock); 120570af302Sopenharmony_ci } 121570af302Sopenharmony_ci} 122570af302Sopenharmony_ci 123570af302Sopenharmony_ciweak_alias(__pthread_key_create, pthread_key_create); 124570af302Sopenharmony_ciweak_alias(__pthread_key_delete, pthread_key_delete); 125570af302Sopenharmony_ciweak_alias(__pthread_tsd_run_dtors_ex1, pthread_tsd_run_dtors);