xref: /aosp_15_r20/external/musl/src/thread/pthread_key_create.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
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)13 static void nodtor(void *dummy)
14 {
15 }
16 
dummy_0(void)17 static 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)24 void __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 *))31 int __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)56 int __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()77 void __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