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