Skip to content

Commit c5a41e9

Browse files
committed
Allow emscripten_atomic_wait_suspending to return synchronously
Followup to the initial version landed in #26941
1 parent 478a1af commit c5a41e9

7 files changed

Lines changed: 52 additions & 7 deletions

File tree

src/lib/libatomic.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,21 @@ addToLibrary({
7575
},
7676

7777
#if ASYNCIFY
78-
emscripten_atomic_wait_suspending__async: 'auto',
79-
emscripten_atomic_wait_suspending__deps: ['$polyfillWaitAsync', '$atomicWaitStates'],
80-
emscripten_atomic_wait_suspending: async (addr, val, maxWaitMilliseconds) => {
78+
_emscripten_atomic_wait_promise__deps: ['$polyfillWaitAsync', '$atomicWaitStates', '$makePromise'],
79+
_emscripten_atomic_wait_promise: (addr, val, maxWaitMilliseconds) => {
8180
var wait = Atomics.waitAsync(HEAP32, {{{ getHeapOffset('addr', 'i32') }}}, val, maxWaitMilliseconds);
82-
return atomicWaitStates.indexOf(await wait.value)
81+
if (wait.async) {
82+
// In the async case return the promise ID.
83+
var chainedPromise = wait.value.then((value) => atomicWaitStates.indexOf(value));
84+
var id = promiseMap.allocate({promise: chainedPromise});
85+
return id;
86+
}
87+
// In the synchronous case return the negative result code
88+
return -atomicWaitStates.indexOf(wait.value);
89+
},
90+
#else
91+
_emscripten_atomic_wait_promise: (addr, val, maxWaitMilliseconds) => {
92+
abort('Please compile your program with async support in order to use asynchronous operations like emscripten_atomic_wait_promising');
8393
},
8494
#endif
8595

src/lib/libsigs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ sigs = {
314314
_embind_register_value_object__sig: 'vpppppp',
315315
_embind_register_value_object_field__sig: 'vpppppppppp',
316316
_embind_register_void__sig: 'vpp',
317+
_emscripten_atomic_wait_promise__sig: 'ppid',
317318
_emscripten_create_audio_worklet__sig: 'viipippp',
318319
_emscripten_create_wasm_worker__sig: 'iipip',
319320
_emscripten_dlopen_js__sig: 'vpppp',
@@ -592,7 +593,6 @@ sigs = {
592593
emscripten_atomic_cancel_all_wait_asyncs_at_address__sig: 'ip',
593594
emscripten_atomic_cancel_wait_async__sig: 'ii',
594595
emscripten_atomic_wait_async__sig: 'ipippd',
595-
emscripten_atomic_wait_suspending__sig: 'ipid',
596596
emscripten_atomics_is_lock_free__sig: 'ii',
597597
emscripten_audio_context_quantum_size__sig: 'ii',
598598
emscripten_audio_context_sample_rate__sig: 'ii',
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2026 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <emscripten/promise.h>
9+
#include <emscripten/atomic.h>
10+
#include "threading_internal.h"
11+
12+
ATOMICS_WAIT_TOKEN_T emscripten_atomic_wait_suspending(volatile void * _Nonnull addr,
13+
uint32_t value,
14+
double maxWaitMilliseconds) {
15+
intptr_t res = _emscripten_atomic_wait_promise(addr, value, maxWaitMilliseconds);
16+
// A negative value is a synchronous result code.
17+
if (res < 0) {
18+
return (ATOMICS_WAIT_TOKEN_T)-res;
19+
}
20+
// Otherwise a positive value is a promise ID, and we can then `await` using
21+
// ASYNCIFY/JSPI.
22+
em_promise_t promise = (em_promise_t)res;
23+
void* await_result = emscripten_promise_await_unchecked(promise);
24+
return (ATOMICS_WAIT_TOKEN_T)(intptr_t)await_result;
25+
}

system/lib/pthread/threading_internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include <inttypes.h>
1011
#include <pthread.h>
1112
#include <stdbool.h>
1213

@@ -131,3 +132,9 @@ void* _emscripten_init_pthread(void *base, size_t* size, pid_t tid);
131132
// __builtin_wasm_memory_atomic_waitXX then they will not be woken by
132133
// this method.
133134
void _emscripten_thread_notify(pthread_t thread);
135+
136+
// Internal promise-returning API used to implement
137+
// emscripten_atomic_wait_syspending.
138+
intptr_t _emscripten_atomic_wait_promise(volatile void *addr,
139+
uint32_t value,
140+
double maxWaitMilliseconds);

test/codesize/test_codesize_hello_dylink_all.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"a.out.js": 268202,
2+
"a.out.js": 268222,
33
"a.out.nodebug.wasm": 587563,
4-
"total": 855765,
4+
"total": 855785,
55
"sent": [
66
"IMG_Init",
77
"IMG_Load",

tools/maint/gen_sig_info.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,15 @@ def main(args):
384384
'MAX_WEBGL_VERSION': 0,
385385
'BUILD_AS_WORKER': 1,
386386
'LINK_AS_CXX': 1,
387+
'SHARED_MEMORY': 0,
387388
'AUTO_JS_LIBRARIES': 0}, cxx=True)
388389
extract_sig_info(sig_info, {'AUDIO_WORKLET': 1, 'WASM_WORKERS': 1, 'JS_LIBRARIES': ['libwasm_worker.js', 'libwebaudio.js']})
389390
extract_sig_info(sig_info, {'USE_GLFW': 3}, ['-DGLFW3'])
390391
extract_sig_info(sig_info, {'JS_LIBRARIES': ['libembind.js', 'libemval.js'],
391392
'USE_SDL': 0,
392393
'MAX_WEBGL_VERSION': 0,
393394
'AUTO_JS_LIBRARIES': 0,
395+
'SHARED_MEMORY': 0,
394396
'ASYNCIFY': 1}, cxx=True, extra_cflags=['-std=c++20'])
395397
extract_sig_info(sig_info, {'LEGACY_GL_EMULATION': 1}, ['-DGLES'])
396398
extract_sig_info(sig_info, {'USE_GLFW': 2, 'FULL_ES3': 1, 'MAX_WEBGL_VERSION': 2})

tools/system_libs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ def get_files(self):
12831283
'emscripten_thread_primitives.c',
12841284
'emscripten_futex_wait.c',
12851285
'emscripten_futex_wake.c',
1286+
'emscripten_atomic_wait_suspending.c',
12861287
])
12871288

12881289
# These files are in libc directories, but only built in libc_optz.

0 commit comments

Comments
 (0)