|
2 | 2 | #include <emscripten/wasm_worker.h>
|
3 | 3 | #include <emscripten/threading.h>
|
4 | 4 | #include <emscripten/heap.h>
|
| 5 | +#include <emscripten/stack.h> |
5 | 6 | #include <malloc.h>
|
6 | 7 |
|
7 | 8 | #ifndef __EMSCRIPTEN_WASM_WORKERS__
|
8 | 9 | #error __EMSCRIPTEN_WASM_WORKERS__ should be defined when building this file!
|
9 | 10 | #endif
|
10 | 11 |
|
11 | 12 | // Options:
|
12 |
| -// #define WASM_WORKER_NO_TLS 0/1 : set to 1 to disable TLS compilation support for a small code size gain |
13 | 13 | // #define STACK_OVERFLOW_CHECK 0/1/2 : set to the current stack overflow check mode
|
14 | 14 |
|
15 | 15 | // Internal implementation function in JavaScript side that emscripten_create_wasm_worker() calls to
|
16 | 16 | // to perform the wasm worker creation.
|
17 |
| -emscripten_wasm_worker_t _emscripten_create_wasm_worker_with_tls(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress); |
18 |
| -emscripten_wasm_worker_t _emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize); |
| 17 | +emscripten_wasm_worker_t _emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize); |
19 | 18 |
|
20 | 19 | void __wasm_init_tls(void *memory);
|
21 | 20 |
|
22 |
| -#if !WASM_WORKER_NO_TLS |
23 | 21 | __attribute__((constructor(48)))
|
24 | 22 | static void emscripten_wasm_worker_main_thread_initialize() {
|
25 | 23 | uintptr_t* sbrk_ptr = emscripten_get_sbrk_ptr();
|
26 | 24 | __wasm_init_tls((void*)*sbrk_ptr);
|
27 | 25 | *sbrk_ptr += __builtin_wasm_tls_size();
|
28 | 26 | }
|
29 |
| -#endif |
30 | 27 |
|
31 |
| -emscripten_wasm_worker_t emscripten_create_wasm_worker_with_tls(void *stackLowestAddress, uint32_t stackSize, void *tlsAddress, uint32_t tlsSize) |
32 |
| -{ |
33 |
| -#if WASM_WORKER_NO_TLS |
34 |
| - return emscripten_create_wasm_worker_no_tls(stackLowestAddress, stackSize); |
35 |
| -#else |
36 |
| - assert((uintptr_t)stackLowestAddress % 16 == 0); |
37 |
| - assert(stackSize % 16 == 0); |
38 |
| - assert(__builtin_wasm_tls_align() != 0 || __builtin_wasm_tls_size() == 0); // Internal consistency check: Clang can report __builtin_wasm_tls_align to be zero if there is no TLS used - double check it never reports zero if it is used. |
39 |
| - assert(__builtin_wasm_tls_align() == 0 || (uintptr_t)tlsAddress % __builtin_wasm_tls_align() == 0 && "TLS memory address not aligned in a call to emscripten_create_wasm_worker_with_tls()! Please allocate memory with alignment from __builtin_wasm_tls_align() when creating a Wasm Worker!"); |
40 |
| - assert(tlsSize != 0 || __builtin_wasm_tls_size() == 0 && "Program code contains TLS: please use function emscripten_create_wasm_worker_with_tls() to create a Wasm Worker!"); |
41 |
| - assert(tlsSize == __builtin_wasm_tls_size() && "TLS size mismatch! Please reserve exactly __builtin_wasm_tls_size() TLS memory in a call to emscripten_create_wasm_worker_with_tls()"); |
42 |
| - assert(tlsAddress != 0 || tlsSize == 0); |
43 |
| - return _emscripten_create_wasm_worker_with_tls((void*)stackLowestAddress, stackSize, tlsAddress); |
44 |
| -#endif |
| 28 | +// TODO: If it is possible to directly access __builtin_wasm_tls_size() and __builtin_wasm_tls_align() |
| 29 | +// from system/lib/compiler-rt/stack_limits.S, then this function can be merged into there. |
| 30 | +uint32_t wasm_worker_init_tls(void *stackLowestAddress) { |
| 31 | + size_t alignedTlsSize = (__builtin_wasm_tls_size() + 15) & -16; |
| 32 | + assert(__builtin_wasm_tls_align() == 0 || (uintptr_t)stackLowestAddress % __builtin_wasm_tls_align() == 0); |
| 33 | + __wasm_init_tls(stackLowestAddress); |
| 34 | + return alignedTlsSize; |
45 | 35 | }
|
46 | 36 |
|
47 |
| -emscripten_wasm_worker_t emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize) |
| 37 | +emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize) |
48 | 38 | {
|
49 |
| -#if !WASM_WORKER_NO_TLS |
50 |
| - return emscripten_create_wasm_worker_with_tls(stackLowestAddress, stackSize, 0, 0); |
51 |
| -#else |
| 39 | + assert(stackLowestAddress != 0); |
52 | 40 | assert((uintptr_t)stackLowestAddress % 16 == 0);
|
| 41 | + assert(stackSize > 0); |
53 | 42 | assert(stackSize % 16 == 0);
|
54 |
| - assert(__builtin_wasm_tls_size() == 0 && "Cannot disable TLS with -sWASM_WORKERS_NO_TLS=1 when compiling code that does require TLS! Rebuild with -sWASM_WORKERS_NO_TLS=1 removed, or remove uses of TLS from the codebase."); |
55 |
| - return _emscripten_create_wasm_worker_no_tls((void*)stackLowestAddress, stackSize); |
56 |
| -#endif |
| 43 | + |
| 44 | + // Guard against a programming oopsie: The target Worker's stack cannot be part of the calling |
| 45 | + // thread's stack. |
| 46 | + assert(emscripten_stack_get_base() <= stackLowestAddress || emscripten_stack_get_end() >= stackLowestAddress + stackSize |
| 47 | + && "When creating a Wasm Worker, its stack should be located either in global data or on the heap, not on the calling thread's own stack!"); |
| 48 | + |
| 49 | + // The Worker's TLS area will be spliced off from the stack region. |
| 50 | + // We expect TLS area to need to be at most 16 bytes aligned |
| 51 | + assert(__builtin_wasm_tls_align() == 0 || 16 % __builtin_wasm_tls_align() == 0); |
| 52 | + |
| 53 | + uint32_t tlsSize = (__builtin_wasm_tls_size() + 15) & -16; |
| 54 | + assert(stackSize > tlsSize); |
| 55 | + |
| 56 | + return _emscripten_create_wasm_worker(stackLowestAddress, stackSize); |
57 | 57 | }
|
58 | 58 |
|
59 | 59 | emscripten_wasm_worker_t emscripten_malloc_wasm_worker(uint32_t stackSize)
|
60 | 60 | {
|
61 |
| -#if WASM_WORKER_NO_TLS |
62 |
| - return emscripten_create_wasm_worker_no_tls(memalign(16, stackSize), stackSize); |
63 |
| -#else |
64 |
| - uint32_t tlsSize = __builtin_wasm_tls_size(); |
65 |
| - return emscripten_create_wasm_worker_with_tls(memalign(16, stackSize), stackSize, tlsSize ? memalign(__builtin_wasm_tls_align(), tlsSize) : 0, tlsSize); |
66 |
| -#endif |
| 61 | + return emscripten_create_wasm_worker(memalign(16, stackSize), stackSize); |
67 | 62 | }
|
68 | 63 |
|
69 | 64 | void emscripten_wasm_worker_sleep(int64_t nsecs)
|
|
0 commit comments