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

wasi-threads: an initial implementation #5484

Merged
merged 33 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fcf5f94
feat: remove mutability from the WasiCtx Table
haraldh Nov 25, 2022
0dd41b6
wasi-threads: add an initial implementation
abrown Dec 20, 2022
8c07438
review: remove LICENSE and README.md
abrown Jan 6, 2023
f17e05b
wasi-threads: factor out process exit logic
abrown Jan 9, 2023
82ce2de
review: work around `fd_fdstat_set_flags`
abrown Jan 26, 2023
9fa3bdf
fix: avoid unused import
abrown Jan 27, 2023
096a882
fix: add wasmtime-wasi-threads to publish script
abrown Jan 27, 2023
ac85c66
fix: use `Arc::get_mut` for other WASI proposals
abrown Jan 27, 2023
950420d
fix: re-add default wasi-nn feature
abrown Jan 27, 2023
b3066ed
review: fix redundant workspace member
abrown Jan 30, 2023
20fa82e
review: add TODO to remove randomness mutex
abrown Jan 30, 2023
ec2ff2c
review: improve thread exit documentation
abrown Jan 31, 2023
0078f81
review: wrap `Linker` with an `Arc` for faster cloning
abrown Jan 31, 2023
3923526
fix: allow wasi-nn to compile with threads changes
abrown Jan 31, 2023
2959abc
review: back out no-longer-needed changes from #5326
abrown Jan 31, 2023
e1a2945
review: move entry point check earlier
abrown Jan 31, 2023
8cfc619
review: catch host errors and exit all threads
abrown Jan 31, 2023
9043f84
fix: formatting
abrown Jan 31, 2023
d58613f
review: change error text
abrown Feb 1, 2023
54f52dd
review: remove more unused code
abrown Feb 1, 2023
642e841
fix: change back more of #5326
abrown Feb 1, 2023
e0daef9
fix: remove unused dependency
abrown Feb 1, 2023
2d7107c
review: conditionally `use std::sync::Arc`
abrown Feb 1, 2023
1db9948
review: add comments explaining `Arc::get_mut` limitations
abrown Feb 1, 2023
87e5e6d
review: rename `_module` to `module`
abrown Feb 1, 2023
e288b8b
review: test wasi-threads in CI
abrown Feb 1, 2023
004c923
fix: move `drop`
abrown Feb 1, 2023
ba2af19
fix: hack some more iterations on the spin waiter
abrown Feb 1, 2023
f734f04
test: use `wait`/`notify` to improve `threads.wat` test
abrown Feb 2, 2023
3005167
review: change `invalid_argument` to `not_supported`
abrown Feb 2, 2023
bc9d443
review: feature-gate and update `maybe_exit_on_error` documentation
abrown Feb 2, 2023
a167f76
review: add top-level README with embedder warning
abrown Feb 2, 2023
f3ece48
fix: remove unnecessary `mut`
abrown Feb 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Cargo.lock

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

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ wasmtime-cli-flags = { workspace = true }
wasmtime-cranelift = { workspace = true }
wasmtime-environ = { workspace = true }
wasmtime-wast = { workspace = true }
wasmtime-wasi = { workspace = true }
wasmtime-wasi = { workspace = true, features = ["exit"] }
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 }
libc = "0.2.60"
humantime = "2.0.0"
once_cell = { workspace = true }
listenfd = "1.0.0"
Expand Down Expand Up @@ -68,6 +68,7 @@ wasmtime-component-util = { workspace = true }
component-macro-test = { path = "crates/misc/component-macro-test" }
component-test-util = { workspace = true }
bstr = "0.2.17"
libc = "0.2.60"

[target.'cfg(windows)'.dev-dependencies]
windows-sys = { workspace = true, features = ["Win32_System_Memory"] }
Expand Down Expand Up @@ -124,6 +125,7 @@ wasmtime-wast = { path = "crates/wast", version = "=7.0.0" }
wasmtime-wasi = { path = "crates/wasi", version = "7.0.0" }
wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "7.0.0" }
wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "7.0.0" }
wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "7.0.0" }
wasmtime-component-util = { path = "crates/component-util", version = "=7.0.0" }
wasmtime-component-macro = { path = "crates/component-macro", version = "=7.0.0" }
wasmtime-asm-macros = { path = "crates/asm-macros", version = "=7.0.0" }
Expand Down Expand Up @@ -205,6 +207,7 @@ 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
1 change: 1 addition & 0 deletions ci/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

cargo test \
--features "test-programs/test_programs" \
--features wasi-threads \
--workspace \
--exclude 'wasmtime-wasi-*' \
--exclude wasi-crypto \
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 @@ -466,8 +470,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 @@ -494,19 +499,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 @@ -518,6 +527,7 @@ impl WasiModules {
wasi_common: false,
wasi_nn: false,
wasi_crypto: false,
wasi_threads: false,
}
}
}
Expand Down Expand Up @@ -663,8 +673,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 @@ -676,8 +687,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 @@ -693,8 +705,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 @@ -707,8 +720,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
1 change: 1 addition & 0 deletions crates/wasi-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ tracing = { workspace = true }
cap-std = { workspace = true }
cap-rand = { workspace = true }
bitflags = { workspace = true }
log = { workspace = true }

