Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() }}});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if an AudioWorklet ends up calling emscripten_futex_wait, it looks like it will just unconditionally fail/trap when it calls __builtin_wasm_memory_atomic_wait32 on line 158 of emscripten_futex_wait.c. Is that just expected to not work?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will then abort in the newly added assert(). That'll be work for a separate PR.

#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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does exit(rc) work here (combined with btest_exit instead of just btest). I think I remember that maybe calling exit from a worker doesn't currently work due to lack of proxying but I can't remember.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got ReferenceError: document not defined

}

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