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