Skip to content

Commit

Permalink
wasm: support rt-multi-thread with wasm32-wasi-preview1-threads (#6510)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Apr 24, 2024
1 parent a73d6bf commit 9ed5957
Show file tree
Hide file tree
Showing 14 changed files with 127 additions and 125 deletions.
33 changes: 25 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -909,16 +909,21 @@ jobs:
working-directory: tokio

wasm32-wasi:
name: wasm32-wasi
name: ${{ matrix.target }}
needs: basics
runs-on: ubuntu-latest
strategy:
matrix:
target:
- wasm32-wasi
- wasm32-wasi-preview1-threads
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
targets: wasm32-wasi
targets: ${{ matrix.target }}

# Install dependencies
- name: Install cargo-hack, wasmtime, and cargo-wasi
Expand All @@ -928,27 +933,39 @@ jobs:

- uses: Swatinem/rust-cache@v2
- name: WASI test tokio full
run: cargo test -p tokio --target wasm32-wasi --features full
run: cargo test -p tokio --target ${{ matrix.target }} --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864

- name: WASI test tokio-util full
run: cargo test -p tokio-util --target wasm32-wasi --features full
run: cargo test -p tokio-util --target ${{ matrix.target }} --features full
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864

- name: WASI test tokio-stream
run: cargo test -p tokio-stream --target wasm32-wasi --features time,net,io-util,sync
run: cargo test -p tokio-stream --target ${{ matrix.target }} --features time,net,io-util,sync
env:
CARGO_TARGET_WASM32_WASI_RUNNER: "wasmtime run --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings
CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864

- name: test tests-integration --features wasi-rt
# TODO: this should become: `cargo hack wasi test --each-feature`
run: cargo wasi test --test rt_yield --features wasi-rt
if: matrix.target == 'wasm32-wasi'
working-directory: tests-integration

- name: test tests-integration --features wasi-threads-rt
run: cargo test --target ${{ matrix.target }} --features wasi-threads-rt
if: matrix.target == 'wasm32-wasi-preview1-threads'
working-directory: tests-integration
env:
CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864

check-external-types:
name: check-external-types (${{ matrix.os }})
Expand Down
1 change: 1 addition & 0 deletions tests-integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ rt-process-signal = ["rt-net", "tokio/process", "tokio/signal"]
# This is an explicit feature so we can use `cargo hack` testing single features
# instead of all possible permutations.
wasi-rt = ["rt", "macros", "sync"]
wasi-threads-rt = ["wasi-rt", "rt-multi-thread"]

full = [
"macros",
Expand Down
6 changes: 1 addition & 5 deletions tests-integration/tests/macros_main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#![cfg(all(
feature = "macros",
feature = "rt-multi-thread",
not(target_os = "wasi")
))]
#![cfg(all(feature = "macros", feature = "rt-multi-thread"))]

