d112094122b316d161a6fd17f1c08d12d0b58e05
[musl] / src / thread / pthread_key_create.c
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
12 static void nodtor(void *dummy)
13 {
14 }
15
16 static void dummy_0(void)
17 {
18 }
19
20 weak_alias(dummy_0, __tl_lock);
21 weak_alias(dummy_0, __tl_unlock);
22
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
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
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);