[352] | 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);
|
---|