-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking issue for WebAssembly atomics #77839
Comments
Anything that can be done short-term to improve the status quo? Happy to contribute if I can. I currently do some shared memory mechanics through |
Adding some thoughts here:
What if this approach were partially modified? A new For example Rust could export |
Ah that's indeed a good point @kettle11! I would personally be wary of doing something Rust-specific, however, and would prefer that we work with other toolchain folks (e.g. C/C++/...) to figure out a standard set of APIs that could work for everyone. Most likely this seems like a WASI-level concern perhaps. My fear is that if we do something Rust-specific it's very tailor-made for just us and doesn't take other ecosystem's feedback into account, which I think is important to do to get a long-lasting convention we're confident in implementing in rust-lang/rust. |
are there any discussions happening with other toolchains currently? I think letting this stale is not the best idea tbh |
Just want to ping the questions @ImUrX brought up. Access to threads is a major feature in the browser, and while workers provide access to parallelism, they're extremely hard to work with. |
Some of us have been working on wasi-threads, a proposal for allowing WASI hosts to spawn threads. Much of the work to figure out the implementation details has happened for the C language in the wasi-libc repository. As a part of all of this work, I opened rust-lang/compiler-team#574 to add a |
I would be interested in helping with the browser piece, though I'm not sure how to get started. |
The webassembly threads proposal has reached phase 4(standardization).
Wouldn't it be the good time to implement threads for the Many crates that depend on |
For WASI we already have wasm32-wasi-preview1-threads which fully supports For wasm32-unknown-unknown implementing |
Have you tried targeting wasm32-unknown-emscripten, @temeddix? I think this is the way forward until such time that browsers have support for WASI and/or the component model. Alternatively there is a crate wasm-bindgen-rayon for using Rayon via wasm32-unknown-unknown that basically does what @bjorn3 described above. |
Thanks for the quick reply. I haven't used I am aware of those helper crates that try to bridge the gap, but it makes me write the code twice for native and web in many cases. The biggest problem was that |
As far as I know, we can interop with JavaScript with |
|
I understand, thank you for your explanation. Perhaps I should focus on |
3+ years after this is was opened there's still no clear path to moving multithreaded Wasm forward on web. Rust should aim to be one of the best languages to use for Wasm on Web and the absence of seamless threading threatens that. With each passing year we're accumulating more and more technical debt and hacks in the Rust ecosystem that bake in or work-around the assumption that multithreading is not available on web. The ideal reality is that using multithreaded Rust on web requires as few code changes as possible. Here are the two largest issues I see blocking that reality:
So here's a proposed solution:
These two changes would allow a significant chunk of the multithreaded Rust ecosystem to just work with only compilation flags (once libraries remove their workarounds for the fact that web isn't multithreaded). |
…=wesleywiser Stabilize Wasm target features that are in phase 4 and 5 This stabilizes the Wasm target features that are known to be working and in [phase 4 and 5](https://github.com/WebAssembly/proposals/tree/04fa8c810e1dc99ab399e41052a6e427ee988180). Feature stabilized: - [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions) - [Import/Export of Mutable Globals](https://github.com/WebAssembly/mutable-global) - [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops) - [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations) - [Extended Constant Expressions](https://github.com/WebAssembly/extended-const) Features not stabilized: - [Multi-value](https://github.com/WebAssembly/multi-value): requires rebuilding `std` rust-lang#73755. - [Reference Types](https://github.com/WebAssembly/reference-types): no point stabilizing without rust-lang#103516. - [Threads](https://github.com/webassembly/threads): requires rebuilding `std` rust-lang#77839. - [Relaxed SIMD](https://github.com/WebAssembly/relaxed-simd): separate PR rust-lang#117468. - [Multi Memory](https://github.com/WebAssembly/multi-memory): not implemented. See rust-lang#117457 (comment) for more context. Documentation: rust-lang/reference#1420 Tracking issue: rust-lang#44839
…=wesleywiser Stabilize Wasm target features that are in phase 4 and 5 This stabilizes the Wasm target features that are known to be working and in [phase 4 and 5](https://github.com/WebAssembly/proposals/tree/04fa8c810e1dc99ab399e41052a6e427ee988180). Feature stabilized: - [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions) - [Import/Export of Mutable Globals](https://github.com/WebAssembly/mutable-global) - [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops) - [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations) - [Extended Constant Expressions](https://github.com/WebAssembly/extended-const) Features not stabilized: - [Multi-value](https://github.com/WebAssembly/multi-value): requires rebuilding `std` rust-lang#73755. - [Reference Types](https://github.com/WebAssembly/reference-types): no point stabilizing without rust-lang#103516. - [Threads](https://github.com/webassembly/threads): requires rebuilding `std` rust-lang#77839. - [Relaxed SIMD](https://github.com/WebAssembly/relaxed-simd): separate PR rust-lang#117468. - [Multi Memory](https://github.com/WebAssembly/multi-memory): not implemented. See rust-lang#117457 (comment) for more context. Documentation: rust-lang/reference#1420 Tracking issue: rust-lang#44839
This is an issue intended to track the state of WebAssembly atomics support in Rust. For the WebAssembly target there is the threads proposal in WebAssembly which adds a number of instructions and a new kind of memory to the WebAssembly specification. The new instructions largely deal with atomic memory operations (e.g.
i32.atomic.add
), but also deal with synchronization between threads (memory.atomic.notify
). The threads proposal does not add an ability to spawn threads nor does it really define what threads are, but it's largely set up to have a wasm-instance-per-thread (not that this is super relevant for the standard library).As of the time of this writing the WebAssembly threads proposal is at stage 2 of the phases process. It is shipping in Chrome and in Firefox, however.
Rust's support for this proposal boils down to a few things:
-Ctarget-feature=+atomics
CLI flag to rustc. This causes codegen for atomic types likestd::sync::atomic
to use the atomic instructions.memory.atomic.notify
memory.atomic.wait32
memory.atomic.wait64
atomics
feature is enabled for the library at compile time. Namely it has custom implementations of:Condvar
Mutex
RwLock
In terms of toolchain, we're, as usual, inheriting a lot of the experience from LLVM as well. As usual the WebAssembly target uses LLD as the linker, but a number of options are passed by default when we're generating an executable compiled with threads (currently detected with
-Ctarget-feature=+atomics
). We instruct LLD to create a "shared" memory (which allows the memory to be shared across multiple wasm instances, how threading works on the web and in other engines), specifies a default maximum size for memory (this is required for shared memory, and normal wasm memories don't need to list a maximum), flags memory as being imported (since otherwise each instance would export a new memory and not share it!), and ensures that a few TLS/initialization-related symbols are exported.The symbols are perhaps the most interesting part here, so to go into them in some more detail:
__wasm_init_memory
- this is called once which initializes all data segments of memory (e.g. copies fromdata
intomemory
). This is intended to only happen once for the lifetime of a module at the beginning.__wasm_init_tls
- this is a function which is intended to be called once-per-instance and initializes thread-local information from a static area. The pointer to thread-local data is passed as the first argument. The pointer must be initialized according to__tls_size
and__tls_align
.Also as of today there is no dedicated target for wasm with atomics. The usage of
-Ctarget-feature=+atomics
was intended to help ship this feature ASAP on nightly Rust, but wasn't necessarily intended to be the final form of the feature. This means that if you want to use wasm and atomics you need to use Cargo's-Zbuild-std
feature to recompiled the standard library.Overall threads, wasm, and Rust I feel are not in a great spot. I'm unfortunately not certain about how best to move things forward. One thing we could do is to simply stabilize everything as-is and call it a day. As can be seen with memory initialization, imports, and TLS, lots of pieces are missing and are quite manual. Additionally
std::thread
has no hope of ever working with this model!In addition to the drawbacks previously mentioned, there's no way for TLS destructors to get implemented with any of this runtime support. The standard library ignores destructors registered on wasm and simply never runs them. Even if a runtime has a method of running TLS destructors, they don't have a way of hooking into the standard library to run the destructors.
I personally fear that the most likely scenario here is to simply stabilize what we have, bad user experience and all. Other possible alternatives (but not great ones?) might be:
I originally started writing this issue to stabilize the
core::arch
intrinsics, but upon reflection there are so many other unanswered questions in this space I'm no longer certain this is the best course of action. In any case I wanted to write down my thoughts on the current state of things, and hopefully have a canonical place this can be discussed for Rust-related things.The text was updated successfully, but these errors were encountered: