Skip to content

Commit

Permalink
Fix Wasm Workers calling emscripten_futex_wait() when building with p…
Browse files Browse the repository at this point in the history
…threads support enabled. Fixes emscripten-core#21549. (emscripten-core#21618)

Would benefit from a test, I'll look into this shortly.
  • Loading branch information
juj committed Aug 27, 2024
1 parent c83c291 commit 62d7153
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 3 deletions.
10 changes: 8 additions & 2 deletions src/library_wasm_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#error "-sPROXY_TO_WORKER is not supported with -sWASM_WORKERS"
#endif

{{{
globalThis.workerSupportsFutexWait = () => AUDIO_WORKLET ? "typeof AudioWorkletGlobalScope === 'undefined'" : '1';
null;
}}}

#endif // ~WASM_WORKERS


Expand Down Expand Up @@ -95,8 +100,9 @@ addToLibrary({
// Run the C side Worker initialization for stack and TLS.
__emscripten_wasm_worker_initialize(m['sb'], m['sz']);
#if PTHREADS
// Record that this Wasm Worker supports synchronous blocking in emscripten_futex_wake().
___set_thread_state(/*thread_ptr=*/0, /*is_main_thread=*/0, /*is_runtime_thread=*/0, /*supports_wait=*/0);
// Record the pthread configuration, and whether this Wasm Worker supports synchronous blocking in emscripten_futex_wait().
// (regular Wasm Workers do, AudioWorklets don't)
___set_thread_state(/*thread_ptr=*/0, /*is_main_thread=*/0, /*is_runtime_thread=*/0, /*supports_wait=*/ {{{ workerSupportsFutexWait() }}});
#endif
#if STACK_OVERFLOW_CHECK >= 2
// Fix up stack base. (TLS frame is created at the bottom address end of the stack)
Expand Down
5 changes: 4 additions & 1 deletion system/lib/pthread/emscripten_futex_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ static int futex_wait_main_browser_thread(volatile void* addr,
uint32_t val,
double timeout) {
// Atomics.wait is not available in the main browser thread, so simulate it
// via busy spinning.
// via busy spinning. Only the main browser thread is allowed to call into
// this function. It is not thread-safe to be called from any other thread.
assert(emscripten_is_main_browser_thread());

double now = emscripten_get_now();
double end = now + timeout;

Expand Down
8 changes: 8 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4946,6 +4946,14 @@ def test_wasm_worker_hello_wasm2js(self):
def test_wasm_worker_embedded(self):
self.btest('wasm_worker/hello_wasm_worker.c', expected='0', args=['-sWASM_WORKERS=2'])

# Tests that it is possible to call emscripten_futex_wait() in Wasm Workers.
@parameterized({
'': ([],),
'pthread': (['-pthread'],),
})
def test_wasm_worker_futex_wait(self, args):
self.btest('wasm_worker/wasm_worker_futex_wait.c', expected='0', args=['-sWASM_WORKERS=1', '-sASSERTIONS'] + args)

# Tests Wasm Worker thread stack setup
@also_with_minimal_runtime
def test_wasm_worker_thread_stack(self):
Expand Down
35 changes: 35 additions & 0 deletions test/wasm_worker/wasm_worker_futex_wait.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Test that emscripten_futex_wait() works in a Wasm Worker.

#include <emscripten.h>
#include <emscripten/console.h>
#include <emscripten/threading.h>
#include <emscripten/wasm_worker.h>
#include <limits.h>
#include <stdio.h>
#include <math.h>

_Atomic uint32_t futex_value = 0;

void wake_worker_after_delay(void *user_data) {
futex_value = 1;
emscripten_futex_wake(&futex_value, INT_MAX);
}

void wake_worker() {
printf("Waking worker thread from futex wait.\n");
emscripten_set_timeout(wake_worker_after_delay, 500, 0);
}

void worker_main() {
printf("Worker sleeping for futex wait.\n");
emscripten_wasm_worker_post_function_v(0, wake_worker);
int rc = emscripten_futex_wait(&futex_value, 0, INFINITY);
printf("emscripten_futex_wait returned with code %d.\n", rc);
#ifdef REPORT_RESULT
REPORT_RESULT(rc);
#endif
}

int main() {
emscripten_wasm_worker_post_function_v(emscripten_malloc_wasm_worker(1024), worker_main);
}

0 comments on commit 62d7153

Please sign in to comment.