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