Skip to content

Commit

Permalink
wasi-threads: add an initial implementation (WIP)
Browse files Browse the repository at this point in the history
This change demonstrates a first step at how `wasi-threads` might be
implemented in Wasmtime. It has hacks (described below), so it should
only be consided a highly-experimental, use-at-your-own-risk work in
progress.

The included test file can be run with the following incantation (the
`+nightly` is to allow the `Arc`-mutation hack):

```
cargo +nightly run -p wasmtime-cli --features wasi-threads -- \
    tests/all/cli_tests/threads.wat \
    --wasm-features threads --wasi-modules experimental-wasi-threads
```

Implementing this highlights two large issues still to be resolved:
- _`Host` sharing_: the approach taken here is to clone the `Linker`
  so that `wasi-threads` has a separate version of it and to share the
  `Host` among threads using an `Arc<Host>`. This does nothing to
  protect the `Host` state from concurrent access--which it must be in a
  future iteration of this. This could be done with, e.g., a `Mutex` per
  WASI proposal, preventing any concurrent access for any method in that
  proposal, but unfortunately the signature of `get_cx` prevents me from
  using the `MutexGuard`. Some more refactoring and thinking is
  necessary here; suggestions welcome.
- _Guest code traps_: this change has no way to recover from traps in
  the user function and return control to the thread entry point, which
  may be responsible for clean up (e.g., in C, `notify` any `pthread_join`ers
  that execution is complete).

Note that the associated CLI test fails, but probably just due to my
misunderstanding how to correctly tell the WAT library to enable the
threads proposal:

```
cargo +nightly test --features wasi-threads -p wasmtime-cli -- cli_tests
```
  • Loading branch information
abrown committed Dec 8, 2022
1 parent 44f8278 commit 2a12d62
Show file tree
Hide file tree
Showing 11 changed files with 559 additions and 40 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ wasmtime-wast = { workspace = true }
wasmtime-wasi = { workspace = true }
wasmtime-wasi-crypto = { workspace = true, optional = true }
wasmtime-wasi-nn = { workspace = true, optional = true }
wasmtime-wasi-threads = { workspace = true, optional = true }
clap = { workspace = true, features = ["color", "suggestions", "derive"] }
anyhow = { workspace = true }
target-lexicon = { workspace = true }
Expand Down Expand Up @@ -85,6 +86,7 @@ members = [
"crates/bench-api",
"crates/c-api",
"crates/cli-flags",
"crates/wasi-threads",
"crates/environ/fuzz",
"crates/jit-icache-coherence",
"crates/winch",
Expand Down Expand Up @@ -120,6 +122,7 @@ wasmtime-wast = { path = "crates/wast", version = "=4.0.0" }
wasmtime-wasi = { path = "crates/wasi", version = "4.0.0" }
wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "4.0.0" }
wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "4.0.0" }
wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "4.0.0" }
wasmtime-component-util = { path = "crates/component-util", version = "=4.0.0" }
wasmtime-component-macro = { path = "crates/component-macro", version = "=4.0.0" }
wasmtime-asm-macros = { path = "crates/asm-macros", version = "=4.0.0" }
Expand Down Expand Up @@ -180,13 +183,13 @@ default = [
"wasmtime/wat",
"wasmtime/parallel-compilation",
"vtune",
"wasi-nn",
"pooling-allocator",
]
jitdump = ["wasmtime/jitdump"]
vtune = ["wasmtime/vtune"]
wasi-crypto = ["dep:wasmtime-wasi-crypto"]
wasi-nn = ["dep:wasmtime-wasi-nn"]
wasi-threads = ["dep:wasmtime-wasi-threads"]
pooling-allocator = ["wasmtime/pooling-allocator", "wasmtime-cli-flags/pooling-allocator"]
all-arch = ["wasmtime/all-arch"]
posix-signals-on-macos = ["wasmtime/posix-signals-on-macos"]
Expand Down
36 changes: 25 additions & 11 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,17 @@ pub const SUPPORTED_WASI_MODULES: &[(&str, &str)] = &[
"wasi-common",
"enables support for the WASI common APIs, see https://github.com/WebAssembly/WASI",
),
(
"experimental-wasi-crypto",
"enables support for the WASI cryptography APIs (experimental), see https://github.com/WebAssembly/wasi-crypto",
),
(
"experimental-wasi-nn",
"enables support for the WASI neural network API (experimental), see https://github.com/WebAssembly/wasi-nn",
),
(
"experimental-wasi-crypto",
"enables support for the WASI cryptography APIs (experimental), see https://github.com/WebAssembly/wasi-crypto",
"experimental-wasi-threads",
"enables support for the WASI threading API (experimental), see https://github.com/WebAssembly/wasi-threads",
),
];

