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
4 changes: 4 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5224,6 +5224,10 @@ def test_wasm_worker_semaphore_waitinf_acquire(self):
def test_wasm_worker_semaphore_try_acquire(self):
self.btest_exit('wasm_worker/semaphore_try_acquire.c', cflags=['-sWASM_WORKERS'])

@also_with_minimal_runtime
def test_wasm_worker_condvar_waitinf(self):
self.btest_exit('wasm_worker/condvar_waitinf.c', cflags=['-sWASM_WORKERS'])

# Tests that calling any proxied function in a Wasm Worker will abort at runtime when ASSERTIONS are enabled.
def test_wasm_worker_proxied_function(self):
error_msg = "abort:Assertion failed: Attempted to call proxied function '_proxied_js_function' in a Wasm Worker, but in Wasm Worker enabled builds, proxied function architecture is not available!"
Expand Down
5 changes: 5 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2794,6 +2794,11 @@ def test_emscripten_semaphore_waitinf_acquire(self):
def test_emscripten_semaphore_try_acquire(self):
self.do_runf('wasm_worker/semaphore_try_acquire.c', 'done\n', cflags=['-pthread'])

@requires_pthreads
@also_with_wasm_workers
def test_emscripten_condvar_waitinf(self):
self.do_runf('wasm_worker/condvar_waitinf.c', 'done\n', cflags=['-pthread'])

def test_tcgetattr(self):
self.do_runf('termios/test_tcgetattr.c', 'success')

Expand Down
99 changes: 99 additions & 0 deletions test/wasm_worker/condvar_waitinf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <assert.h>
#include <emscripten/console.h>
#include <emscripten/threading.h>
#include <stdbool.h>
#include <stdlib.h>

#ifdef __EMSCRIPTEN_PTHREADS__
#include <pthread.h>
#else
#include <emscripten/wasm_worker.h>
#endif

emscripten_condvar_t condvar = EMSCRIPTEN_CONDVAR_T_STATIC_INITIALIZER;
emscripten_lock_t mutex = EMSCRIPTEN_LOCK_T_STATIC_INITIALIZER;

int globalVar = 0;
_Atomic bool waiterStarted = false;

#ifndef __EMSCRIPTEN_PTHREADS__
void do_exit() {
emscripten_out("do_exit");
emscripten_terminate_all_wasm_workers();
emscripten_force_exit(0);
}
#endif

void waiter_main() {
emscripten_out("waiter_main");
emscripten_lock_waitinf_acquire(&mutex);
emscripten_out("waiter: got mutex");
assert(!globalVar);
waiterStarted = true;

while (!globalVar) {
emscripten_out("waiter: condvar wait");
emscripten_condvar_waitinf(&condvar, &mutex);
}

emscripten_out("waiter: done");
emscripten_lock_release(&mutex);

#ifndef __EMSCRIPTEN_PTHREADS__
emscripten_wasm_worker_post_function_v(EMSCRIPTEN_WASM_WORKER_ID_PARENT,
do_exit);
#endif
}

void signaler_main() {
emscripten_out("signaler_main");
while (!waiterStarted) {
// busy-wait for waiter
}
// At this point we know the waiter took the lock already.
// That means that once we acquire the lock here the waiter
// muste be `emscripten_condvar_waitinf`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// muste be `emscripten_condvar_waitinf`.
// must be `emscripten_condvar_waitinf`.

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.

Fixed in followup


emscripten_out("signaler: aquiring lock");
emscripten_lock_waitinf_acquire(&mutex);

emscripten_out("signaler: incrementing globalVar");
globalVar += 1;

emscripten_out("signaler: signaling condition");
emscripten_condvar_signal(&condvar, 1);

emscripten_out("signaler: done");
emscripten_lock_release(&mutex);
}

#ifdef __EMSCRIPTEN_PTHREADS__
void* waiter_pthread(void* arg) {
waiter_main();
return NULL;
}
void* signaler_pthread(void* arg) {
signaler_main();
return NULL;
}
#endif

int main() {
emscripten_out("in main");

#ifdef __EMSCRIPTEN_PTHREADS__
pthread_t waiter;
pthread_t signaler;
pthread_create(&waiter, NULL, waiter_pthread, NULL);
pthread_create(&signaler, NULL, signaler_pthread, NULL);
pthread_join(waiter, NULL);
pthread_join(signaler, NULL);
emscripten_out("done");
#else
emscripten_wasm_worker_t waiter = emscripten_malloc_wasm_worker(1024);
emscripten_wasm_worker_post_function_v(waiter, waiter_main);

emscripten_wasm_worker_t signaler = emscripten_malloc_wasm_worker(1024);
emscripten_wasm_worker_post_function_v(signaler, signaler_main);
#endif
}
Loading