From 9ee3f909abda3b8e50a147acdbf64c012e09988c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Aug 2026 10:53:12 -0700 Subject: [PATCH 1/2] Prepare tests to run on WASIp3 This commit updates various bits/pieces of infrastructure/tests to ensure that all tests can run on WASIp3 targets in addition to WASIp2 targets. This isn't yet added to CI because toolchains aren't published quite just yet, but everything's been tested locally for now. The changes here are: * The wit-component/wasm-tools dependencies are updated. * Task state in Rust bindings is now stored in a TLS variable for wasip3 instead of a context slot like in wasip2. This is because context slots are taken in wasip3 for ABI details (stack pointer and TLS base). * Task state management in TLS on no-std builds requires an auxiliary C file to store the actual thread local. * Tests in C using context slots have a similar change where for wasip2 they use the context slot but for wasip3 they're now using a TLS variable. * Tests in Rust using TLS and relying on that being global are updated to use `static` variables instead as on wasip3 targets TLS is per-task, not global. --- Cargo.lock | 76 +++++++-------- Cargo.toml | 14 +-- ci/rebuild-libwit-bindgen-cabi.sh | 23 +++++ crates/guest-rust/src/rt/async_support.rs | 88 ++++++++++++------ .../src/rt/async_support/wasip3_context.rs | 8 ++ .../guest-rust/src/rt/libwit_bindgen_cabi.a | Bin 858 -> 1140 bytes .../src/rt/wit_bindgen_cabi_wasip3.c | 10 ++ .../src/rt/wit_bindgen_cabi_wasip3.o | Bin 260 -> 462 bytes tests/runtime/cancel-import/test.c | 28 +++++- tests/runtime/future-cancel-read/test.c | 26 +++++- .../future-close-then-receive-read/test.rs | 10 +- .../stream-write-cancel/holder-service.rs | 24 ++--- tests/runtime/pending-import/test.c | 25 ++++- tests/runtime/ping-pong/test.c | 45 ++++++++- 14 files changed, 271 insertions(+), 106 deletions(-) create mode 100644 crates/guest-rust/src/rt/async_support/wasip3_context.rs diff --git a/Cargo.lock b/Cargo.lock index 778453fa6..eeefa4da9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1024,7 +1024,7 @@ name = "test-helpers" version = "0.0.0" dependencies = [ "codegen-macro", - "wasm-encoder 0.254.0", + "wasm-encoder 0.257.0", "wit-bindgen-core", "wit-component", "wit-parser", @@ -1221,9 +1221,9 @@ checksum = "1b6c48003fe59c201c97a7786ff55feabe6b6f83b598aa9ff5bcc4f94d940bf3" [[package]] name = "wasm-compose" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd717357bff09b5f1ea49aea8ed1cd149b0c521823a1cc70bc2ac16b90b651a" +checksum = "f50dca8ad84209376ecd75df8ce737120c02dcb0d6cde03ce472d5aa582173ed" dependencies = [ "anyhow", "heck", @@ -1234,8 +1234,8 @@ dependencies = [ "serde_derive", "serde_yaml2", "smallvec", - "wasm-encoder 0.254.0", - "wasmparser 0.254.0", + "wasm-encoder 0.257.0", + "wasmparser 0.257.0", "wat", ] @@ -1251,12 +1251,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09480d646178e5fdd12bb06e812d0af9a3a191dbc9cd697fdc86687beade7393" +checksum = "aa129869530182297573e069436f29c6275c45ab5491376cd55f0b358a74f4af" dependencies = [ "leb128fmt", - "wasmparser 0.254.0", + "wasmparser 0.257.0", ] [[package]] @@ -1280,14 +1280,14 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01df5f3b4ca7881e843f3bc0fb8a3905d79c68692250dcb8e33e698705ccdb6" +checksum = "1b2c8b8ed96d4b3b889b77228e38db7bf62cf8460c4bd433c6c3b4c21a428465" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.254.0", - "wasmparser 0.254.0", + "wasm-encoder 0.257.0", + "wasmparser 0.257.0", ] [[package]] @@ -1305,9 +1305,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5769a29f799fbab136aaf65b4fe5384cd7d93fe6fc9ba0dcb6c8382a1f16e27" +checksum = "277090e6e7fff4e570dd15d9fff10bcebac3aa386239d1b3c15b0488f38b9c63" dependencies = [ "bitflags", "hashbrown 0.17.1", @@ -1318,22 +1318,22 @@ dependencies = [ [[package]] name = "wast" -version = "254.0.0" +version = "257.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ed4dfc8f6b9fc38b231065e2cdfbf7359af5ab945990abf09658dcc63c3e32" +checksum = "47c1ab2ea6570a5b404a8aae38c009dfdceb0685114abe27d0bf9240aeaf06f5" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width 0.2.2", - "wasm-encoder 0.254.0", + "wasm-encoder 0.257.0", ] [[package]] name = "wat" -version = "1.254.0" +version = "1.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7127f7f9b8f127c879991cecd35f494e4628bae1b0874c681414d8d8831e952c" +checksum = "0e786a1328d9061fcc63f1223d1ea7080fdc0a6a6fc7300e13239ed6eeb15760" dependencies = [ "wast", ] @@ -1378,8 +1378,8 @@ dependencies = [ "clap", "heck", "indexmap", - "wasm-encoder 0.254.0", - "wasm-metadata 0.254.0", + "wasm-encoder 0.257.0", + "wasm-metadata 0.257.0", "wit-bindgen-core", "wit-component", ] @@ -1391,7 +1391,7 @@ dependencies = [ "anyhow", "clap", "env_logger", - "wasm-encoder 0.254.0", + "wasm-encoder 0.257.0", "wit-bindgen-c", "wit-bindgen-core", "wit-bindgen-cpp", @@ -1424,8 +1424,8 @@ dependencies = [ "heck", "indexmap", "test-helpers", - "wasm-encoder 0.254.0", - "wasm-metadata 0.254.0", + "wasm-encoder 0.257.0", + "wasm-metadata 0.257.0", "wit-bindgen-c", "wit-bindgen-core", "wit-component", @@ -1441,7 +1441,7 @@ dependencies = [ "heck", "indexmap", "regex", - "wasm-metadata 0.254.0", + "wasm-metadata 0.257.0", "wit-bindgen-core", "wit-component", "wit-parser", @@ -1454,8 +1454,8 @@ dependencies = [ "anyhow", "clap", "heck", - "wasm-encoder 0.254.0", - "wasm-metadata 0.254.0", + "wasm-encoder 0.257.0", + "wasm-metadata 0.257.0", "wit-bindgen-core", "wit-component", ] @@ -1496,7 +1496,7 @@ dependencies = [ "serde_json", "syn", "test-helpers", - "wasm-metadata 0.254.0", + "wasm-metadata 0.257.0", "wit-bindgen", "wit-bindgen-core", "wit-component", @@ -1535,8 +1535,8 @@ dependencies = [ "wac-types", "wasi-preview1-component-adapter-provider", "wasm-compose", - "wasm-encoder 0.254.0", - "wasmparser 0.254.0", + "wasm-encoder 0.257.0", + "wasmparser 0.257.0", "wat", "wit-bindgen-csharp", "wit-component", @@ -1545,9 +1545,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e65bb94c369b3c4741ce3d1d2704b1fec93db7c540df0e521a097e7ceeb5be" +checksum = "08062174a2912604fca675aa83c42fa0605891ba966d55de2706e10d1c38cada" dependencies = [ "anyhow", "bitflags", @@ -1556,18 +1556,18 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.254.0", - "wasm-metadata 0.254.0", - "wasmparser 0.254.0", + "wasm-encoder 0.257.0", + "wasm-metadata 0.257.0", + "wasmparser 0.257.0", "wat", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.254.0" +version = "0.257.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1655131e4f7d3f0cb141f6eca71315ca40eff0f3d4de7cff0a82bacedd8c89b4" +checksum = "90b040adb88ce81a73961591cd6ab0bd9bcec21de6c49789216b3760787fe924" dependencies = [ "anyhow", "hashbrown 0.17.1", @@ -1579,7 +1579,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-ident", - "wasmparser 0.254.0", + "wasmparser 0.257.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 092648e32..3061a05f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,13 +48,13 @@ syn = { version = "2.0.89", features = ["printing"] } futures = "0.3.31" macro-string = "0.2.0" -wat = "1.254.0" -wasmparser = "0.254.0" -wasm-encoder = "0.254.0" -wasm-metadata = { version = "0.254.0", default-features = false } -wit-parser = "0.254.0" -wit-component = "0.254.0" -wasm-compose = "0.254.0" +wat = "1.257.0" +wasmparser = "0.257.0" +wasm-encoder = "0.257.0" +wasm-metadata = { version = "0.257.0", default-features = false } +wit-parser = "0.257.0" +wit-component = "0.257.0" +wasm-compose = "0.257.0" wit-bindgen-core = { path = 'crates/core', version = '0.60.0' } wit-bindgen-c = { path = 'crates/c', version = '0.60.0' } diff --git a/ci/rebuild-libwit-bindgen-cabi.sh b/ci/rebuild-libwit-bindgen-cabi.sh index bbb57c1ea..6f11e1055 100755 --- a/ci/rebuild-libwit-bindgen-cabi.sh +++ b/ci/rebuild-libwit-bindgen-cabi.sh @@ -42,6 +42,8 @@ set -ex version=$(./ci/print-current-version.sh | sed 's/\./_/g') realloc=cabi_realloc_wit_bindgen_$version +wasip3_get=wit_bindgen_${version}_get_task_context +wasip3_set=wit_bindgen_${version}_set_task_context rm -f crates/guest-rust/src/rt/wit_bindgen_*.{rs,o,c} rm -f crates/guest-rust/src/rt/libwit_bindgen_cabi.a @@ -60,6 +62,17 @@ pub unsafe extern "C" fn $realloc( } EOF +cat >./crates/guest-rust/src/rt/async_support/wasip3_context.rs <<-EOF +// This file is generated by $0 + +unsafe extern "C" { + #[link_name = "$wasip3_get"] + pub fn get() -> *mut u8; + #[link_name = "$wasip3_set"] + pub fn set(ptr: *mut u8); +} +EOF + cat >./crates/guest-rust/src/rt/wit_bindgen_cabi_realloc.c <<-EOF // This file is generated by $0 @@ -86,6 +99,16 @@ void *wasip3_task_set(void *ptr) { WASIP3_TASK = ptr; return ret; } + +static _Thread_local void *task_context = NULL; + +void *$wasip3_get(void) { + return task_context; +} + +void $wasip3_set(void *ptr) { + task_context = ptr; +} EOF build() { diff --git a/crates/guest-rust/src/rt/async_support.rs b/crates/guest-rust/src/rt/async_support.rs index 680e5f9ab..a8b11bb25 100644 --- a/crates/guest-rust/src/rt/async_support.rs +++ b/crates/guest-rust/src/rt/async_support.rs @@ -537,6 +537,60 @@ impl ReturnCode { } } +#[cfg(not(target_env = "p3"))] +mod task_state { + pub fn get() -> *mut u8 { + extern_wasm! { + #[link(wasm_import_module = "$root")] + unsafe extern "C" { + #[link_name = "[context-get-0]"] + fn get() -> *mut u8; + } + } + + unsafe { get() } + } + + pub unsafe fn set(value: *mut u8) { + extern_wasm! { + #[link(wasm_import_module = "$root")] + unsafe extern "C" { + #[link_name = "[context-set-0]"] + fn set(value: *mut u8); + } + } + + unsafe { set(value) } + } +} + +#[cfg(all(target_env = "p3", feature = "std"))] +mod task_state { + std::thread_local!(static TASK_STATE: std::cell::Cell<*mut u8> = std::cell::Cell::new(std::ptr::null_mut())); + + pub fn get() -> *mut u8 { + TASK_STATE.with(|c| c.get()) + } + + pub unsafe fn set(value: *mut u8) { + TASK_STATE.with(|c| c.set(value)) + } +} + +#[cfg(all(target_env = "p3", not(feature = "std")))] +mod wasip3_context; +#[cfg(all(target_env = "p3", not(feature = "std")))] +mod task_state { + + pub fn get() -> *mut u8 { + unsafe { super::wasip3_context::get() } + } + + pub unsafe fn set(value: *mut u8) { + unsafe { super::wasip3_context::set(value) } + } +} + /// Starts execution of the `task` provided, an asynchronous computation. /// /// This is used for async-lifted exports at their definition site. The @@ -557,8 +611,8 @@ pub fn start_task(task: impl Future + 'static) -> i32 { // task, and then `callback` is only invoked when context-local storage is // valid. unsafe { - assert!(context_get().is_null()); - context_set(state.cast()); + assert!(task_state::get().is_null()); + task_state::set(state.cast()); callback(EVENT_NONE, 0, 0) as i32 } } @@ -574,10 +628,10 @@ pub unsafe fn callback(event0: u32, event1: u32, event2: u32) -> u32 { // Acquire our context-local state, assert it's not-null, and then reset // the state to null while we're running to help prevent any unintended // usage. - let state = context_get().cast::>(); + let state = task_state::get().cast::>(); assert!(!state.is_null()); unsafe { - context_set(ptr::null_mut()); + task_state::set(ptr::null_mut()); } // Use `state` to run the `callback` function in the context of our event @@ -589,7 +643,7 @@ pub unsafe fn callback(event0: u32, event1: u32, event2: u32) -> u32 { if rc == CallbackCode::Exit { drop(Box::from_raw(state)); } else { - context_set(state.cast()); + task_state::set(state.cast()); } rtdebug!(" => (cb) {rc:?}"); rc.encode() @@ -723,30 +777,6 @@ pub fn backpressure_dec() { unsafe { backpressure_dec() } } -fn context_get() -> *mut u8 { - extern_wasm! { - #[link(wasm_import_module = "$root")] - unsafe extern "C" { - #[link_name = "[context-get-0]"] - fn get() -> *mut u8; - } - } - - unsafe { get() } -} - -unsafe fn context_set(value: *mut u8) { - extern_wasm! { - #[link(wasm_import_module = "$root")] - unsafe extern "C" { - #[link_name = "[context-set-0]"] - fn set(value: *mut u8); - } - } - - unsafe { set(value) } -} - #[doc(hidden)] pub struct TaskCancelOnDrop { _priv: (), diff --git a/crates/guest-rust/src/rt/async_support/wasip3_context.rs b/crates/guest-rust/src/rt/async_support/wasip3_context.rs new file mode 100644 index 000000000..be92be98d --- /dev/null +++ b/crates/guest-rust/src/rt/async_support/wasip3_context.rs @@ -0,0 +1,8 @@ +// This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh + +unsafe extern "C" { + #[link_name = "wit_bindgen_0_60_0_get_task_context"] + pub fn get() -> *mut u8; + #[link_name = "wit_bindgen_0_60_0_set_task_context"] + pub fn set(ptr: *mut u8); +} diff --git a/crates/guest-rust/src/rt/libwit_bindgen_cabi.a b/crates/guest-rust/src/rt/libwit_bindgen_cabi.a index fe3af6e29064341999289b5a5dd927c41cbe65a6..772ea62f696220bb2ec0596bc226db4d35f70b8c 100644 GIT binary patch delta 495 zcmZvY&q~8U5XNV=F)2y0{<{jL6%{mTty1(PK|M$h7Akm5H|;j2O;XHm(OVQec(n8^ zUcGqmA$$ohzJw3p1{G@QzzoC3?9BJu5A`eixL??*RtrDT(g8pLz$yUg{pF~!TEF&% zLCLBR|-)Rpb!EOZ1nBmhiP%e+I%(tgkT-&QnoTWTOc^l_5EleR2>ISS+Kx{?Q21&j9225XWF|pbJE}ic)j(ll7eaU0hk1*x4Al Md6*a`yE3T&0A3Cy_W%F@ diff --git a/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.c b/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.c index 2e4a50617..387d2f2c0 100644 --- a/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.c +++ b/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.c @@ -10,3 +10,13 @@ void *wasip3_task_set(void *ptr) { WASIP3_TASK = ptr; return ret; } + +static _Thread_local void *task_context = NULL; + +void *wit_bindgen_0_60_0_get_task_context(void) { + return task_context; +} + +void wit_bindgen_0_60_0_set_task_context(void *ptr) { + task_context = ptr; +} diff --git a/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.o b/crates/guest-rust/src/rt/wit_bindgen_cabi_wasip3.o index 5e7eea4c81deaa0fe19f7b3c0986b3920be62ca6..a9c0f5f04a9c58f48e9d02704316c9de493c8c34 100644 GIT binary patch literal 462 zcmZuu+e*Vg5S^K%jdZK6mk;O#M9>7GQ1D5D`XGH!sNmyv)2=aXl1g@K^(hKI_$mH~ z|K%oDXu*XYcFxS1Ifn(I5(EI;u|}92rhgI7+3+cp{T|_DX;SyvK{ed)KuBQCRBDZwol*# zvyDCg-(Eew(J`84Q5w?L=erqDg$gv5LPbwKu7#R$B{emT9(L~!uWx(&&L0i{Y_PGr zj5H6TbP~#xpYr~x38B=#wDCOE@`6}#C(+iaH)>aejmeBfC z0_fB-8PCVw#m(iFU3IF+>IBXqvJ)GeGi2w+x7W}jD+E4Bp%set = test_waitable_set_new(); test_waitable_join(task->future, task->set); - test_context_set_0(task); + assert(get_task() == NULL); + set_task(task); return TEST_CALLBACK_CODE_WAIT(task->set); } test_callback_code_t exports_test_pending_import_callback(test_event_t *event) { - struct my_task *task = (struct my_task*) test_context_get_0(); + struct my_task *task = get_task(); + set_task(NULL); + test_waitable_join(task->future, 0); if (event->event == TEST_EVENT_CANCEL) { assert(event->waitable == 0); assert(event->code == 0); @@ -40,7 +63,6 @@ test_callback_code_t exports_test_pending_import_callback(test_event_t *event) { exports_test_pending_import_return(); } - test_waitable_join(task->future, 0); exports_test_future_void_drop_readable(task->future); test_waitable_set_drop(task->set); diff --git a/tests/runtime/future-cancel-read/test.c b/tests/runtime/future-cancel-read/test.c index f04b56ee4..278e3bcc6 100644 --- a/tests/runtime/future-cancel-read/test.c +++ b/tests/runtime/future-cancel-read/test.c @@ -40,6 +40,26 @@ struct start_read_then_cancel_state { uint32_t result; }; +#ifdef __wasm_libcall_thread_context__ +static _Thread_local struct start_read_then_cancel_state *current_state = NULL; + +static void set_state(struct start_read_then_cancel_state *state) { + current_state = state; +} + +static struct start_read_then_cancel_state *get_state(void) { + return current_state; +} +#else +static void set_state(struct start_read_then_cancel_state *state) { + test_context_set_0(state); +} + +static struct start_read_then_cancel_state *get_state(void) { + return test_context_get_0(); +} +#endif + test_callback_code_t exports_test_start_read_then_cancel( exports_test_future_u32_t data, exports_test_future_void_t signal @@ -58,13 +78,13 @@ test_callback_code_t exports_test_start_read_then_cancel( test_waitable_join(signal, state->set); - test_context_set_0(state); + set_state(state); return TEST_CALLBACK_CODE_WAIT(state->set); } test_callback_code_t exports_test_start_read_then_cancel_callback(test_event_t *event) { - struct start_read_then_cancel_state *state = - (struct start_read_then_cancel_state*) test_context_get_0(); + struct start_read_then_cancel_state *state = get_state(); + set_state(NULL); assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == state->signal); assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_COMPLETED); diff --git a/tests/runtime/future-close-then-receive-read/test.rs b/tests/runtime/future-close-then-receive-read/test.rs index bfb00b5a3..c6b6d9d95 100644 --- a/tests/runtime/future-close-then-receive-read/test.rs +++ b/tests/runtime/future-close-then-receive-read/test.rs @@ -1,22 +1,20 @@ include!(env!("BINDINGS")); use crate::exports::a::b::the_test::Guest; -use std::cell::Cell; +use std::sync::Mutex; use wit_bindgen::rt::async_support::FutureReader; struct Component; export!(Component); -std::thread_local!( - static SLOT: Cell>> = const { Cell::new(None) }; -); +static SLOT: Mutex>> = Mutex::new(None); impl Guest for Component { fn set(future: FutureReader<()>) { - SLOT.with(|s| s.set(Some(future))); + *SLOT.lock().unwrap() = Some(future); } fn get() -> FutureReader<()> { - SLOT.with(|s| s.replace(None).unwrap()) + SLOT.lock().unwrap().take().unwrap() } } diff --git a/tests/runtime/moonbit/stream-write-cancel/holder-service.rs b/tests/runtime/moonbit/stream-write-cancel/holder-service.rs index 1fc2aadfc..a0c1bd306 100644 --- a/tests/runtime/moonbit/stream-write-cancel/holder-service.rs +++ b/tests/runtime/moonbit/stream-write-cancel/holder-service.rs @@ -1,11 +1,8 @@ include!(env!("BINDINGS")); -use crate::exports::test::moonbit_stream_write_cancel::holder::{ - Guest, GuestLeaf, Leaf, -}; -use std::cell::RefCell; -use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; +use crate::exports::test::moonbit_stream_write_cancel::holder::{Guest, GuestLeaf, Leaf}; use std::sync::Mutex; +use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::task::Waker; use wit_bindgen::{StreamReader, StreamResult}; @@ -17,10 +14,7 @@ static WRITE_STARTED: AtomicBool = AtomicBool::new(false); static WRITE_STARTED_WAKER: Mutex> = Mutex::new(None); static LEAF_LIVE_COUNT: AtomicU32 = AtomicU32::new(0); static LEAF_DROP_COUNT: AtomicU32 = AtomicU32::new(0); - -thread_local! { - static HELD_STREAM: RefCell>> = const { RefCell::new(None) }; -} +static HELD_STREAM: Mutex>> = Mutex::new(None); struct MyLeaf; @@ -28,7 +22,8 @@ impl Guest for Component { type Leaf = MyLeaf; async fn hold(value: StreamReader) { - HELD_STREAM.with(|stream| assert!(stream.borrow_mut().replace(value).is_none())); + let prev = HELD_STREAM.lock().unwrap().replace(value); + assert!(prev.is_none()); } fn mark_write_started() { @@ -61,20 +56,21 @@ impl Guest for Component { } async fn writable_dropped() -> bool { - let mut stream = HELD_STREAM.with(|stream| stream.borrow_mut().take().unwrap()); + let mut stream = HELD_STREAM.lock().unwrap().take().unwrap(); let (result, values) = stream.read(Vec::with_capacity(1)).await; result == StreamResult::Dropped && values.is_empty() } async fn read_one_and_keep() -> bool { - let mut stream = HELD_STREAM.with(|stream| stream.borrow_mut().take().unwrap()); + let mut stream = HELD_STREAM.lock().unwrap().take().unwrap(); let (result, values) = stream.read(Vec::with_capacity(1)).await; - HELD_STREAM.with(|held| assert!(held.borrow_mut().replace(stream).is_none())); + let prev = HELD_STREAM.lock().unwrap().replace(stream); + assert!(prev.is_none()); result == StreamResult::Complete(1) && values.len() == 1 } async fn read_one_and_drop() -> bool { - let mut stream = HELD_STREAM.with(|stream| stream.borrow_mut().take().unwrap()); + let mut stream = HELD_STREAM.lock().unwrap().take().unwrap(); let (result, values) = stream.read(Vec::with_capacity(1)).await; result == StreamResult::Complete(1) && values.len() == 1 } diff --git a/tests/runtime/pending-import/test.c b/tests/runtime/pending-import/test.c index 8e095d4d0..a0f9a38d1 100644 --- a/tests/runtime/pending-import/test.c +++ b/tests/runtime/pending-import/test.c @@ -9,6 +9,26 @@ struct my_task { exports_test_future_void_t future; }; +#ifdef __wasm_libcall_thread_context__ +static _Thread_local struct my_task *current_task = NULL; + +static void set_task(struct my_task *task) { + current_task = task; +} + +static struct my_task *get_task(void) { + return current_task; +} +#else +static void set_task(struct my_task *task) { + test_context_set_0(task); +} + +static struct my_task *get_task(void) { + return test_context_get_0(); +} +#endif + test_callback_code_t exports_test_pending_import(exports_test_future_void_t x) { struct my_task *task = (struct my_task*) malloc(sizeof(struct my_task)); assert(task != NULL); @@ -18,12 +38,13 @@ test_callback_code_t exports_test_pending_import(exports_test_future_void_t x) { task->set = test_waitable_set_new(); test_waitable_join(task->future, task->set); - test_context_set_0(task); + set_task(task); return TEST_CALLBACK_CODE_WAIT(task->set); } test_callback_code_t exports_test_pending_import_callback(test_event_t *event) { - struct my_task *task = (struct my_task*) test_context_get_0(); + struct my_task *task = get_task(); + set_task(NULL); assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == task->future); assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_COMPLETED); diff --git a/tests/runtime/ping-pong/test.c b/tests/runtime/ping-pong/test.c index e66de999f..ca196da0c 100644 --- a/tests/runtime/ping-pong/test.c +++ b/tests/runtime/ping-pong/test.c @@ -17,6 +17,43 @@ struct ping_task { exports_test_future_string_writer_t writer; }; +#ifdef __wasm_libcall_thread_context__ +static _Thread_local struct ping_task *current_ping = NULL; +static _Thread_local struct pong_task *current_pong = NULL; + +static void set_ping_task(struct ping_task *task) { + current_ping = task; +} + +static struct ping_task *get_ping_task(void) { + return current_ping; +} + +static void set_pong_task(struct pong_task *task) { + current_pong = task; +} + +static struct pong_task *get_pong_task(void) { + return current_pong; +} +#else +static void set_ping_task(struct ping_task *task) { + test_context_set_0(task); +} + +static struct ping_task *get_ping_task(void) { + return test_context_get_0(); +} + +static void set_pong_task(struct pong_task *task) { + test_context_set_0(task); +} + +static struct pong_task *get_pong_task(void) { + return test_context_get_0(); +} +#endif + test_callback_code_t exports_test_ping(exports_test_future_string_t x, test_string_t *y) { // Initialize a new task struct ping_task *task = (struct ping_task*) malloc(sizeof(struct ping_task)); @@ -33,12 +70,12 @@ test_callback_code_t exports_test_ping(exports_test_future_string_t x, test_stri // Register ourselves as waiting on the future, then block our task. test_waitable_join(task->future, task->set); - test_context_set_0(task); + set_ping_task(task); return TEST_CALLBACK_CODE_WAIT(task->set); } test_callback_code_t exports_test_ping_callback(test_event_t *event) { - struct ping_task *task = (struct ping_task*) test_context_get_0(); + struct ping_task *task = get_ping_task(); switch (task->state) { case PING_S1: { // Assert that our future read completed and discard the read end of the @@ -126,12 +163,12 @@ test_callback_code_t exports_test_pong(exports_test_future_string_t x) { assert(status == TEST_WAITABLE_STATUS_BLOCKED); test_waitable_join(task->future, task->set); - test_context_set_0(task); + set_pong_task(task); return TEST_CALLBACK_CODE_WAIT(task->set); } test_callback_code_t exports_test_pong_callback(test_event_t *event) { - struct pong_task *task = (struct pong_task*) test_context_get_0(); + struct pong_task *task = get_pong_task(); // assert this event is a future read completion assert(event->event == TEST_EVENT_FUTURE_READ); From 45cab663c8290a164b891a626fe13f9938d78a74 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 19 Aug 2026 12:11:29 -0700 Subject: [PATCH 2/2] Fix C++ compat in tests --- tests/runtime/cancel-import/test.c | 2 +- tests/runtime/future-cancel-read/test.c | 2 +- tests/runtime/pending-import/test.c | 2 +- tests/runtime/ping-pong/test.c | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/runtime/cancel-import/test.c b/tests/runtime/cancel-import/test.c index 411109dcf..49914cfbc 100644 --- a/tests/runtime/cancel-import/test.c +++ b/tests/runtime/cancel-import/test.c @@ -25,7 +25,7 @@ static void set_task(struct my_task *task) { } static struct my_task *get_task(void) { - return test_context_get_0(); + return (struct my_task*) test_context_get_0(); } #endif diff --git a/tests/runtime/future-cancel-read/test.c b/tests/runtime/future-cancel-read/test.c index 278e3bcc6..96fca3850 100644 --- a/tests/runtime/future-cancel-read/test.c +++ b/tests/runtime/future-cancel-read/test.c @@ -56,7 +56,7 @@ static void set_state(struct start_read_then_cancel_state *state) { } static struct start_read_then_cancel_state *get_state(void) { - return test_context_get_0(); + return (struct start_read_then_cancel_state*) test_context_get_0(); } #endif diff --git a/tests/runtime/pending-import/test.c b/tests/runtime/pending-import/test.c index a0f9a38d1..b275dd004 100644 --- a/tests/runtime/pending-import/test.c +++ b/tests/runtime/pending-import/test.c @@ -25,7 +25,7 @@ static void set_task(struct my_task *task) { } static struct my_task *get_task(void) { - return test_context_get_0(); + return (struct my_task*) test_context_get_0(); } #endif diff --git a/tests/runtime/ping-pong/test.c b/tests/runtime/ping-pong/test.c index ca196da0c..be6803c50 100644 --- a/tests/runtime/ping-pong/test.c +++ b/tests/runtime/ping-pong/test.c @@ -17,6 +17,12 @@ struct ping_task { exports_test_future_string_writer_t writer; }; +struct pong_task { + test_string_t read_result; + exports_test_future_string_t future; + test_waitable_set_t set; +}; + #ifdef __wasm_libcall_thread_context__ static _Thread_local struct ping_task *current_ping = NULL; static _Thread_local struct pong_task *current_pong = NULL; @@ -42,7 +48,7 @@ static void set_ping_task(struct ping_task *task) { } static struct ping_task *get_ping_task(void) { - return test_context_get_0(); + return (struct ping_task*) test_context_get_0(); } static void set_pong_task(struct pong_task *task) { @@ -50,7 +56,7 @@ static void set_pong_task(struct pong_task *task) { } static struct pong_task *get_pong_task(void) { - return test_context_get_0(); + return (struct pong_task*) test_context_get_0(); } #endif @@ -145,12 +151,6 @@ test_callback_code_t exports_test_ping_callback(test_event_t *event) { } -struct pong_task { - test_string_t read_result; - exports_test_future_string_t future; - test_waitable_set_t set; -}; - test_callback_code_t exports_test_pong(exports_test_future_string_t x) { struct pong_task *task = (struct pong_task*) malloc(sizeof(struct pong_task)); assert(task != NULL);