|
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) |
| 28 | +emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackLowestAddress, uint32_t stackSize) |
32 | 29 | {
|
33 |
| -#if WASM_WORKER_NO_TLS |
34 |
| - return emscripten_create_wasm_worker_no_tls(stackLowestAddress, stackSize); |
35 |
| -#else |
| 30 | + assert(stackLowestAddress != 0); |
36 | 31 | assert((uintptr_t)stackLowestAddress % 16 == 0);
|
| 32 | + assert(stackSize > 0); |
37 | 33 | 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 |
45 |
| -} |
46 | 34 |
|
47 |
| -emscripten_wasm_worker_t emscripten_create_wasm_worker_no_tls(void *stackLowestAddress, uint32_t stackSize) |
48 |
| -{ |
49 |
| -#if !WASM_WORKER_NO_TLS |
50 |
| - return emscripten_create_wasm_worker_with_tls(stackLowestAddress, stackSize, 0, 0); |
51 |
| -#else |
52 |
| - assert((uintptr_t)stackLowestAddress % 16 == 0); |
53 |
| - 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 |
| 35 | + // Guard against a programming oopsie: The target Worker's stack cannot be part of the calling |
| 36 | + // thread's stack. |
| 37 | + assert(emscripten_stack_get_base() <= (uintptr_t)stackLowestAddress || emscripten_stack_get_end() >= (uintptr_t)stackLowestAddress + stackSize |
| 38 | + && "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!"); |
| 39 | + |
| 40 | + // The Worker's TLS area will be spliced off from the stack region. |
| 41 | + // We expect TLS area to need to be at most 16 bytes aligned |
| 42 | + assert(__builtin_wasm_tls_align() == 0 || 16 % __builtin_wasm_tls_align() == 0); |
| 43 | + |
| 44 | + uint32_t tlsSize = (__builtin_wasm_tls_size() + 15) & -16; |
| 45 | + assert(stackSize > tlsSize); |
| 46 | + |
| 47 | + return _emscripten_create_wasm_worker(stackLowestAddress, stackSize); |
57 | 48 | }
|
58 | 49 |
|
59 | 50 | emscripten_wasm_worker_t emscripten_malloc_wasm_worker(uint32_t stackSize)
|
60 | 51 | {
|
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 |
| 52 | + return emscripten_create_wasm_worker(memalign(16, stackSize), stackSize); |
67 | 53 | }
|
68 | 54 |
|
69 | 55 | void emscripten_wasm_worker_sleep(int64_t nsecs)
|
|
0 commit comments