You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.8 KiB
121 lines
3.8 KiB
#![cfg(not(miri))]
|
|
|
|
use std::time::Instant;
|
|
use wasmtime::*;
|
|
|
|
#[test]
|
|
fn atomic_wait_timeout_length() -> Result<()> {
|
|
let sleep_nanoseconds = 500000000;
|
|
let wat = format!(
|
|
r#"(module
|
|
(import "env" "memory" (memory 1 1 shared))
|
|
|
|
(func (export "func1") (result i32)
|
|
(memory.atomic.wait32 (i32.const 0) (i32.const 0) (i64.const {sleep_nanoseconds}))
|
|
)
|
|
|
|
(data (i32.const 0) "\00\00\00\00")
|
|
)"#
|
|
);
|
|
let mut config = Config::new();
|
|
config.wasm_threads(true);
|
|
let engine = Engine::new(&config)?;
|
|
let module = Module::new(&engine, wat)?;
|
|
let mut store = Store::new(&engine, ());
|
|
let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 1))?;
|
|
let instance = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
|
|
let now = Instant::now();
|
|
let func_ret = instance
|
|
.get_typed_func::<(), i32>(&mut store, "func1")
|
|
.unwrap()
|
|
.call(&mut store, ())
|
|
.unwrap();
|
|
let duration = now.elapsed();
|
|
assert!(
|
|
duration.as_nanos() >= sleep_nanoseconds,
|
|
"duration: {duration:?} < {sleep_nanoseconds:?}"
|
|
);
|
|
assert_eq!(func_ret, 2);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn atomic_wait_notify_basic() -> Result<()> {
|
|
let wat = r#"(module
|
|
(import "env" "memory" (memory 1 1 shared))
|
|
|
|
(func (export "first_thread") (result i32)
|
|
(drop (memory.atomic.wait32 (i32.const 4) (i32.const 0) (i64.const -1)))
|
|
(i32.atomic.store (i32.const 0) (i32.const 42))
|
|
(drop (memory.atomic.notify (i32.const 0) (i32.const -1)))
|
|
(i32.atomic.load (i32.const 0))
|
|
)
|
|
|
|
(func (export "second_thread") (result i32)
|
|
(i32.atomic.store (i32.const 4) (i32.const 21))
|
|
(drop (memory.atomic.notify (i32.const 4) (i32.const -1)))
|
|
(drop (memory.atomic.wait32 (i32.const 0) (i32.const 0) (i64.const -1)))
|
|
(i32.atomic.load (i32.const 0))
|
|
)
|
|
|
|
(data (i32.const 0) "\00\00\00\00")
|
|
(data (i32.const 4) "\00\00\00\00")
|
|
)"#;
|
|
let mut config = Config::new();
|
|
config.wasm_threads(true);
|
|
let engine = Engine::new(&config)?;
|
|
let module = Module::new(&engine, wat)?;
|
|
let mut store = Store::new(&engine, ());
|
|
let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 1))?;
|
|
let instance1 = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
|
|
|
|
let thread = {
|
|
let engine = engine.clone();
|
|
let module = module.clone();
|
|
let shared_memory = shared_memory.clone();
|
|
std::thread::spawn(move || {
|
|
let mut store = Store::new(&engine, ());
|
|
let instance2 = Instance::new(&mut store, &module, &[shared_memory.into()]).unwrap();
|
|
|
|
let instance2_first_word = instance2
|
|
.get_typed_func::<(), i32>(&mut store, "second_thread")
|
|
.unwrap()
|
|
.call(&mut store, ())
|
|
.unwrap();
|
|
|
|
assert_eq!(instance2_first_word, 42);
|
|
})
|
|
};
|
|
|
|
let instance1_first_word = instance1
|
|
.get_typed_func::<(), i32>(&mut store, "first_thread")
|
|
.unwrap()
|
|
.call(&mut store, ())
|
|
.unwrap();
|
|
assert_eq!(instance1_first_word, 42);
|
|
|
|
thread.join().unwrap();
|
|
|
|
let data = shared_memory.data();
|
|
// Verify that the memory is the same in all shared locations.
|
|
let shared_memory_first_word = i32::from_le_bytes(unsafe {
|
|
[
|
|
*data[0].get(),
|
|
*data[1].get(),
|
|
*data[2].get(),
|
|
*data[3].get(),
|
|
]
|
|
});
|
|
assert_eq!(shared_memory_first_word, 42);
|
|
|
|
let shared_memory_second_word = i32::from_le_bytes(unsafe {
|
|
[
|
|
*data[4].get(),
|
|
*data[5].get(),
|
|
*data[6].get(),
|
|
*data[7].get(),
|
|
]
|
|
});
|
|
assert_eq!(shared_memory_second_word, 21);
|
|
Ok(())
|
|
}
|
|
|