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