1 #include "pthread_impl.h" 2 #include "fork_impl.h" 3 4 volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX; 5 void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 }; 6 7 static void (*keys[PTHREAD_KEYS_MAX])(void *); 8 9 static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER; 10 11 static pthread_key_t next_key; 12 nodtor(void * dummy)13static void nodtor(void *dummy) 14 { 15 } 16 dummy_0(void)17static void dummy_0(void) 18 { 19 } 20 21 weak_alias(dummy_0, __tl_lock); 22 weak_alias(dummy_0, __tl_unlock); 23 __pthread_key_atfork(int who)24void __pthread_key_atfork(int who) 25 { 26 if (who<0) __pthread_rwlock_rdlock(&key_lock); 27 else if (!who) __pthread_rwlock_unlock(&key_lock); 28 else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; 29 } 30 __pthread_key_create(pthread_key_t * k,void (* dtor)(void *))31int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) 32 { 33 pthread_t self = __pthread_self(); 34 35 /* This can only happen in the main thread before 36 * pthread_create has been called. */ 37 if (!self->tsd) self->tsd = __pthread_tsd_main; 38 39 /* Purely a sentinel value since null means slot is free. */ 40 if (!dtor) dtor = nodtor; 41 42 __pthread_rwlock_wrlock(&key_lock); 43 pthread_key_t j = next_key; 44 do { 45 if (!keys[j]) { 46 keys[next_key = *k = j] = dtor; 47 __pthread_rwlock_unlock(&key_lock); 48 return 0; 49 } 50 } while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key); 51 52 __pthread_rwlock_unlock(&key_lock); 53 return EAGAIN; 54 } 55 __pthread_key_delete(pthread_key_t k)56int __pthread_key_delete(pthread_key_t k) 57 { 58 sigset_t set; 59 pthread_t self = __pthread_self(), td=self; 60 61 __block_app_sigs(&set); 62 __pthread_rwlock_wrlock(&key_lock); 63 64 __tl_lock(); 65 do td->tsd[k] = 0; 66 while ((td=td->next)!=self); 67 __tl_unlock(); 68 69 keys[k] = 0; 70 71 __pthread_rwlock_unlock(&key_lock); 72 __restore_sigs(&set); 73 74 return 0; 75 } 76 __pthread_tsd_run_dtors()77void __pthread_tsd_run_dtors() 78 { 79 pthread_t self = __pthread_self(); 80 int i, j; 81 for (j=0; self->tsd_used && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) { 82 __pthread_rwlock_rdlock(&key_lock); 83 self->tsd_used = 0; 84 for (i=0; i<PTHREAD_KEYS_MAX; i++) { 85 void *val = self->tsd[i]; 86 void (*dtor)(void *) = keys[i]; 87 self->tsd[i] = 0; 88 if (val && dtor && dtor != nodtor) { 89 __pthread_rwlock_unlock(&key_lock); 90 dtor(val); 91 __pthread_rwlock_rdlock(&key_lock); 92 } 93 } 94 __pthread_rwlock_unlock(&key_lock); 95 } 96 } 97 98 weak_alias(__pthread_key_create, pthread_key_create); 99 weak_alias(__pthread_key_delete, pthread_key_delete); 100