| |
| |
| |
| |
| |
| |
|
|
| #include <emscripten/heap.h> |
| #include <emscripten/threading.h> |
| #include <emscripten/console.h> |
| #include <stdlib.h> |
| #include <malloc.h> |
|
|
| #include "pthread_impl.h" |
|
|
| |
| |
| #ifdef DEBUG_TLS |
| #define dbg(fmt, ...) emscripten_dbgf(fmt, ##__VA_ARGS__) |
| #else |
| #define dbg(fmt, ...) |
| #endif |
|
|
| |
| extern void __wasm_init_tls(void *memory); |
|
|
| extern int __dso_handle; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| __asm__(".globaltype g_needs_dynamic_alloc, i32\n" |
| "g_needs_dynamic_alloc:\n"); |
|
|
| static void set_needs_dynamic_alloc(void) { |
| __asm__("i32.const 1\n" |
| "global.set g_needs_dynamic_alloc\n"); |
| } |
|
|
| static int needs_dynamic_alloc(void) { |
| int val; |
| __asm__("global.get g_needs_dynamic_alloc\n" |
| "local.set %0" : "=r" (val)); |
| return val; |
| } |
|
|
| void _emscripten_tls_free() { |
| void* tls_block = __builtin_wasm_tls_base(); |
| if (tls_block && needs_dynamic_alloc()) { |
| dbg("tls free: dso=%p <- %p", &__dso_handle, tls_block); |
| emscripten_builtin_free(tls_block); |
| } |
| } |
|
|
| void* _emscripten_tls_init(void) { |
| size_t tls_size = __builtin_wasm_tls_size(); |
| void* tls_block = __builtin_wasm_tls_base(); |
| pthread_t self = pthread_self(); |
| if (self->tls_base) { |
| |
| |
| tls_block = self->tls_base; |
| self->tls_base = NULL; |
| } else if (needs_dynamic_alloc() || (!tls_block && tls_size)) { |
| |
| set_needs_dynamic_alloc(); |
| tls_block = emscripten_builtin_memalign(__builtin_wasm_tls_align(), tls_size); |
| } |
| dbg("tls init: size=%zu dso=%p -> %p:%p", tls_size, &__dso_handle, tls_block, ((char*)tls_block)+tls_size); |
| __wasm_init_tls(tls_block); |
| return tls_block; |
| } |
|
|