diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index e7f52e00cd07..c3fd38365d74 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -200,7 +200,8 @@ impl Config { || self.module_config.function_references_enabled || reference_types.unwrap_or(false); config.extended_const_enabled = extended_const.unwrap_or(false); - config.exceptions_enabled = exceptions.unwrap_or(false); + config.exceptions_enabled = + self.module_config.stack_switching || exceptions.unwrap_or(false); if multi_memory.unwrap_or(false) { config.max_memories = limits::MEMORIES_PER_MODULE as usize; } else { diff --git a/crates/test-util/src/wast.rs b/crates/test-util/src/wast.rs index dd6f5033491c..b6ec104358de 100644 --- a/crates/test-util/src/wast.rs +++ b/crates/test-util/src/wast.rs @@ -536,6 +536,7 @@ impl WastTest { // shared memories + pooling allocator aren't supported yet "misc_testsuite/memory-combos.wast", "misc_testsuite/threads/atomics-end-of-memory.wast", + "misc_testsuite/threads/atomic_wait_endianness.wast", "misc_testsuite/threads/LB.wast", "misc_testsuite/threads/LB_atomic.wast", "misc_testsuite/threads/MP.wast", diff --git a/crates/wasmtime/src/runtime/vm/memory/shared_memory.rs b/crates/wasmtime/src/runtime/vm/memory/shared_memory.rs index 679984c25063..9f0721be11f0 100644 --- a/crates/wasmtime/src/runtime/vm/memory/shared_memory.rs +++ b/crates/wasmtime/src/runtime/vm/memory/shared_memory.rs @@ -146,6 +146,9 @@ impl SharedMemory { assert!(std::mem::size_of::() == 4); assert!(std::mem::align_of::() <= 4); let atomic = unsafe { AtomicU32::from_ptr(addr.cast()) }; + // Wasm linear memory is always little-endian, but `AtomicU32` uses the + // host's native endianness. + let expected = expected.to_le(); // Note that `checked_add` is used such that when `timeout` is too large // it'll cause there to be no timeout at all if we can't represent the @@ -175,6 +178,9 @@ impl SharedMemory { assert!(std::mem::size_of::() == 8); assert!(std::mem::align_of::() <= 8); let atomic = unsafe { AtomicU64::from_ptr(addr.cast()) }; + // Wasm linear memory is always little-endian, but `AtomicU64` uses the + // host's native endianness. + let expected = expected.to_le(); // See `atomic_wait32` for why this is using `checked_add`. let deadline = timeout.and_then(|d| Instant::now().checked_add(d)); diff --git a/tests/misc_testsuite/threads/atomic_wait_endianness.wast b/tests/misc_testsuite/threads/atomic_wait_endianness.wast new file mode 100644 index 000000000000..ee111a0039d9 --- /dev/null +++ b/tests/misc_testsuite/threads/atomic_wait_endianness.wast @@ -0,0 +1,26 @@ +;;! threads = true + +(module + (memory (export "shared") 1 1 shared) + + (func (export "eq32") (result i32) + (i32.atomic.store (i32.const 0) (i32.const 1)) + (memory.atomic.wait32 (i32.const 0) (i32.const 1) (i64.const 0))) + + (func (export "ne32") (result i32) + (i32.atomic.store (i32.const 0) (i32.const 1)) + (memory.atomic.wait32 (i32.const 0) (i32.const 0x01000000) (i64.const 0))) + + (func (export "eq64") (result i32) + (i64.atomic.store (i32.const 8) (i64.const 1)) + (memory.atomic.wait64 (i32.const 8) (i64.const 1) (i64.const 0))) + + (func (export "ne64") (result i32) + (i64.atomic.store (i32.const 8) (i64.const 1)) + (memory.atomic.wait64 (i32.const 8) (i64.const 0x0100000000000000) (i64.const 0))) +) + +(assert_return (invoke "eq32") (i32.const 2)) +(assert_return (invoke "ne32") (i32.const 1)) +(assert_return (invoke "eq64") (i32.const 2)) +(assert_return (invoke "ne64") (i32.const 1))