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