[target.'cfg(unix)'.dependencies]
rustix = { workspace = true, features = ["fs"] }
Expand Down
35 changes: 17 additions & 18 deletions crates/wasi-common/cap-std-sync/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,23 @@ impl WasiFile for File {
fn pollable(&self) -> Option<rustix::fd::BorrowedFd> {
Some(self.0.as_fd())
}

#[cfg(windows)]
fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {
Some(self.0.as_raw_handle_or_socket())
}
async fn datasync(&mut self) -> Result<(), Error> {
async fn datasync(&self) -> Result<(), Error> {
self.0.sync_data()?;
Ok(())
}
async fn sync(&mut self) -> Result<(), Error> {
async fn sync(&self) -> Result<(), Error> {
self.0.sync_all()?;
Ok(())
}
async fn get_filetype(&mut self) -> Result<FileType, Error> {
async fn get_filetype(&self) -> Result<FileType, Error> {
let meta = self.0.metadata()?;
Ok(filetype_from(&meta.file_type()))
}
async fn get_fdflags(&mut self) -> Result<FdFlags, Error> {
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
let fdflags = get_fd_flags(&self.0)?;
Ok(fdflags)
}
Expand All @@ -64,7 +63,7 @@ impl WasiFile for File {
self.0.set_fd_flags(set_fd_flags)?;
Ok(())
}
async fn get_filestat(&mut self) -> Result<Filestat, Error> {
async fn get_filestat(&self) -> Result<Filestat, Error> {
let meta = self.0.metadata()?;
Ok(Filestat {
device_id: meta.dev(),
Expand All @@ -77,62 +76,62 @@ impl WasiFile for File {
ctim: meta.created().map(|t| Some(t.into_std())).unwrap_or(None),
})
}
async fn set_filestat_size(&mut self, size: u64) -> Result<(), Error> {
async fn set_filestat_size(&self, size: u64) -> Result<(), Error> {
self.0.set_len(size)?;
Ok(())
}
async fn advise(&mut self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
self.0.advise(offset, len, convert_advice(advice))?;
Ok(())
}
async fn allocate(&mut self, offset: u64, len: u64) -> Result<(), Error> {
async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
self.0.allocate(offset, len)?;
Ok(())
}
async fn set_times(
&mut self,
&self,
atime: Option<wasi_common::SystemTimeSpec>,
mtime: Option<wasi_common::SystemTimeSpec>,
) -> Result<(), Error> {
self.0
.set_times(convert_systimespec(atime), convert_systimespec(mtime))?;
Ok(())
}
async fn read_vectored<'a>(&mut self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
let n = self.0.read_vectored(bufs)?;
Ok(n.try_into()?)
}
async fn read_vectored_at<'a>(
&mut self,
&self,
bufs: &mut [io::IoSliceMut<'a>],
offset: u64,
) -> Result<u64, Error> {
let n = self.0.read_vectored_at(bufs, offset)?;
Ok(n.try_into()?)
}
async fn write_vectored<'a>(&mut self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
let n = self.0.write_vectored(bufs)?;
Ok(n.try_into()?)
}
async fn write_vectored_at<'a>(
&mut self,
&self,
bufs: &[io::IoSlice<'a>],
offset: u64,
) -> Result<u64, Error> {
let n = self.0.write_vectored_at(bufs, offset)?;
Ok(n.try_into()?)
}
async fn seek(&mut self, pos: std::io::SeekFrom) -> Result<u64, Error> {
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
Ok(self.0.seek(pos)?)
}
async fn peek(&mut self, buf: &mut [u8]) -> Result<u64, Error> {
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
let n = self.0.peek(buf)?;
Ok(n.try_into()?)
}
async fn num_ready_bytes(&self) -> Result<u64, Error> {
fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(self.0.num_ready_bytes()?)
}
fn isatty(&mut self) -> bool {
fn isatty(&self) -> bool {
self.0.is_terminal()
}
}
Expand Down
10 changes: 5 additions & 5 deletions crates/wasi-common/cap-std-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ impl WasiCtxBuilder {
}
Ok(self)
}
pub fn stdin(mut self, f: Box<dyn WasiFile>) -> Self {
pub fn stdin(self, f: Box<dyn WasiFile>) -> Self {
self.0.set_stdin(f);
self
}
pub fn stdout(mut self, f: Box<dyn WasiFile>) -> Self {
pub fn stdout(self, f: Box<dyn WasiFile>) -> Self {
self.0.set_stdout(f);
self
}
pub fn stderr(mut self, f: Box<dyn WasiFile>) -> Self {
pub fn stderr(self, f: Box<dyn WasiFile>) -> Self {
self.0.set_stderr(f);
self
}
Expand All @@ -118,12 +118,12 @@ impl WasiCtxBuilder {
pub fn inherit_stdio(self) -> Self {
self.inherit_stdin().inherit_stdout().inherit_stderr()
}
pub fn preopened_dir(mut self, dir: Dir, guest_path: impl AsRef<Path>) -> Result<Self, Error> {
pub fn preopened_dir(self, dir: Dir, guest_path: impl AsRef<Path>) -> Result<Self, Error> {
let dir = Box::new(crate::dir::Dir::from_cap_std(dir));
self.0.push_preopened_dir(dir, guest_path)?;
Ok(self)
}
pub fn preopened_socket(mut self, fd: u32, socket: impl Into<Socket>) -> Result<Self, Error> {
pub fn preopened_socket(self, fd: u32, socket: impl Into<Socket>) -> Result<Self, Error> {
let socket: Socket = socket.into();
let file: Box<dyn WasiFile> = socket.into();

Expand Down
Loading