]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
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 | ||
f41256b6 | 16 | static void dummy_0(void) |
320054e8 DG |
17 | { |
18 | } | |
19 | ||
f41256b6 DG |
20 | weak_alias(dummy_0, __tl_lock); |
21 | weak_alias(dummy_0, __tl_unlock); | |
320054e8 DG |
22 | |
23 | int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) | |
24 | { | |
320054e8 | 25 | pthread_t self = __pthread_self(); |
320054e8 DG |
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 | ||
f41256b6 DG |
34 | __pthread_rwlock_wrlock(&key_lock); |
35 | pthread_key_t j = next_key; | |
320054e8 DG |
36 | do { |
37 | if (!keys[j]) { | |
38 | keys[next_key = *k = j] = dtor; | |
f41256b6 | 39 | __pthread_rwlock_unlock(&key_lock); |
320054e8 | 40 | return 0; |
320054e8 DG |
41 | } |
42 | } while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key); | |
43 | ||
f41256b6 DG |
44 | __pthread_rwlock_unlock(&key_lock); |
45 | return EAGAIN; | |
320054e8 DG |
46 | } |
47 | ||
f41256b6 | 48 | int __pthread_key_delete(pthread_key_t k) |
320054e8 | 49 | { |
f41256b6 DG |
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 | ||
320054e8 DG |
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++) { | |
f41256b6 | 74 | __pthread_rwlock_rdlock(&key_lock); |
320054e8 DG |
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; | |
f41256b6 DG |
80 | if (val && dtor && dtor != nodtor) { |
81 | __pthread_rwlock_unlock(&key_lock); | |
320054e8 | 82 | dtor(val); |
f41256b6 | 83 | __pthread_rwlock_rdlock(&key_lock); |
320054e8 DG |
84 | } |
85 | } | |
f41256b6 | 86 | __pthread_rwlock_unlock(&key_lock); |
320054e8 DG |
87 | } |
88 | } | |
89 | ||
90 | weak_alias(__pthread_key_create, pthread_key_create); | |
f41256b6 | 91 | weak_alias(__pthread_key_delete, pthread_key_delete); |