Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a new API that allows notifying that a Store has moved to a new thread #2822

Merged
merged 2 commits into from
Apr 16, 2021

Conversation

bnjbvr
Copy link
Member

@bnjbvr bnjbvr commented Apr 9, 2021

While potentially unsafe, https://docs.wasmtime.dev/examples-rust-multithreading.html#multithreading-without-send suggests that we can move over a Store and all that's attached to it to other threads. To make this a reality, a new API is required to notify the store that it's been moved over, so that it can initialize trap handling on this particular thread. I've made it an unsafe function, this should catch the eye of the users that they wouldn't need to use it in general. Also added a test that crashed before on a Mac.

@bnjbvr bnjbvr requested a review from alexcrichton April 9, 2021 14:00
@github-actions github-actions bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label Apr 9, 2021
@github-actions
Copy link

github-actions bot commented Apr 9, 2021

Subscribe to Label Action

cc @peterhuene

This issue or pull request has been labeled: "wasmtime:api"

Thus the following users have been cc'd because of the following labels:

  • peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@peterhuene
Copy link
Member

I wonder if we should be invoking init_traps automatically when we're about to resume a fiber inside of the async machinery just in case the future moved threads. It would reduce the use case of this to only times when users explicitly move a Store and related components to another thread.

@bnjbvr
Copy link
Member Author

bnjbvr commented Apr 12, 2021

It's a good point, and in fact it's already done automatically by wasmtime after resuming from a suspended fiber: https://github.com/bytecodealliance/wasmtime/blob/main/crates/runtime/src/traphandlers.rs#L436

Your remark makes me notice that this new API would also create a double standard: the runtime may automatically manage switching to a different thread in one case (async import causing wasm execution resuming on a different thread) when in another case one has to explicitly call the new API. The ubiquity of multithreaded future executors makes it justified in my opinion, but that's open to discussion!

@alexcrichton
Copy link
Member

Thanks for this! I agree that it's a little odd that this might automatically happen as part of a future execution but then it doesn't automatically happen otherwise, but I agree that it's probably ok for now. Can you add documentation about this function on the multithreading page and also link the documentation on this function to the multithreading page?

@bnjbvr bnjbvr force-pushed the store_notify_thread_switch branch from f52af76 to 7ec65c7 Compare April 16, 2021 08:15
@bnjbvr
Copy link
Member Author

bnjbvr commented Apr 16, 2021

Done, thanks!

@github-actions github-actions bot added the wasmtime:docs Issues related to Wasmtime's documentation label Apr 16, 2021
@alexcrichton alexcrichton merged commit ba73b45 into bytecodealliance:main Apr 16, 2021
@bnjbvr bnjbvr deleted the store_notify_thread_switch branch April 16, 2021 16:16
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Apr 28, 2021
Platforms Wasmtime supports may have per-thread initialization that
needs to run before WebAssembly. For example Unix needs to setup a
sigaltstack and macOS needs to set up mach ports. In bytecodealliance#2757 this
per-thread setup was moved out of the invocation of a wasm function,
relying on the lack of Send for Store to initialize the thread at Store
creation time and never worry about it later.

This conflicted with [wasmtime's desired multithreading
story](bytecodealliance#2812) so a new
[`Store::notify_switched_thread` was
added](bytecodealliance#2822) to
explicitly indicate a Store has moved to another thread (if it unsafely
did so).

It turns out though that it's not always easy to determine when a
`Store` moves to a new thread. For example the Go bindings for Wasmtime
are generally unaware when a goroutine switches OS threads. This led to
bytecodealliance/wasmtime-go#74 where a SIGILL
was left uncaught, making it appear that traps aren't working properly.

This commit revisits the decision in bytecodealliance#2757 and moves per-thread
initialization back into the path of calling into WebAssembly. This is
differently from before, though, where there's still only one TLS access
on the path of calling into WebAssembly, unlike before where it was a
separate access. This allows us to get the speed benefits of bytecodealliance#2757 as
well as the flexibility benefits of not having to explicitly move a
store between threads.

With this new ability this commit deletes the recently added
`Store::notify_switched_thread` method since it's no longer necessary.
alexcrichton added a commit that referenced this pull request Apr 28, 2021
* Bring back per-thread lazy initialization

Platforms Wasmtime supports may have per-thread initialization that
needs to run before WebAssembly. For example Unix needs to setup a
sigaltstack and macOS needs to set up mach ports. In #2757 this
per-thread setup was moved out of the invocation of a wasm function,
relying on the lack of Send for Store to initialize the thread at Store
creation time and never worry about it later.

This conflicted with [wasmtime's desired multithreading
story](#2812) so a new
[`Store::notify_switched_thread` was
added](#2822) to
explicitly indicate a Store has moved to another thread (if it unsafely
did so).

It turns out though that it's not always easy to determine when a
`Store` moves to a new thread. For example the Go bindings for Wasmtime
are generally unaware when a goroutine switches OS threads. This led to
bytecodealliance/wasmtime-go#74 where a SIGILL
was left uncaught, making it appear that traps aren't working properly.

This commit revisits the decision in #2757 and moves per-thread
initialization back into the path of calling into WebAssembly. This is
differently from before, though, where there's still only one TLS access
on the path of calling into WebAssembly, unlike before where it was a
separate access. This allows us to get the speed benefits of #2757 as
well as the flexibility benefits of not having to explicitly move a
store between threads.

With this new ability this commit deletes the recently added
`Store::notify_switched_thread` method since it's no longer necessary.

* Fix a test compiling
mchesser pushed a commit to mchesser/wasmtime that referenced this pull request May 24, 2021
… new thread (bytecodealliance#2822)

* Introduce a new API that allows notifying that a Store has moved to a new thread

* Add backlink to documentation, and mention the new API in the multithreading doc;
mchesser pushed a commit to mchesser/wasmtime that referenced this pull request May 24, 2021
* Bring back per-thread lazy initialization

Platforms Wasmtime supports may have per-thread initialization that
needs to run before WebAssembly. For example Unix needs to setup a
sigaltstack and macOS needs to set up mach ports. In bytecodealliance#2757 this
per-thread setup was moved out of the invocation of a wasm function,
relying on the lack of Send for Store to initialize the thread at Store
creation time and never worry about it later.

This conflicted with [wasmtime's desired multithreading
story](bytecodealliance#2812) so a new
[`Store::notify_switched_thread` was
added](bytecodealliance#2822) to
explicitly indicate a Store has moved to another thread (if it unsafely
did so).

It turns out though that it's not always easy to determine when a
`Store` moves to a new thread. For example the Go bindings for Wasmtime
are generally unaware when a goroutine switches OS threads. This led to
bytecodealliance/wasmtime-go#74 where a SIGILL
was left uncaught, making it appear that traps aren't working properly.

This commit revisits the decision in bytecodealliance#2757 and moves per-thread
initialization back into the path of calling into WebAssembly. This is
differently from before, though, where there's still only one TLS access
on the path of calling into WebAssembly, unlike before where it was a
separate access. This allows us to get the speed benefits of bytecodealliance#2757 as
well as the flexibility benefits of not having to explicitly move a
store between threads.

With this new ability this commit deletes the recently added
`Store::notify_switched_thread` method since it's no longer necessary.

* Fix a test compiling
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:docs Issues related to Wasmtime's documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants