diff --git a/system/lib/pthread/library_pthread_stub.c b/system/lib/pthread/library_pthread_stub.c index 6c9712378de00..e380f8ef2a9c9 100644 --- a/system/lib/pthread/library_pthread_stub.c +++ b/system/lib/pthread/library_pthread_stub.c @@ -21,10 +21,16 @@ bool emscripten_has_threading_support() { return false; } int emscripten_num_logical_cores() { return 1; } -int emscripten_futex_wait( - volatile void /*uint32_t*/* addr, uint32_t val, double maxWaitMilliseconds) { - // nop - return 0; // success +int emscripten_futex_wait(volatile void /*uint32_t*/* addr, + uint32_t val, + double maxWaitMilliseconds) { + if (!addr) { + return -EINVAL; + } + if (*(uint32_t*)addr != val) { + return -EWOULDBLOCK; + } + return -ENOTSUP; } int emscripten_futex_wake(volatile void /*uint32_t*/* addr, int count) { diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index b15a472089760..e8ec37864352d 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { "a.out.js": 244691, - "a.out.nodebug.wasm": 577678, - "total": 822369, + "a.out.nodebug.wasm": 577699, + "total": 822390, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/test_browser.py b/test/test_browser.py index c651383f4dd4b..cbbf261148409 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -5039,9 +5039,11 @@ def test_wasm_worker_hello_wasm2js(self): def test_wasm_worker_hello_embedded(self): self.btest_exit('wasm_worker/hello_wasm_worker.c', cflags=['-sWASM_WORKERS=2']) - # Tests that it is possible to call emscripten_futex_wait() in Wasm Workers. + # Tests that it is possible to call emscripten_futex_wait() in Wasm Workers when pthreads + # are also enabled. @parameterized({ - '': ([],), + # Without pthreads we expect the stub version of the futex API + '': (['-DEXPECT_STUB'],), 'pthread': (['-pthread'],), }) def test_wasm_worker_futex_wait(self, args): diff --git a/test/wasm_worker/wasm_worker_futex_wait.c b/test/wasm_worker/wasm_worker_futex_wait.c index 7830fca63b397..579a3ef2e23e1 100644 --- a/test/wasm_worker/wasm_worker_futex_wait.c +++ b/test/wasm_worker/wasm_worker_futex_wait.c @@ -1,5 +1,7 @@ // Test that emscripten_futex_wait() works in a Wasm Worker. +#include +#include #include #include #include @@ -12,21 +14,37 @@ _Atomic uint32_t futex_value = 0; void wake_worker_after_delay(void *user_data) { futex_value = 1; - emscripten_futex_wake(&futex_value, INT_MAX); + emscripten_futex_wake(&futex_value, INT_MAX); } void wake_worker() { - printf("Waking worker thread from futex wait.\n"); + 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"); + printf("Worker sleeping on futex...\n"); + double start = emscripten_performance_now(); + int rc = emscripten_futex_wait(&futex_value, 0, 100); + double end = emscripten_performance_now(); + printf("emscripten_futex_wait returned: %d after %.2fms\n", rc, end - start); +#if EXPECT_STUB + // The stub implemenation returns -ENOTSUP + assert(rc == -ENOTSUP); +#else + assert(rc == -ETIMEDOUT); + assert((end - start) >= 100); + + printf("Worker sleeping on futex with wakeup...\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); + rc = emscripten_futex_wait(&futex_value, 0, INFINITY); + printf("emscripten_futex_wait returned: %d\n", rc); + assert(rc == 0); + assert(futex_value == 1); +#endif + #ifdef REPORT_RESULT - REPORT_RESULT(rc); + REPORT_RESULT(0); #endif } diff --git a/test/webaudio/audioworklet_worker.c b/test/webaudio/audioworklet_worker.c index 046ac8992a692..1887986f6123c 100644 --- a/test/webaudio/audioworklet_worker.c +++ b/test/webaudio/audioworklet_worker.c @@ -2,14 +2,14 @@ #include #include #include +#include // Tests that // - audioworklets and workers can be used at the same time. // - an audioworklet can emscripten_futex_wake() a waiting worker. // - global values can be shared between audioworklets and workers. -int workletToWorkerFutexLocation = 0; -int workletToWorkerFlag = 0; +_Atomic bool workletToWorkerFlag = false; EMSCRIPTEN_WEBAUDIO_T context; void do_exit() { @@ -19,8 +19,10 @@ void do_exit() { } void run_in_worker() { - while (0 == emscripten_futex_wait(&workletToWorkerFutexLocation, 0, 30000)) { - if (workletToWorkerFlag == 1) { + // TODO: Convert to emscripten_futex_wait once it becomes available in Wasm + // Workers. + while (1) { + if (workletToWorkerFlag == true) { emscripten_out("Test success"); emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT, &do_exit); break; @@ -31,8 +33,7 @@ void run_in_worker() { // This event will fire on the audio worklet thread. void MessageReceivedInAudioWorkletThread() { assert(emscripten_current_thread_is_audio_worklet()); - workletToWorkerFlag = 1; - emscripten_futex_wake(&workletToWorkerFutexLocation, 1); + workletToWorkerFlag = true; } void WebAudioWorkletThreadInitialized(EMSCRIPTEN_WEBAUDIO_T audioContext, bool success, void *userData) {