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 (*volatile keys[PTHREAD_KEYS_MAX])(void *);
|
---|
7 |
|
---|
8 | static void nodtor(void *dummy)
|
---|
9 | {
|
---|
10 | }
|
---|
11 |
|
---|
12 | int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
|
---|
13 | {
|
---|
14 | unsigned i = (uintptr_t)&k / 16 % PTHREAD_KEYS_MAX;
|
---|
15 | unsigned j = i;
|
---|
16 | pthread_t self = __pthread_self();
|
---|
17 |
|
---|
18 | /* This can only happen in the main thread before
|
---|
19 | * pthread_create has been called. */
|
---|
20 | if (!self->tsd) self->tsd = __pthread_tsd_main;
|
---|
21 |
|
---|
22 | if (!dtor) dtor = nodtor;
|
---|
23 | do {
|
---|
24 | if (!a_cas_p(keys+j, 0, (void *)dtor)) {
|
---|
25 | *k = j;
|
---|
26 | return 0;
|
---|
27 | }
|
---|
28 | } while ((j=(j+1)%PTHREAD_KEYS_MAX) != i);
|
---|
29 | return EAGAIN;
|
---|
30 | }
|
---|
31 |
|
---|
32 | int __pthread_key_delete(pthread_key_t k)
|
---|
33 | {
|
---|
34 | keys[k] = 0;
|
---|
35 | return 0;
|
---|
36 | }
|
---|
37 |
|
---|
38 | void __pthread_tsd_run_dtors()
|
---|
39 | {
|
---|
40 | pthread_t self = __pthread_self();
|
---|
41 | int i, j, not_finished = self->tsd_used;
|
---|
42 | for (j=0; not_finished && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) {
|
---|
43 | not_finished = 0;
|
---|
44 | for (i=0; i<PTHREAD_KEYS_MAX; i++) {
|
---|
45 | if (self->tsd[i] && keys[i]) {
|
---|
46 | void *tmp = self->tsd[i];
|
---|
47 | self->tsd[i] = 0;
|
---|
48 | keys[i](tmp);
|
---|
49 | not_finished = 1;
|
---|
50 | }
|
---|
51 | }
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | weak_alias(__pthread_key_delete, pthread_key_delete);
|
---|
56 | weak_alias(__pthread_key_create, pthread_key_create);
|
---|