Skip to content

Commit 551540f

Browse files
authored
Fix TLS alignment over 16 in wasm workers (#19570)
Fixes: #19540
1 parent 7301dcd commit 551540f

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

system/lib/wasm_worker/library_wasm_worker.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <emscripten/stack.h>
66
#include <emscripten/console.h>
77
#include <malloc.h>
8+
#include <sys/param.h> // For MAX()
89

910
#include "emscripten_internal.h"
1011

@@ -13,6 +14,8 @@
1314
#endif
1415

1516
#define ROUND_UP(x, ALIGNMENT) (((x)+ALIGNMENT-1)&-ALIGNMENT)
17+
#define SBRK_ALIGN (__alignof__(max_align_t))
18+
#define STACK_ALIGN 16
1619

1720
// Options:
1821
// #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);
2225
__attribute__((constructor(48)))
2326
static void emscripten_wasm_worker_main_thread_initialize() {
2427
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+
}
2732
__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);
2934
}
3035

3136
emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackPlusTLSAddress, size_t stackPlusTLSSize)
3237
{
3338
assert(stackPlusTLSAddress != 0);
34-
assert((uintptr_t)stackPlusTLSAddress % 16 == 0);
39+
assert((uintptr_t)stackPlusTLSAddress % STACK_ALIGN == 0);
3540
assert(stackPlusTLSSize > 0);
36-
assert(stackPlusTLSSize % 16 == 0);
41+
assert(stackPlusTLSSize % STACK_ALIGN == 0);
3742

3843
// Guard against a programming oopsie: The target Worker's stack cannot be part of the calling
3944
// thread's stack.
4045
assert(emscripten_stack_get_base() <= (uintptr_t)stackPlusTLSAddress || emscripten_stack_get_end() >= (uintptr_t)stackPlusTLSAddress + stackPlusTLSSize
4146
&& "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!");
4247

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-
4648
#ifndef NDEBUG
4749
// The Worker's TLS area will be spliced off from the stack region, so the
4850
// 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());
5052
assert(stackPlusTLSSize > tlsSize);
5153
#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+
}
5265
return _emscripten_create_wasm_worker(stackPlusTLSAddress, stackPlusTLSSize);
5366
}
5467

5568
emscripten_wasm_worker_t emscripten_malloc_wasm_worker(size_t stackSize)
5669
{
5770
// Add the TLS size to the provided stackSize so that the allocation
5871
// 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);
6175
}
6276

6377
void emscripten_wasm_worker_sleep(int64_t nsecs)

test/wasm_worker/c11__Thread_local.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <assert.h>
44
#include <threads.h>
55

6-
_Thread_local int tls = 1;
6+
_Thread_local int __attribute__((aligned(64))) tls = 1;
77

88
void main_thread_func()
99
{
@@ -17,6 +17,7 @@ void main_thread_func()
1717
void worker_main()
1818
{
1919
assert(emscripten_current_thread_is_wasm_worker());
20+
assert(((intptr_t)&tls % 64) == 0);
2021
assert(tls != 42);
2122
assert(tls != 0);
2223
assert(tls == 1);
@@ -29,6 +30,7 @@ char stack[1024];
2930
int main()
3031
{
3132
EM_ASM(console.log($0), tls);
33+
assert(((intptr_t)&tls % 64) == 0);
3234
assert(!emscripten_current_thread_is_wasm_worker());
3335
tls = 42;
3436
emscripten_wasm_worker_t worker = emscripten_create_wasm_worker(stack, sizeof(stack));

0 commit comments

Comments
 (0)