From 298c5b5a8c3e950249171bd6cdc0760274f5755a Mon Sep 17 00:00:00 2001 From: kme Date: Thu, 10 Nov 2022 19:50:52 +0800 Subject: [PATCH 1/4] enable thread safety for sbrk and emmalloc, when using WASM_WORKERS --- system/lib/emmalloc.c | 2 +- system/lib/sbrk.c | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/system/lib/emmalloc.c b/system/lib/emmalloc.c index 1fcad3318f363..aff8a836b745b 100644 --- a/system/lib/emmalloc.c +++ b/system/lib/emmalloc.c @@ -107,7 +107,7 @@ typedef struct RootRegion uint8_t* endPtr; } RootRegion; -#if defined(__EMSCRIPTEN_PTHREADS__) +#if defined(__EMSCRIPTEN_PTHREADS__) || defined(__EMSCRIPTEN_WASM_WORKERS__) // In multithreaded builds, use a simple global spinlock strategy to acquire/release access to the memory allocator. static volatile uint8_t multithreadingLock = 0; #define MALLOC_ACQUIRE() while(__sync_lock_test_and_set(&multithreadingLock, 1)) { while(multithreadingLock) { /*nop*/ } } diff --git a/system/lib/sbrk.c b/system/lib/sbrk.c index e443ddf3ba893..369718639cced 100644 --- a/system/lib/sbrk.c +++ b/system/lib/sbrk.c @@ -6,13 +6,21 @@ * */ +#if __EMSCRIPTEN_PTHREADS__ +#define RETRY_SBRK 1 +#endif + +#ifdef __EMSCRIPTEN_WASM_WORKERS__ +#define RETRY_SBRK 1 +#endif + #ifndef EMSCRIPTEN_NO_ERRNO #include #endif #include #include #include -#if __EMSCRIPTEN_PTHREADS__ // for error handling, see below +#if RETRY_SBRK // for error handling, see below #include #include #endif @@ -54,16 +62,16 @@ void *sbrk(intptr_t increment_) { uintptr_t old_size; uintptr_t increment = (uintptr_t)increment_; increment = (increment + (SBRK_ALIGNMENT-1)) & ~(SBRK_ALIGNMENT-1); -#if __EMSCRIPTEN_PTHREADS__ +#if RETRY_SBRK // Our default dlmalloc uses locks around each malloc/free, so no additional // work is necessary to keep things threadsafe, but we also make sure sbrk // itself is threadsafe so alternative allocators work. We do that by looping // and retrying if we hit interference with another thread. uintptr_t expected; while (1) { -#endif // __EMSCRIPTEN_PTHREADS__ +#endif // RETRY_SBRK uintptr_t* sbrk_ptr = emscripten_get_sbrk_ptr(); -#if __EMSCRIPTEN_PTHREADS__ +#if RETRY_SBRK uintptr_t old_brk = __c11_atomic_load((_Atomic(uintptr_t)*)sbrk_ptr, __ATOMIC_SEQ_CST); #else uintptr_t old_brk = *sbrk_ptr; @@ -81,7 +89,7 @@ void *sbrk(intptr_t increment_) { goto Error; } } -#if __EMSCRIPTEN_PTHREADS__ +#if RETRY_SBRK // Attempt to update the dynamic top to new value. Another thread may have // beat this one to the update, in which case we will need to start over // by iterating the loop body again. @@ -93,18 +101,18 @@ void *sbrk(intptr_t increment_) { if (expected != old_brk) { continue; } -#else // __EMSCRIPTEN_PTHREADS__ +#else // RETRY_SBRK *sbrk_ptr = new_brk; -#endif // __EMSCRIPTEN_PTHREADS__ +#endif // RETRY_SBRK #ifdef __EMSCRIPTEN_TRACING__ emscripten_memprof_sbrk_grow(old_brk, new_brk); #endif return (void*)old_brk; -#if __EMSCRIPTEN_PTHREADS__ +#if RETRY_SBRK } -#endif // __EMSCRIPTEN_PTHREADS__ +#endif // RETRY_SBRK Error: SET_ERRNO(); @@ -112,7 +120,7 @@ void *sbrk(intptr_t increment_) { } int brk(void* ptr) { -#if __EMSCRIPTEN_PTHREADS__ +#if RETRY_SBRK // FIXME printf("brk() is not theadsafe yet, https://github.com/emscripten-core/emscripten/issues/10006"); abort(); From 529b8e3b74a127459eb94773bbcf682b58b30589 Mon Sep 17 00:00:00 2001 From: kme Date: Thu, 10 Nov 2022 21:54:52 +0800 Subject: [PATCH 2/4] test/code_size/hello_wasm_worker_wasm.json: rebaseline --- test/code_size/hello_wasm_worker_wasm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/code_size/hello_wasm_worker_wasm.json b/test/code_size/hello_wasm_worker_wasm.json index e3837cd951cb2..13b3212340a7d 100644 --- a/test/code_size/hello_wasm_worker_wasm.json +++ b/test/code_size/hello_wasm_worker_wasm.json @@ -3,8 +3,8 @@ "a.html.gz": 433, "a.js": 733, "a.js.gz": 463, - "a.wasm": 1805, - "a.wasm.gz": 1002, + "a.wasm": 1861, + "a.wasm.gz": 1031, "total": 3275, "total_gz": 1898 } From 1fa4e7be90f70ed8bcf9892ac5bc0cbbf380fcfe Mon Sep 17 00:00:00 2001 From: kme Date: Mon, 14 Nov 2022 01:56:08 +0800 Subject: [PATCH 3/4] enable thread safety for sbrk and emmalloc, when using WASM_WORKERS - use __EMSCRIPTEN_SHARED_MEMORY__ for shared pthread/wasm workers cases --- system/lib/emmalloc.c | 2 +- system/lib/sbrk.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/system/lib/emmalloc.c b/system/lib/emmalloc.c index aff8a836b745b..8d144f616a7af 100644 --- a/system/lib/emmalloc.c +++ b/system/lib/emmalloc.c @@ -107,7 +107,7 @@ typedef struct RootRegion uint8_t* endPtr; } RootRegion; -#if defined(__EMSCRIPTEN_PTHREADS__) || defined(__EMSCRIPTEN_WASM_WORKERS__) +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ // In multithreaded builds, use a simple global spinlock strategy to acquire/release access to the memory allocator. static volatile uint8_t multithreadingLock = 0; #define MALLOC_ACQUIRE() while(__sync_lock_test_and_set(&multithreadingLock, 1)) { while(multithreadingLock) { /*nop*/ } } diff --git a/system/lib/sbrk.c b/system/lib/sbrk.c index 369718639cced..f8976b4ec0dfe 100644 --- a/system/lib/sbrk.c +++ b/system/lib/sbrk.c @@ -6,11 +6,7 @@ * */ -#if __EMSCRIPTEN_PTHREADS__ -#define RETRY_SBRK 1 -#endif - -#ifdef __EMSCRIPTEN_WASM_WORKERS__ +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ #define RETRY_SBRK 1 #endif From fb4fbdeed3182469c4b42d0dc383c512729526e3 Mon Sep 17 00:00:00 2001 From: kme Date: Mon, 14 Nov 2022 19:38:47 +0800 Subject: [PATCH 4/4] enable thread safety for sbrk and emmalloc, when using WASM_WORKERS - remove redundant RETRY_SBRK --- system/lib/sbrk.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/system/lib/sbrk.c b/system/lib/sbrk.c index f8976b4ec0dfe..21f2d570956eb 100644 --- a/system/lib/sbrk.c +++ b/system/lib/sbrk.c @@ -6,17 +6,13 @@ * */ -#ifdef __EMSCRIPTEN_SHARED_MEMORY__ -#define RETRY_SBRK 1 -#endif - #ifndef EMSCRIPTEN_NO_ERRNO #include #endif #include #include #include -#if RETRY_SBRK // for error handling, see below +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ // for error handling, see below #include #include #endif @@ -58,16 +54,16 @@ void *sbrk(intptr_t increment_) { uintptr_t old_size; uintptr_t increment = (uintptr_t)increment_; increment = (increment + (SBRK_ALIGNMENT-1)) & ~(SBRK_ALIGNMENT-1); -#if RETRY_SBRK +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ // Our default dlmalloc uses locks around each malloc/free, so no additional // work is necessary to keep things threadsafe, but we also make sure sbrk // itself is threadsafe so alternative allocators work. We do that by looping // and retrying if we hit interference with another thread. uintptr_t expected; while (1) { -#endif // RETRY_SBRK +#endif // __EMSCRIPTEN_SHARED_MEMORY__ uintptr_t* sbrk_ptr = emscripten_get_sbrk_ptr(); -#if RETRY_SBRK +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ uintptr_t old_brk = __c11_atomic_load((_Atomic(uintptr_t)*)sbrk_ptr, __ATOMIC_SEQ_CST); #else uintptr_t old_brk = *sbrk_ptr; @@ -85,7 +81,7 @@ void *sbrk(intptr_t increment_) { goto Error; } } -#if RETRY_SBRK +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ // Attempt to update the dynamic top to new value. Another thread may have // beat this one to the update, in which case we will need to start over // by iterating the loop body again. @@ -97,18 +93,18 @@ void *sbrk(intptr_t increment_) { if (expected != old_brk) { continue; } -#else // RETRY_SBRK +#else // __EMSCRIPTEN_SHARED_MEMORY__ *sbrk_ptr = new_brk; -#endif // RETRY_SBRK +#endif // __EMSCRIPTEN_SHARED_MEMORY__ #ifdef __EMSCRIPTEN_TRACING__ emscripten_memprof_sbrk_grow(old_brk, new_brk); #endif return (void*)old_brk; -#if RETRY_SBRK +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ } -#endif // RETRY_SBRK +#endif // __EMSCRIPTEN_SHARED_MEMORY__ Error: SET_ERRNO(); @@ -116,7 +112,7 @@ void *sbrk(intptr_t increment_) { } int brk(void* ptr) { -#if RETRY_SBRK +#ifdef __EMSCRIPTEN_SHARED_MEMORY__ // FIXME printf("brk() is not theadsafe yet, https://github.com/emscripten-core/emscripten/issues/10006"); abort();