#[tokio::main]
async fn basic_main() -> usize {
Expand Down
5 changes: 4 additions & 1 deletion tests-integration/tests/macros_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use futures::channel::oneshot;
use futures::executor::block_on;
use std::thread;

#[cfg_attr(target_os = "wasi", ignore = "WASI: std::thread::spawn not supported")]
#[cfg_attr(
not(feature = "rt-multi-thread"),
ignore = "WASI: std::thread::spawn not supported"
)]
#[test]
fn join_with_select() {
block_on(async {
Expand Down
2 changes: 0 additions & 2 deletions tokio-util/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

#[cfg(tokio_unstable)]
mod join_map;
#[cfg(not(target_os = "wasi"))]
mod spawn_pinned;
#[cfg(not(target_os = "wasi"))]
pub use spawn_pinned::LocalPoolHandle;

#[cfg(tokio_unstable)]
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/macros/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ macro_rules! cfg_not_rt {
macro_rules! cfg_rt_multi_thread {
($($item:item)*) => {
$(
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
$item
)*
Expand Down
8 changes: 4 additions & 4 deletions tokio/src/runtime/blocking/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ impl BlockingSchedule {
scheduler::Handle::CurrentThread(handle) => {
handle.driver.clock.inhibit_auto_advance();
}
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
scheduler::Handle::MultiThread(_) => {}
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
scheduler::Handle::MultiThreadAlt(_) => {}
}
}
Expand All @@ -45,9 +45,9 @@ impl task::Schedule for BlockingSchedule {
handle.driver.clock.allow_auto_advance();
handle.driver.unpark();
}
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
scheduler::Handle::MultiThread(_) => {}
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
scheduler::Handle::MultiThreadAlt(_) => {}
}
}
Expand Down
58 changes: 28 additions & 30 deletions tokio/src/runtime/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ pub(crate) type ThreadNameFn = std::sync::Arc<dyn Fn() -> String + Send + Sync +
#[derive(Clone, Copy)]
pub(crate) enum Kind {
CurrentThread,
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
MultiThread,
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
MultiThreadAlt,
}

Expand All @@ -224,35 +224,33 @@ impl Builder {
Builder::new(Kind::CurrentThread, EVENT_INTERVAL)
}

cfg_not_wasi! {
/// Returns a new builder with the multi thread scheduler selected.
/// Returns a new builder with the multi thread scheduler selected.
///
/// Configuration methods can be chained on the return value.
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
pub fn new_multi_thread() -> Builder {
// The number `61` is fairly arbitrary. I believe this value was copied from golang.
Builder::new(Kind::MultiThread, 61)
}

cfg_unstable! {
/// Returns a new builder with the alternate multi thread scheduler
/// selected.
///
/// The alternate multi threaded scheduler is an in-progress
/// candidate to replace the existing multi threaded scheduler. It
/// currently does not scale as well to 16+ processors.
///
/// This runtime flavor is currently **not considered production
/// ready**.
///
/// Configuration methods can be chained on the return value.
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
pub fn new_multi_thread() -> Builder {
pub fn new_multi_thread_alt() -> Builder {
// The number `61` is fairly arbitrary. I believe this value was copied from golang.
Builder::new(Kind::MultiThread, 61)
}

cfg_unstable! {
/// Returns a new builder with the alternate multi thread scheduler
/// selected.
///
/// The alternate multi threaded scheduler is an in-progress
/// candidate to replace the existing multi threaded scheduler. It
/// currently does not scale as well to 16+ processors.
///
/// This runtime flavor is currently **not considered production
/// ready**.
///
/// Configuration methods can be chained on the return value.
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
pub fn new_multi_thread_alt() -> Builder {
// The number `61` is fairly arbitrary. I believe this value was copied from golang.
Builder::new(Kind::MultiThreadAlt, 61)
}
Builder::new(Kind::MultiThreadAlt, 61)
}
}

Expand Down Expand Up @@ -697,9 +695,9 @@ impl Builder {
pub fn build(&mut self) -> io::Result<Runtime> {
match &self.kind {
Kind::CurrentThread => self.build_current_thread_runtime(),
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
Kind::MultiThread => self.build_threaded_runtime(),
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
Kind::MultiThreadAlt => self.build_alt_threaded_runtime(),
}
}
Expand All @@ -708,9 +706,9 @@ impl Builder {
driver::Cfg {
enable_pause_time: match self.kind {
Kind::CurrentThread => true,
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
Kind::MultiThread => false,
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
Kind::MultiThreadAlt => false,
},
enable_io: self.enable_io,
Expand Down
8 changes: 4 additions & 4 deletions tokio/src/runtime/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,9 @@ impl Handle {
pub fn runtime_flavor(&self) -> RuntimeFlavor {
match self.inner {
scheduler::Handle::CurrentThread(_) => RuntimeFlavor::CurrentThread,
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
scheduler::Handle::MultiThread(_) => RuntimeFlavor::MultiThread,
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
scheduler::Handle::MultiThreadAlt(_) => RuntimeFlavor::MultiThreadAlt,
}
}
Expand Down Expand Up @@ -385,9 +385,9 @@ impl Handle {
pub fn id(&self) -> runtime::Id {
let owned_id = match &self.inner {
scheduler::Handle::CurrentThread(handle) => handle.owned_id(),
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
scheduler::Handle::MultiThread(handle) => handle.owned_id(),
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
scheduler::Handle::MultiThreadAlt(handle) => handle.owned_id(),
};
owned_id.into()
Expand Down
78 changes: 38 additions & 40 deletions tokio/src/runtime/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ pub(super) enum Scheduler {
CurrentThread(CurrentThread),

/// Execute tasks across multiple threads.
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
MultiThread(MultiThread),

/// Execute tasks across multiple threads.
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
MultiThreadAlt(MultiThreadAlt),
}

Expand All @@ -147,40 +147,38 @@ impl Runtime {
}
}

cfg_not_wasi! {
/// Creates a new runtime instance with default configuration values.
///
/// This results in the multi threaded scheduler, I/O driver, and time driver being
/// initialized.
///
/// Most applications will not need to call this function directly. Instead,
/// they will use the [`#[tokio::main]` attribute][main]. When a more complex
/// configuration is necessary, the [runtime builder] may be used.
///
/// See [module level][mod] documentation for more details.
///
/// # Examples
///
/// Creating a new `Runtime` with default configuration values.
///
/// ```
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new()
/// .unwrap();
///
/// // Use the runtime...
/// ```
///
/// [mod]: index.html
/// [main]: ../attr.main.html
/// [threaded scheduler]: index.html#threaded-scheduler
/// [runtime builder]: crate::runtime::Builder
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
pub fn new() -> std::io::Result<Runtime> {
Builder::new_multi_thread().enable_all().build()
}
/// Creates a new runtime instance with default configuration values.
///
/// This results in the multi threaded scheduler, I/O driver, and time driver being
/// initialized.
///
/// Most applications will not need to call this function directly. Instead,
/// they will use the [`#[tokio::main]` attribute][main]. When a more complex
/// configuration is necessary, the [runtime builder] may be used.
///
/// See [module level][mod] documentation for more details.
///
/// # Examples
///
/// Creating a new `Runtime` with default configuration values.
///
/// ```
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new()
/// .unwrap();
///
/// // Use the runtime...
/// ```
///
/// [mod]: index.html
/// [main]: ../attr.main.html
/// [threaded scheduler]: index.html#threaded-scheduler
/// [runtime builder]: crate::runtime::Builder
#[cfg(feature = "rt-multi-thread")]
#[cfg_attr(docsrs, doc(cfg(feature = "rt-multi-thread")))]
pub fn new() -> std::io::Result<Runtime> {
Builder::new_multi_thread().enable_all().build()
}

/// Returns a handle to the runtime's spawner.
Expand Down Expand Up @@ -347,9 +345,9 @@ impl Runtime {

match &self.scheduler {
Scheduler::CurrentThread(exec) => exec.block_on(&self.handle.inner, future),
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
Scheduler::MultiThread(exec) => exec.block_on(&self.handle.inner, future),
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
Scheduler::MultiThreadAlt(exec) => exec.block_on(&self.handle.inner, future),
}
}
Expand Down Expand Up @@ -469,13 +467,13 @@ impl Drop for Runtime {
let _guard = context::try_set_current(&self.handle.inner);
current_thread.shutdown(&self.handle.inner);
}
#[cfg(all(feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(feature = "rt-multi-thread")]
Scheduler::MultiThread(multi_thread) => {
// The threaded scheduler drops its tasks on its worker threads, which is
// already in the runtime's context.
multi_thread.shutdown(&self.handle.inner);
}
#[cfg(all(tokio_unstable, feature = "rt-multi-thread", not(target_os = "wasi")))]
#[cfg(all(tokio_unstable, feature = "rt-multi-thread"))]
Scheduler::MultiThreadAlt(multi_thread) => {
// The threaded scheduler drops its tasks on its worker threads, which is
// already in the runtime's context.
Expand Down
5 changes: 1 addition & 4 deletions tokio/src/runtime/scheduler/inject/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ impl<T: 'static> Shared<T> {
}

// Kind of annoying to have to include the cfg here
#[cfg(any(
tokio_taskdump,
all(feature = "rt-multi-thread", not(target_os = "wasi"))
))]
#[cfg(any(tokio_taskdump, feature = "rt-multi-thread"))]
pub(crate) fn is_closed(&self, synced: &Synced) -> bool {
synced.is_closed
}
Expand Down

0 comments on commit 9ed5957

Please sign in to comment.