Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/pthread/emscripten_tls_init.c
6178 views
1
/*
2
* Copyright 2019 The Emscripten Authors. All rights reserved.
3
* Emscripten is available under two separate licenses, the MIT license and the
4
* University of Illinois/NCSA Open Source License. Both these licenses can be
5
* found in the LICENSE file.
6
*/
7
8
#include <emscripten/heap.h>
9
#include <emscripten/threading.h>
10
#include <emscripten/console.h>
11
#include <stdlib.h>
12
#include <malloc.h>
13
14
#include "pthread_impl.h"
15
16
// Uncomment to trace TLS allocations.
17
// #define DEBUG_TLS
18
#ifdef DEBUG_TLS
19
#define dbg(fmt, ...) emscripten_dbgf(fmt, ##__VA_ARGS__)
20
#else
21
#define dbg(fmt, ...)
22
#endif
23
24
// linker-generated symbol that loads static TLS data at the given location.
25
extern void __wasm_init_tls(void *memory);
26
27
extern int __dso_handle;
28
29
// Create a thread-local wasm global which signals that the current thread is not
30
// to use the primary/static TLS region. Once this gets set it forces that all
31
// future calls to emscripten_tls_init to dynamically allocate TLS.
32
// This is needed because emscripten re-uses module instances owned by the
33
// worker for new pthreads. This in turn means that stale values of __tls_base
34
// from a previous pthreads need to be ignored.
35
// If this global is true then TLS needs to be dynamically allocated, if it's
36
// false we are free to use the existing/global __tls_base.
37
__asm__(".globaltype g_needs_dynamic_alloc, i32\n"
38
"g_needs_dynamic_alloc:\n");
39
40
static void set_needs_dynamic_alloc(void) {
41
__asm__("i32.const 1\n"
42
"global.set g_needs_dynamic_alloc\n");
43
}
44
45
static int needs_dynamic_alloc(void) {
46
int val;
47
__asm__("global.get g_needs_dynamic_alloc\n"
48
"local.set %0" : "=r" (val));
49
return val;
50
}
51
52
void _emscripten_tls_free() {
53
void* tls_block = __builtin_wasm_tls_base();
54
if (tls_block && needs_dynamic_alloc()) {
55
dbg("tls free: dso=%p <- %p", &__dso_handle, tls_block);
56
emscripten_builtin_free(tls_block);
57
}
58
}
59
60
void* _emscripten_tls_init(void) {
61
size_t tls_size = __builtin_wasm_tls_size();
62
void* tls_block = __builtin_wasm_tls_base();
63
if (pthread_self()->tls_base) {
64
// The TLS block for the main module is allocated alongside the pthread
65
// itself and its stack.
66
tls_block = pthread_self()->tls_base;
67
pthread_self()->tls_base = NULL;
68
} else if (needs_dynamic_alloc() || (!tls_block && tls_size)) {
69
// For non-main modules we do a dynamic allocation.
70
set_needs_dynamic_alloc();
71
tls_block = emscripten_builtin_memalign(__builtin_wasm_tls_align(), tls_size);
72
}
73
dbg("tls init: size=%zu dso=%p -> %p:%p", tls_size, &__dso_handle, tls_block, ((char*)tls_block)+tls_size);
74
__wasm_init_tls(tls_block);
75
return tls_block;
76
}
77
78