Path: blob/main/system/lib/pthread/emscripten_tls_init.c
6178 views
/*1* Copyright 2019 The Emscripten Authors. All rights reserved.2* Emscripten is available under two separate licenses, the MIT license and the3* University of Illinois/NCSA Open Source License. Both these licenses can be4* found in the LICENSE file.5*/67#include <emscripten/heap.h>8#include <emscripten/threading.h>9#include <emscripten/console.h>10#include <stdlib.h>11#include <malloc.h>1213#include "pthread_impl.h"1415// Uncomment to trace TLS allocations.16// #define DEBUG_TLS17#ifdef DEBUG_TLS18#define dbg(fmt, ...) emscripten_dbgf(fmt, ##__VA_ARGS__)19#else20#define dbg(fmt, ...)21#endif2223// linker-generated symbol that loads static TLS data at the given location.24extern void __wasm_init_tls(void *memory);2526extern int __dso_handle;2728// Create a thread-local wasm global which signals that the current thread is not29// to use the primary/static TLS region. Once this gets set it forces that all30// future calls to emscripten_tls_init to dynamically allocate TLS.31// This is needed because emscripten re-uses module instances owned by the32// worker for new pthreads. This in turn means that stale values of __tls_base33// from a previous pthreads need to be ignored.34// If this global is true then TLS needs to be dynamically allocated, if it's35// false we are free to use the existing/global __tls_base.36__asm__(".globaltype g_needs_dynamic_alloc, i32\n"37"g_needs_dynamic_alloc:\n");3839static void set_needs_dynamic_alloc(void) {40__asm__("i32.const 1\n"41"global.set g_needs_dynamic_alloc\n");42}4344static int needs_dynamic_alloc(void) {45int val;46__asm__("global.get g_needs_dynamic_alloc\n"47"local.set %0" : "=r" (val));48return val;49}5051void _emscripten_tls_free() {52void* tls_block = __builtin_wasm_tls_base();53if (tls_block && needs_dynamic_alloc()) {54dbg("tls free: dso=%p <- %p", &__dso_handle, tls_block);55emscripten_builtin_free(tls_block);56}57}5859void* _emscripten_tls_init(void) {60size_t tls_size = __builtin_wasm_tls_size();61void* tls_block = __builtin_wasm_tls_base();62if (pthread_self()->tls_base) {63// The TLS block for the main module is allocated alongside the pthread64// itself and its stack.65tls_block = pthread_self()->tls_base;66pthread_self()->tls_base = NULL;67} else if (needs_dynamic_alloc() || (!tls_block && tls_size)) {68// For non-main modules we do a dynamic allocation.69set_needs_dynamic_alloc();70tls_block = emscripten_builtin_memalign(__builtin_wasm_tls_align(), tls_size);71}72dbg("tls init: size=%zu dso=%p -> %p:%p", tls_size, &__dso_handle, tls_block, ((char*)tls_block)+tls_size);73__wasm_init_tls(tls_block);74return tls_block;75}767778