Expand Down Expand Up @@ -477,8 +481,9 @@ fn parse_wasi_modules(modules: &str) -> Result<WasiModules> {
let mut set = |module: &str, enable: bool| match module {
"" => Ok(()),
"wasi-common" => Ok(wasi_modules.wasi_common = enable),
"experimental-wasi-nn" => Ok(wasi_modules.wasi_nn = enable),
"experimental-wasi-crypto" => Ok(wasi_modules.wasi_crypto = enable),
"experimental-wasi-nn" => Ok(wasi_modules.wasi_nn = enable),
"experimental-wasi-threads" => Ok(wasi_modules.wasi_threads = enable),
"default" => bail!("'default' cannot be specified with other WASI modules"),
_ => bail!("unsupported WASI module '{}'", module),
};
Expand All @@ -505,19 +510,23 @@ pub struct WasiModules {
/// parts once the implementation allows for it (e.g. wasi-fs, wasi-clocks, etc.).
pub wasi_common: bool,

/// Enable the experimental wasi-nn implementation
/// Enable the experimental wasi-crypto implementation.
pub wasi_crypto: bool,

/// Enable the experimental wasi-nn implementation.
pub wasi_nn: bool,

/// Enable the experimental wasi-crypto implementation
pub wasi_crypto: bool,
/// Enable the experimental wasi-threads implementation.
pub wasi_threads: bool,
}

impl Default for WasiModules {
fn default() -> Self {
Self {
wasi_common: true,
wasi_nn: false,
wasi_crypto: false,
wasi_nn: false,
wasi_threads: false,
}
}
}
Expand All @@ -529,6 +538,7 @@ impl WasiModules {
wasi_common: false,
wasi_nn: false,
wasi_crypto: false,
wasi_threads: false,
}
}
}
Expand Down Expand Up @@ -674,8 +684,9 @@ mod test {
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: true,
wasi_crypto: false,
wasi_nn: false,
wasi_crypto: false
wasi_threads: false
}
);
}
Expand All @@ -687,8 +698,9 @@ mod test {
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: true,
wasi_crypto: false,
wasi_nn: false,
wasi_crypto: false
wasi_threads: false
}
);
}
Expand All @@ -704,8 +716,9 @@ mod test {
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: false,
wasi_crypto: false,
wasi_nn: true,
wasi_crypto: false
wasi_threads: false
}
);
}
Expand All @@ -718,8 +731,9 @@ mod test {
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: false,
wasi_crypto: false,
wasi_nn: false,
wasi_crypto: false
wasi_threads: false
}
);
}
Expand Down
21 changes: 21 additions & 0 deletions crates/wasi-threads/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "wasmtime-wasi-threads"
version.workspace = true
authors.workspace = true
description = "Wasmtime implementation of the wasi-threads API"
documentation = "https://docs.rs/wasmtime-wasi-nn"
license = "Apache-2.0 WITH LLVM-exception"
categories = ["wasm", "parallelism", "threads"]
keywords = ["webassembly", "wasm", "neural-network"]
repository = "https://github.com/bytecodealliance/wasmtime"
readme = "README.md"
edition.workspace = true

[dependencies]
anyhow = { workspace = true }
log = { workspace = true }
rand = "0.8"
wasmtime = { workspace = true }

[badges]
maintenance = { status = "experimental" }
Loading

0 comments on commit 2a12d62

Please sign in to comment.