Skip to content

SHARED_WASMGC mechanism for sending data to new threads - #27472

Open
tlively wants to merge 2 commits into
mainfrom
shared-wasmgc-pthread-create
Open

SHARED_WASMGC mechanism for sending data to new threads#27472
tlively wants to merge 2 commits into
mainfrom
shared-wasmgc-pthread-create

Conversation

@tlively

@tlively tlively commented Aug 1, 2026

Copy link
Copy Markdown
Member

The experimental SHARED_WASMGC setting already allows for sharing data between threads in the form of a single global value initialized once on the main thread and then imported whenever the module is instantiated on a new worker. This is technically sufficient to bootstrap arbitrary shared state, including a user space message-passing primitives, as long as threads can be initialized with different thread IDs, but this is not very convenient.

Add another mechanism gated behind SHARED_WASMGC that allows sending specific shared values to newly spawned threads without a complicated user space TID-keyed parallel mailbox system. The new system depends on the module exporting two new globals, _gc_spawn_arg for outgoing values and _gc_thread_state for received values. When a thread calls pthread_create, its _gc_spawn_arg value is read and transferred via postMessage to the Worker where the new thread is created, where it is assigned to _gc_thread_state before pthread initialization.

Make both the existing globally shared state mechanism and the new thread state mechanism optional so users can use either or both as they wish.

The experimental SHARED_WASMGC setting already allows for sharing data between threads in the form of a single global value initialized once on the main thread and then imported whenever the module is instantiated on a new worker. This is technically sufficient to bootstrap arbitrary shared state, including a user space message-passing primitives, as long as threads can be initialized with different thread IDs, but this is not very convenient.

Add another mechanism gated behind SHARED_WASMGC that allows sending specific shared values to newly spawned threads without a complicated user space TID-keyed parallel mailbox system. The new system depends on the module exporting two new globals, _gc_spawn_arg for outgoing values and _gc_thread_state for received values. When a thread calls pthread_create, its _gc_spawn_arg value is read and transferred via postMessage to the Worker where the new thread is created, where it is assigned to _gc_thread_state before pthread initialization.

Make both the existing globally shared state mechanism and the new thread state mechanism optional so users can use either or both as they wish.
@tlively
tlively requested a review from sbc100 August 1, 2026 02:46
Comment thread src/lib/libpthread.js
#endif
#if SHARED_WASMGC
sharedHeapRootVal: wasmExports['_shared_heap_root'].value,
sharedHeapRootVal: wasmExports['_shared_heap_root']?.value ?? null,

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.

Do you need the ?? null it seems redundant to because if the null would only used if the LHS is already null-ish.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If we didn't have the ?? and there was no export, this would end up sending undefined. But then I guess the receiving thread would not do anything with the undefined, so it would be ok. I'll simplify this.

Comment thread src/lib/libpthread.js
#endif // OFFSCREENCANVAS_SUPPORT

#if SHARED_WASMGC
var gcSpawnArg = wasmExports['_gc_spawn_arg']?.value ?? null;

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.

ditto

Comment thread src/lib/libpthread.js
if (ENVIRONMENT_IS_PTHREAD && (!transferList.length || error)) {
if (ENVIRONMENT_IS_PTHREAD && (!transferList.length || error)
#if SHARED_WASMGC
&& gcSpawnArg === null

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 gcSpawnArg need to go in transferList? Is so then maybe this change is not needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, it can just be added as a normal property of the message.

Comment thread src/runtime_pthread.js
#endif
#if SHARED_WASMGC
if (wasmExports['_gc_thread_state']) {
wasmExports['_gc_thread_state'].value = msgData.gcSpawnArg ?? null;

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.

Do you need the ?? null here?

Comment thread test/test_other.py
)
''')

out_js = self.in_dir('test_shared_wasmgc_thread_state.js')

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.

You don't (or at least you shouldn't) need self.in_dir here

Comment thread test/test_other.py
out_wasm = self.in_dir('test_shared_wasmgc_thread_state.wasm')

self.run_process([
EMCC, '-pthread', '-sSHARED_WASMGC', '-sERROR_ON_UNDEFINED_SYMBOLS=0',

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.

Why is ERROR_ON_UNDEFINED_SYMBOLS=0 needed?

Comment thread test/test_other.py
self.run_process([
EMCC, '-pthread', '-sSHARED_WASMGC', '-sERROR_ON_UNDEFINED_SYMBOLS=0',
'-sEXIT_RUNTIME', '-sPROXY_TO_PTHREAD',
'-sEXPORTED_FUNCTIONS=_main,_print_int,_spawn_pthread,_join_pthread',

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.

Instead of EXPORTED_FUNCTIONS you can add `EMSCRIPTEN_KEEPALIVE in the source

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants