5
5
#include <emscripten/stack.h>
6
6
#include <emscripten/console.h>
7
7
#include <malloc.h>
8
+ #include <sys/param.h> // For MAX()
8
9
9
10
#include "emscripten_internal.h"
10
11
13
14
#endif
14
15
15
16
#define ROUND_UP (x , ALIGNMENT ) (((x)+ALIGNMENT-1)&-ALIGNMENT)
17
+ #define SBRK_ALIGN (__alignof__(max_align_t))
18
+ #define STACK_ALIGN 16
16
19
17
20
// Options:
18
21
// #define STACK_OVERFLOW_CHECK 0/1/2 : set to the current stack overflow check mode
@@ -22,42 +25,53 @@ void __wasm_init_tls(void *memory);
22
25
__attribute__((constructor (48 )))
23
26
static void emscripten_wasm_worker_main_thread_initialize () {
24
27
uintptr_t * sbrk_ptr = emscripten_get_sbrk_ptr ();
25
- assert ((* sbrk_ptr & 15 ) == 0 );
26
- assert (__builtin_wasm_tls_align () <= 16 );
28
+ assert ((* sbrk_ptr % STACK_ALIGN ) == 0 );
29
+ if (__builtin_wasm_tls_align () > STACK_ALIGN ) {
30
+ * sbrk_ptr = ROUND_UP (* sbrk_ptr , __builtin_wasm_tls_align ());
31
+ }
27
32
__wasm_init_tls ((void * )* sbrk_ptr );
28
- * sbrk_ptr += ROUND_UP (__builtin_wasm_tls_size (), 16 );
33
+ * sbrk_ptr += ROUND_UP (__builtin_wasm_tls_size (), SBRK_ALIGN );
29
34
}
30
35
31
36
emscripten_wasm_worker_t emscripten_create_wasm_worker (void * stackPlusTLSAddress , size_t stackPlusTLSSize )
32
37
{
33
38
assert (stackPlusTLSAddress != 0 );
34
- assert ((uintptr_t )stackPlusTLSAddress % 16 == 0 );
39
+ assert ((uintptr_t )stackPlusTLSAddress % STACK_ALIGN == 0 );
35
40
assert (stackPlusTLSSize > 0 );
36
- assert (stackPlusTLSSize % 16 == 0 );
41
+ assert (stackPlusTLSSize % STACK_ALIGN == 0 );
37
42
38
43
// Guard against a programming oopsie: The target Worker's stack cannot be part of the calling
39
44
// thread's stack.
40
45
assert (emscripten_stack_get_base () <= (uintptr_t )stackPlusTLSAddress || emscripten_stack_get_end () >= (uintptr_t )stackPlusTLSAddress + stackPlusTLSSize
41
46
&& "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!" );
42
47
43
- // We expect TLS area to need to be at most 16 bytes aligned
44
- assert (__builtin_wasm_tls_align () == 0 || 16 % __builtin_wasm_tls_align () == 0 );
45
-
46
48
#ifndef NDEBUG
47
49
// The Worker's TLS area will be spliced off from the stack region, so the
48
50
// stack needs to be at least as large as the TLS region.
49
- uint32_t tlsSize = ROUND_UP (__builtin_wasm_tls_size (), 16 );
51
+ uint32_t tlsSize = ROUND_UP (__builtin_wasm_tls_size (), __builtin_wasm_tls_align () );
50
52
assert (stackPlusTLSSize > tlsSize );
51
53
#endif
54
+ // The TLS region lives at the start of the stack region (the lowest address
55
+ // of the stack). Since the TLS data alignment may be larger than stack
56
+ // alignment, we may need to round up the lowest stack address to meet this
57
+ // requirment.
58
+ if (__builtin_wasm_tls_align () > STACK_ALIGN ) {
59
+ uintptr_t tlsBase = (uintptr_t )stackPlusTLSAddress ;
60
+ tlsBase = ROUND_UP (tlsBase , __builtin_wasm_tls_align ());
61
+ size_t padding = tlsBase - (uintptr_t )stackPlusTLSAddress ;
62
+ stackPlusTLSAddress = (void * )tlsBase ;
63
+ stackPlusTLSSize -= padding ;
64
+ }
52
65
return _emscripten_create_wasm_worker (stackPlusTLSAddress , stackPlusTLSSize );
53
66
}
54
67
55
68
emscripten_wasm_worker_t emscripten_malloc_wasm_worker (size_t stackSize )
56
69
{
57
70
// Add the TLS size to the provided stackSize so that the allocation
58
71
// will always be large enough to hold the worker TLS data.
59
- stackSize += ROUND_UP (__builtin_wasm_tls_size (), 16 );
60
- return emscripten_create_wasm_worker (emscripten_builtin_memalign (16 , stackSize ), stackSize );
72
+ stackSize += ROUND_UP (__builtin_wasm_tls_size (), STACK_ALIGN );
73
+ void * stackPlusTLSAddress = emscripten_builtin_memalign (MAX (__builtin_wasm_tls_align (), STACK_ALIGN ), stackSize );
74
+ return emscripten_create_wasm_worker (stackPlusTLSAddress , stackSize );
61
75
}
62
76
63
77
void emscripten_wasm_worker_sleep (int64_t nsecs )
0 commit comments