1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
33
38
39
40
41
42
43
44
45
50
51
52
53
54
55
56
57
58
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
87
88
89
90
91
92
93
96
97
98
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
136
137
138
139
140
141
142
145
146
147
148
149
150
153
154
155
156
157
158
161
162
163
164
168
169
170
171
172
182
183
184
185
186
189
190
191
194
195
196
197
198
199
200
203
204
205
206
207
210
211
212
213
217
218
219
220
221
231
232
235
236
237
238
239
240
241
242
243
244
245
248
253
254
255
256
257
258
259
/* ... */
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sys/lock.h"
#include "sys/queue.h"
#include "pthread_internal.h"10 includes
#if (CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS < 1)
#error "CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS cannot be 0 for pthread TLS"
#endif
#define PTHREAD_TLS_INDEX 0
typedef void (*pthread_destructor_t)(void*);
/* ... */
typedef struct key_entry_t_ {
pthread_key_t key;
pthread_destructor_t destructor;
SLIST_ENTRY(key_entry_t_) next;
}{ ... } key_entry_t;
SLIST_HEAD(key_list_t, key_entry_t_) s_keys = SLIST_HEAD_INITIALIZER(s_keys);
static portMUX_TYPE s_keys_lock = portMUX_INITIALIZER_UNLOCKED;
typedef struct value_entry_t_ {
pthread_key_t key;
void *value;
SLIST_ENTRY(value_entry_t_) next;
}{ ... } value_entry_t;
SLIST_HEAD(values_list_t_, value_entry_t_);
typedef struct values_list_t_ values_list_t;
int pthread_key_create(pthread_key_t *key, pthread_destructor_t destructor)
{
key_entry_t *new_key = malloc(sizeof(key_entry_t));
if (new_key == NULL) {
return ENOMEM;
}{...}
portENTER_CRITICAL(&s_keys_lock);
const key_entry_t *head = SLIST_FIRST(&s_keys);
new_key->key = (head == NULL) ? 1 : (head->key + 1);
new_key->destructor = destructor;
*key = new_key->key;
SLIST_INSERT_HEAD(&s_keys, new_key, next);
portEXIT_CRITICAL(&s_keys_lock);
return 0;
}{ ... }
static key_entry_t *find_key(pthread_key_t key)
{
portENTER_CRITICAL(&s_keys_lock);
key_entry_t *result = NULL;;
SLIST_FOREACH(result, &s_keys, next) {
if (result->key == key) {
break;
}{...}
}{...}
portEXIT_CRITICAL(&s_keys_lock);
return result;
}{ ... }
int pthread_key_delete(pthread_key_t key)
{
portENTER_CRITICAL(&s_keys_lock);
/* ... */
key_entry_t *entry = find_key(key);
if (entry != NULL) {
SLIST_REMOVE(&s_keys, entry, key_entry_t_, next);
free(entry);
}{...}
portEXIT_CRITICAL(&s_keys_lock);
return 0;
}{ ... }
/* ... */
static void pthread_cleanup_thread_specific_data_callback(int index, void *v_tls)
{
values_list_t *tls = (values_list_t *)v_tls;
assert(tls != NULL);
while (1) {
value_entry_t *entry = SLIST_FIRST(tls);
if (entry == NULL) {
break;
}{...}
SLIST_REMOVE_HEAD(tls, next);
key_entry_t *key = find_key(entry->key);
if (key != NULL && key->destructor != NULL) {
key->destructor(entry->value);
}{...}
free(entry);
}{...}
free(tls);
}{ ... }
/* ... */
void pthread_internal_local_storage_destructor_callback(TaskHandle_t handle)
{
void *tls = pvTaskGetThreadLocalStoragePointer(handle, PTHREAD_TLS_INDEX);
if (tls != NULL) {
pthread_cleanup_thread_specific_data_callback(PTHREAD_TLS_INDEX, tls);
/* ... */
#if !defined(CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS)
vTaskSetThreadLocalStoragePointer(handle, PTHREAD_TLS_INDEX, NULL);
#else
vTaskSetThreadLocalStoragePointerAndDelCallback(handle,
PTHREAD_TLS_INDEX,
NULL,
NULL);/* ... */
#endif
}{...}
}{ ... }
static value_entry_t *find_value(const values_list_t *list, pthread_key_t key)
{
value_entry_t *result = NULL;;
SLIST_FOREACH(result, list, next) {
if (result->key == key) {
break;
}{...}
}{...}
return result;
}{ ... }
void *pthread_getspecific(pthread_key_t key)
{
values_list_t *tls = (values_list_t *) pvTaskGetThreadLocalStoragePointer(NULL, PTHREAD_TLS_INDEX);
if (tls == NULL) {
return NULL;
}{...}
value_entry_t *entry = find_value(tls, key);
if (entry != NULL) {
return entry->value;
}{...}
return NULL;
}{ ... }
int pthread_setspecific(pthread_key_t key, const void *value)
{
key_entry_t *key_entry = find_key(key);
if (key_entry == NULL) {
return ENOENT;
}{...}
values_list_t *tls = pvTaskGetThreadLocalStoragePointer(NULL, PTHREAD_TLS_INDEX);
if (tls == NULL) {
tls = calloc(1, sizeof(values_list_t));
if (tls == NULL) {
return ENOMEM;
}{...}
#if !defined(CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS)
vTaskSetThreadLocalStoragePointer(NULL, PTHREAD_TLS_INDEX, tls);
#else
vTaskSetThreadLocalStoragePointerAndDelCallback(NULL,
PTHREAD_TLS_INDEX,
tls,
pthread_cleanup_thread_specific_data_callback);/* ... */
#endif
}{...}
value_entry_t *entry = find_value(tls, key);
if (entry != NULL) {
if (value != NULL) {
entry->value = (void *) value;
}{...} else {
SLIST_REMOVE(tls, entry, value_entry_t_, next);
free(entry);
}{...}
}{...} else if (value != NULL) {
entry = malloc(sizeof(value_entry_t));
if (entry == NULL) {
return ENOMEM;
}{...}
entry->key = key;
entry->value = (void *) value;
value_entry_t *last_entry = NULL;
value_entry_t *it;
SLIST_FOREACH(it, tls, next) {
last_entry = it;
}{...}
if (last_entry == NULL) {
SLIST_INSERT_HEAD(tls, entry, next);
}{...} else {
SLIST_INSERT_AFTER(last_entry, entry, next);
}{...}
}{...}
return 0;
}{ ... }
void pthread_include_pthread_local_storage_impl(void)
{
}{ ... }