| 155 | } |
| 156 | |
| 157 | static void NTAPI thread_exit(void *ctx) |
| 158 | { |
| 159 | FLS_KEY *fkey = (FLS_KEY *) ctx; |
| 160 | assert(fkey && fkey->locals); |
| 161 | |
| 162 | // The first one is set in thread_init() in fiber.c, it should be called |
| 163 | // in the end, because the original fiber will be freed that it means |
| 164 | // the current thread will be end and the thread context will freed. |
| 165 | TLS_OBJ *first = fifo_pop_front(fkey->locals), *obj; |
| 166 | assert(first); |
| 167 | |
| 168 | char key[32]; |
| 169 | |
| 170 | pthread_mutex_lock(&__lock); |
| 171 | |
| 172 | while ((obj = fifo_pop_front(fkey->locals))) { |
| 173 | hash_key(obj->key, key, sizeof(key)); |
| 174 | TLS_KEY *tkey = (TLS_KEY*) htable_find(__pkeys->keys, key); |
| 175 | if (tkey == NULL || tkey->destructor == NULL) { |
| 176 | continue; |
| 177 | } |
| 178 | tkey->destructor(obj->value); |
| 179 | mem_free(obj); |
| 180 | } |
| 181 | |
| 182 | fifo_free(fkey->locals, NULL); |
| 183 | mem_free(fkey); |
| 184 | |
| 185 | hash_key(first->key, key, sizeof(key)); |
| 186 | TLS_KEY *tkey = (TLS_KEY*) htable_find(__pkeys->keys, key); |
| 187 | assert(tkey); |
| 188 | |
| 189 | pthread_mutex_unlock(&__lock); |
| 190 | |
| 191 | void *value = first->value; |
| 192 | mem_free(first); |
| 193 | |
| 194 | // Must the __fls_key's value to NULL to avoid the thread_exit |
| 195 | // to be triggered again for the current thread when the original |
| 196 | // fiber is deleted. |
| 197 | FlsSetValue(__fls_key, NULL); |
| 198 | tkey->destructor(value); |
| 199 | } |
| 200 | |
| 201 | static void thread_once(void) |
| 202 | { |
nothing calls this directly
no test coverage detected
searching dependent graphs…