@@ -70,38 +70,56 @@ static void init_file_lock(FILE *f) {
7070 if (f && f -> lock < 0 ) f -> lock = 0 ;
7171}
7272
73+ static size_t max_alignment () {
74+ return MAX (__builtin_wasm_tls_align (), STACK_ALIGN );
75+ }
76+
7377#ifdef __EMSCRIPTEN_PTHREADS__
74- /* pthread_key_create.c overrides this */
78+ _Static_assert (STACK_ALIGN >= _Alignof(struct pthread ));
79+
80+ /*
81+ * pthread_key_create.c overrides this, meaning we only allocate space for TSD
82+ * if needed by the program.
83+ */
7584static volatile size_t dummy = 0 ;
7685weak_alias (dummy , __pthread_tsd_size );
7786
78- #define TSD_ALIGN (sizeof(void*))
79-
8087/**
8188 * The layout of the wasm worker stack space in hybrid mode is as follow.
82- * [ struct pthread ] [ pthread TSD slots ] [ TLS data ] [ ... stack ]
89+ * [ struct pthread ] [ pthread TSD slots ] [ ... stack ] [ TLS data ]
8390 *
8491 * As opposed to the layout for regular Wasm Workers which is just:
85- * [ TLS data ] [ ... stack ]
92+ * [ ... stack ] [ TLS data ]
93+ *
94+ * In either case these sections are all aligned to `max_alignment()`
95+ * which is the max alignment of any of the given chunks.
8696 */
8797static void * init_pthread_struct (void * stackPlusTLSAddress , pid_t tid , size_t * stackPlusTLSSize ) {
8898 // TODO: Remove duplication with pthread_create
89-
9099 pthread_t self = pthread_self ();
91- pthread_t new = (pthread_t )stackPlusTLSAddress ;
92100
93101 uintptr_t base = (uintptr_t )stackPlusTLSAddress ;
94102 uintptr_t offset = base ;
95103
96- // 3. tsd slots
104+ size_t alignment = max_alignment ();
105+ assert (base % alignment == 0 );
106+
107+ // 1. struct pthread comes first
108+ pthread_t new = (pthread_t )offset ;
109+ memset (new , 0 , sizeof (struct pthread ));
110+ offset += ROUND_UP (sizeof (struct pthread ), alignment );
111+
112+ // 2. tsd slots
97113 if (__pthread_tsd_size ) {
98- offset = ROUND_UP (offset , TSD_ALIGN );
99114 new -> tsd = (void * )offset ;
100- offset += __pthread_tsd_size ;
115+ memset (new -> tsd , 0 , __pthread_tsd_size );
116+ offset += ROUND_UP (__pthread_tsd_size , alignment );
101117 }
102118
119+ // 3. Remaining space is for TLS data + stack, which is handled by
120+ // the wasm worker startup code.
121+
103122 // Calculate updated stack size
104- offset = ROUND_UP (offset , STACK_ALIGN );
105123 size_t new_stack_size = * stackPlusTLSSize - (offset - base );
106124 assert (new_stack_size % STACK_ALIGN == 0 );
107125 assert (new_stack_size > 0 );
@@ -192,11 +210,17 @@ emscripten_wasm_worker_t emscripten_create_wasm_worker(void *stackPlusTLSAddress
192210}
193211
194212emscripten_wasm_worker_t emscripten_malloc_wasm_worker (size_t stackSize ) {
195- // Add the TLS size to the provided stackSize so that the allocation
196- // will always be large enough to hold the worker TLS data.
197- stackSize += ROUND_UP (__builtin_wasm_tls_size (), STACK_ALIGN );
198- void * stackPlusTLSAddress = emscripten_builtin_memalign (MAX (__builtin_wasm_tls_align (), STACK_ALIGN ), stackSize );
199- return emscripten_create_wasm_worker (stackPlusTLSAddress , stackSize );
213+ // Add the TLS size (and pthread metadata size) to the provided stackSize so
214+ // that the allocation will always be large enough.
215+ size_t alignment = max_alignment ();
216+ size_t totalSize = stackSize + ROUND_UP (__builtin_wasm_tls_size (), alignment );
217+ #ifdef __EMSCRIPTEN_PTHREADS__
218+ totalSize += ROUND_UP (sizeof (struct pthread ), alignment );
219+ totalSize += ROUND_UP (__pthread_tsd_size , alignment );
220+ #endif
221+
222+ void * address = emscripten_builtin_memalign (alignment , totalSize );
223+ return emscripten_create_wasm_worker (address , totalSize );
200224}
201225
202226void emscripten_wasm_worker_sleep (int64_t nsecs ) {
0 commit comments