Skip to content

Commit 7bca7aa

Browse files
committed
[JSPI] Automatically add promising JSPI wrappers to thread entry points.
Use a WebAssembly.Promising wrapper on the thread entry points to allow JSPI to be used from worker threads. The code that invokes the wrapper also adds async/await to handle this async call to entry point. Fixes #22354
1 parent 44c7540 commit 7bca7aa

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

src/library_pthread.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ var LibraryPThread = {
10431043
'$runtimeKeepaliveCounter',
10441044
#endif
10451045
],
1046-
$invokeEntryPoint: (ptr, arg) => {
1046+
$invokeEntryPoint: {{{ asyncIf(ASYNCIFY == 2) }}} (ptr, arg) => {
10471047
#if PTHREADS_DEBUG
10481048
dbg(`invokeEntryPoint: ${ptrToString(ptr)}`);
10491049
#endif
@@ -1079,7 +1079,11 @@ var LibraryPThread = {
10791079
// *ThreadMain(void *arg) form, or try linking with the Emscripten linker
10801080
// flag -sEMULATE_FUNCTION_POINTER_CASTS to add in emulation for this x86
10811081
// ABI extension.
1082+
#if ASYNCIFY == 2
1083+
var result = WebAssembly.promising({{{ makeDynCall('pp', 'ptr') }}})(arg);
1084+
#else
10821085
var result = {{{ makeDynCall('pp', 'ptr') }}}(arg);
1086+
#endif
10831087
#if STACK_OVERFLOW_CHECK
10841088
checkStackCookie();
10851089
#endif
@@ -1098,10 +1102,9 @@ var LibraryPThread = {
10981102
#endif
10991103
}
11001104
#if ASYNCIFY == 2
1101-
Promise.resolve(result).then(finish);
1102-
#else
1103-
finish(result);
1105+
result = await result;
11041106
#endif
1107+
finish(result);
11051108
},
11061109
11071110
#if MAIN_MODULE

src/runtime_pthread.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
9090
// notified about them.
9191
self.onunhandledrejection = (e) => { throw e.reason || e; };
9292

93-
function handleMessage(e) {
93+
{{{ asyncIf(ASYNCIFY == 2) }}} function handleMessage(e) {
9494
try {
9595
var msgData = e['data'];
9696
//dbg('msgData: ' + Object.keys(msgData));
@@ -201,7 +201,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
201201
}
202202

203203
try {
204-
invokeEntryPoint(msgData.start_routine, msgData.arg);
204+
{{{ awaitIf(ASYNCIFY == 2) }}} invokeEntryPoint(msgData.start_routine, msgData.arg);
205205
} catch(ex) {
206206
if (ex != 'unwind') {
207207
// The pthread "crashed". Do not call `_emscripten_thread_exit` (which

test/core/test_pthread_join_and_asyncify.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ EM_ASYNC_JS(int, async_call, (), {
1313
return 42;
1414
});
1515

16-
// TODO Remove EMSCRIPTEN_KEEPALIVE when support for async attributes is enabled.
17-
EMSCRIPTEN_KEEPALIVE void *run_thread(void *args) {
16+
void *run_thread(void *args) {
1817
int ret = async_call();
1918
assert(ret == 42);
2019
return NULL;
2120
}
2221

2322
int main() {
2423
pthread_t id;
24+
// Test that JSPI works on main thread.
25+
emscripten_sleep(1);
26+
// Also test that JSPI works on other threads.
2527
pthread_create(&id, NULL, run_thread, NULL);
2628
printf("joining thread!\n");
2729
pthread_join(id, NULL);

test/test_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8300,7 +8300,7 @@ def test_pthread_join_and_asyncify(self):
83008300
# TODO Test with ASYNCIFY=1 https://github.com/emscripten-core/emscripten/issues/17552
83018301
self.require_jspi()
83028302
self.do_runf('core/test_pthread_join_and_asyncify.c', 'joining thread!\njoined thread!',
8303-
emcc_args=['-sJSPI_EXPORTS=run_thread',
8303+
emcc_args=['-sJSPI',
83048304
'-sEXIT_RUNTIME=1',
83058305
'-pthread', '-sPROXY_TO_PTHREAD'])
83068306

0 commit comments

Comments
 (0)