1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <aos/errno.h>
8
9 #include "internal/pthread.h"
10
11 typedef struct key_value {
12 pthread_t thread;
13 const uint32_t *value;
14 } key_value_t;
15
16 typedef struct pthread_key_value {
17 key_value_t key_value;
18
19 struct pthread_key_value *next;
20 } pthread_key_value_t;
21
22 typedef struct pthread_key_value_head {
23 void (*fun)(void *);
24
25 pthread_key_value_t *next;
26 } pthread_key_value_head_t;
27
28 typedef struct pthread_key_list_s {
29 pthread_key_t key_num;
30 pthread_key_value_head_t head;
31
32 struct pthread_key_list_s *next;
33 } pthread_key_list_t;
34
35 pthread_key_list_t pthread_key_list_head;
36 pthread_mutex_t g_pthread_key_lock = PTHREAD_MUTEX_INITIALIZER;
37
pthread_tsd_dtors(void)38 void pthread_tsd_dtors(void)
39 {
40 pthread_key_list_t *pthread_key_list_s_c = NULL;
41 pthread_key_value_t **key_value_s_prev = NULL;
42 pthread_key_value_t *key_value_s_cur = NULL;
43 pthread_key_value_t *key_value_s_del = NULL;
44
45 pthread_mutex_lock(&g_pthread_key_lock);
46 pthread_key_list_s_c = &pthread_key_list_head;
47 while (pthread_key_list_s_c != NULL) {
48 key_value_s_cur = pthread_key_list_s_c->head.next;
49 if (key_value_s_cur == NULL) {
50 pthread_key_list_s_c = pthread_key_list_s_c->next;
51 continue;
52 }
53
54 key_value_s_prev = &pthread_key_list_s_c->head.next;
55
56 while (key_value_s_cur != NULL) {
57 if (key_value_s_cur->key_value.thread == pthread_self()) {
58 if (pthread_key_list_s_c->head.fun != NULL) {
59 pthread_key_list_s_c->head.fun((void *)key_value_s_cur->key_value.value);
60 }
61
62 key_value_s_del = key_value_s_cur;
63 *key_value_s_prev = key_value_s_cur->next;
64 key_value_s_cur = key_value_s_cur->next;
65 free(key_value_s_del);
66 continue;
67 }
68
69 key_value_s_prev = &key_value_s_cur->next;
70 key_value_s_cur = key_value_s_cur->next;
71 }
72 pthread_key_list_s_c = pthread_key_list_s_c->next;
73 }
74
75 pthread_mutex_unlock(&g_pthread_key_lock);
76 }
77
78
pthread_key_create(pthread_key_t * key,void (* destructor)(void *))79 int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
80 {
81 pthread_key_list_t *pthread_key_list_s_c = NULL;
82 pthread_key_list_t *pthread_key_list_s_l = NULL;
83
84 if (key == NULL) {
85 return EINVAL;
86 }
87
88 pthread_mutex_lock(&g_pthread_key_lock);
89
90 /* if the key list is empty int pthread_key_list_head to save the first key */
91 if (pthread_key_list_head.key_num == 0) {
92 pthread_key_list_head.key_num = 1;
93 pthread_key_list_head.head.fun = destructor;
94 *key = pthread_key_list_head.key_num;
95 } else {
96 /* if the key list is not empty find the last key and add key */
97 /* find the last key */
98 pthread_key_list_s_c = pthread_key_list_head.next;
99 pthread_key_list_s_l = &pthread_key_list_head;
100 while (pthread_key_list_s_c != NULL) {
101 pthread_key_list_s_l = pthread_key_list_s_c;
102 pthread_key_list_s_c = pthread_key_list_s_c->next;
103 }
104
105 /* malloc the new key */
106 pthread_key_list_s_c = (pthread_key_list_t *)malloc(sizeof(pthread_key_list_t));
107 if (pthread_key_list_s_c == NULL) {
108 pthread_mutex_unlock(&g_pthread_key_lock);
109 return -1;
110 }
111
112 /* init the new key */
113 memset(pthread_key_list_s_c, 0, sizeof(pthread_key_list_t));
114
115 /* insert the key to the end of list */
116 pthread_key_list_s_c->key_num = pthread_key_list_s_l->key_num + 1;
117 pthread_key_list_s_c->head.fun = destructor;
118 pthread_key_list_s_l->next = pthread_key_list_s_c;
119
120 /* update the key value */
121 *key = pthread_key_list_s_c->key_num;
122 }
123
124 pthread_mutex_unlock(&g_pthread_key_lock);
125
126 return 0;
127 }
128
pthread_setspecific(pthread_key_t key,const void * value)129 int pthread_setspecific(pthread_key_t key, const void *value)
130 {
131 pthread_key_list_t *pthread_key_list_s_c = NULL;
132 pthread_key_value_t *key_value_s_o = NULL;
133 pthread_key_value_t *key_value_s = NULL;
134 pthread_key_value_t *key_value_s_c = NULL;
135 pthread_key_value_t *key_value_s_l = NULL;
136 int list_flag = 0;
137 int value_flag = 0;
138 pthread_t self = pthread_self();
139
140 pthread_mutex_lock(&g_pthread_key_lock);
141
142 /* find the key in list */
143 pthread_key_list_s_c = &pthread_key_list_head;
144 while (pthread_key_list_s_c != NULL) {
145 if (pthread_key_list_s_c->key_num == key){
146 list_flag = 1;
147 key_value_s_o = pthread_key_list_s_c->head.next;
148 break;
149 }
150
151 pthread_key_list_s_c = pthread_key_list_s_c->next;
152 }
153
154 /* if can not find the key in list, return error */
155 if (list_flag == 0) {
156 pthread_mutex_unlock(&g_pthread_key_lock);
157 return EINVAL;
158 }
159
160 /* if no value store in the key, create new pthread_key_value_t to save the value */
161 if (key_value_s_o == NULL) {
162 key_value_s = (pthread_key_value_t *)malloc(sizeof(pthread_key_value_t));
163 if (key_value_s == NULL) {
164 pthread_mutex_unlock(&g_pthread_key_lock);;
165 return ENOMEM;
166 }
167
168 memset(key_value_s, 0, sizeof(pthread_key_value_t));
169
170 /* save the thread id and value */
171 key_value_s->key_value.value = (uint32_t*)value;
172 key_value_s->key_value.thread = self;
173 key_value_s->next = NULL;
174
175 /* and pthread_key_value_t to value list */
176 pthread_key_list_s_c->head.next = key_value_s;
177 } else {
178 /* if value store in the key, find the last value and add the new value */
179 /* sreach the value list to find if same thread had save the value */
180 key_value_s_c = key_value_s_o;
181 while (key_value_s_c != NULL) {
182 /* if the same thread had save the value update the value */
183 if (key_value_s_c->key_value.thread == self) {
184 key_value_s_c->key_value.value = (uint32_t*)value;
185 value_flag = 1;
186
187 break;
188 }
189
190 key_value_s_l = key_value_s_c;
191 key_value_s_c = key_value_s_c->next;
192 }
193
194 /* if no same thread had save the value before create new pthread_key_value_t */
195 if (value_flag == 0) {
196 key_value_s = (pthread_key_value_t *)malloc(sizeof(pthread_key_value_t));
197 if (key_value_s == NULL) {
198 pthread_mutex_unlock(&g_pthread_key_lock);;
199 return ENOMEM;
200 }
201
202 memset(key_value_s, 0, sizeof(pthread_key_value_t));
203
204 /* save current value to pthread_key_value_t */
205 key_value_s->next = key_value_s_l->next;
206 key_value_s->key_value.value = (uint32_t*)value;
207 key_value_s->key_value.thread = self;
208
209 /* add the value to the list */
210 key_value_s_l->next = key_value_s;
211 }
212 }
213
214 pthread_mutex_unlock(&g_pthread_key_lock);
215
216 return 0;
217 }
218
pthread_getspecific(pthread_key_t key)219 void *pthread_getspecific(pthread_key_t key)
220 {
221 pthread_key_list_t *pthread_key_list_s_c = NULL;
222 pthread_key_value_t *key_value_s_o = NULL;
223 pthread_key_value_t *key_value_s_c = NULL;
224 int list_flag = 0;
225
226 pthread_mutex_lock(&g_pthread_key_lock);
227
228 /* find the key in list */
229 pthread_key_list_s_c = &pthread_key_list_head;
230 while (pthread_key_list_s_c != NULL) {
231 if (pthread_key_list_s_c->key_num == key){
232 list_flag = 1;
233 key_value_s_o = pthread_key_list_s_c->head.next;
234 break;
235 }
236
237 pthread_key_list_s_c = pthread_key_list_s_c->next;
238 }
239
240 /* if can not find the key in list, or no value store in the key, return NULL */
241 if ((list_flag == 0) || (key_value_s_o == NULL)) {
242 pthread_mutex_unlock(&g_pthread_key_lock);
243 return NULL;
244 }
245
246 /* search the value list to find the value current thread saved */
247 key_value_s_c = key_value_s_o;
248 while (key_value_s_c != NULL) {
249 if (key_value_s_c->key_value.thread == pthread_self()) {
250 pthread_mutex_unlock(&g_pthread_key_lock);
251 return (void *)key_value_s_c->key_value.value;
252 }
253
254 key_value_s_c = key_value_s_c->next;
255 }
256
257 /* if can not find the value current thread saved return NULL */
258 pthread_mutex_unlock(&g_pthread_key_lock);
259 return NULL;
260 }
261
pthread_key_delete(pthread_key_t key)262 int pthread_key_delete(pthread_key_t key)
263 {
264 pthread_key_list_t *pthread_key_list_s_c = NULL;
265 pthread_key_list_t *pthread_key_list_s_l = NULL;
266 pthread_key_value_t *key_value_s_o = NULL;
267 pthread_key_value_t *key_value_s_c = NULL;
268 pthread_key_value_t *key_value_s_n = NULL;
269
270 int list_flag = 0;
271
272 pthread_mutex_lock(&g_pthread_key_lock);
273
274 /* if key saved in pthread_key_list_head */
275 if (pthread_key_list_head.key_num == key) {
276 key_value_s_c = pthread_key_list_head.head.next;
277
278 /* free the value saved in the key */
279 while (key_value_s_c != NULL) {
280 key_value_s_n = key_value_s_c->next;
281 free(key_value_s_c);
282 key_value_s_c = key_value_s_n;
283 }
284
285 /* set the list pointer to NULL */
286 pthread_key_list_head.head.next = NULL;
287
288 /* if no other key save in the list set key_num to 0 */
289 if (pthread_key_list_head.next == NULL) {
290 pthread_key_list_head.key_num = 0;
291 }
292 else /* else copy the next key to the head */
293 {
294 pthread_key_list_s_c = pthread_key_list_head.next;
295 pthread_key_list_head.key_num = pthread_key_list_head.next->key_num;
296 memcpy(&pthread_key_list_head.head, &pthread_key_list_head.next->head,
297 sizeof(pthread_key_value_head_t));
298 pthread_key_list_head.next = pthread_key_list_head.next->next;
299
300 free(pthread_key_list_s_c);
301 }
302 }
303 else /* if key is not saved in pthread_key_list_head, find the key in the list */
304 {
305 /* find the key in the list */
306 pthread_key_list_s_c = pthread_key_list_head.next;
307 while (pthread_key_list_s_c != NULL) {
308 if (pthread_key_list_s_c->key_num == key){
309 key_value_s_o = pthread_key_list_s_c->head.next;
310
311 if (pthread_key_list_s_l == NULL) {
312 pthread_key_list_head.next = pthread_key_list_s_c->next;
313 } else {
314 pthread_key_list_s_l->next = pthread_key_list_s_c->next;
315 }
316
317 free(pthread_key_list_s_c);
318
319 list_flag = 1;
320 break;
321 }
322
323 pthread_key_list_s_l = pthread_key_list_s_c;
324 pthread_key_list_s_c = pthread_key_list_s_c->next;
325 }
326
327 /* if can not find the key in list return error */
328 if (list_flag == 0) {
329 pthread_mutex_unlock(&g_pthread_key_lock);
330 return EINVAL;
331 }
332
333 /* if no value saved in the key return */
334 if (key_value_s_o == NULL) {
335 pthread_mutex_unlock(&g_pthread_key_lock);
336 return 0;
337 }
338
339 key_value_s_c = key_value_s_o;
340 while (key_value_s_c != NULL) {
341 key_value_s_n = key_value_s_c->next;
342 free(key_value_s_c);
343 key_value_s_c = key_value_s_n;
344 }
345 }
346
347 pthread_mutex_unlock(&g_pthread_key_lock);
348 return 0;
349 }
350