xref: /wasmtime-44.0.1/tests/all/wait_notify.rs (revision 48f4621f)
1 #![cfg(not(miri))]
2 
3 use crate::threads::engine;
4 use std::time::Instant;
5 use wasmtime::*;
6 
7 #[test]
atomic_wait_timeout_length() -> Result<()>8 fn atomic_wait_timeout_length() -> Result<()> {
9     let sleep_nanoseconds = 500000000;
10     let wat = format!(
11         r#"(module
12         (import "env" "memory" (memory 1 1 shared))
13 
14         (func (export "func1") (result i32)
15             (memory.atomic.wait32 (i32.const 0) (i32.const 0) (i64.const {sleep_nanoseconds}))
16         )
17 
18         (data (i32.const 0) "\00\00\00\00")
19     )"#
20     );
21     let Some(engine) = engine() else {
22         return Ok(());
23     };
24     let module = Module::new(&engine, wat)?;
25     let mut store = Store::new(&engine, ());
26     let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 1))?;
27     let instance = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
28     let now = Instant::now();
29     let func_ret = instance
30         .get_typed_func::<(), i32>(&mut store, "func1")
31         .unwrap()
32         .call(&mut store, ())
33         .unwrap();
34     let duration = now.elapsed();
35     assert!(
36         duration.as_nanos() >= sleep_nanoseconds,
37         "duration: {duration:?} < {sleep_nanoseconds:?}"
38     );
39     assert_eq!(func_ret, 2);
40     Ok(())
41 }
42 
43 #[test]
atomic_wait_notify_basic() -> Result<()>44 fn atomic_wait_notify_basic() -> Result<()> {
45     let wat = r#"(module
46         (import "env" "memory" (memory 1 1 shared))
47 
48         (func (export "first_thread") (result i32)
49             (drop (memory.atomic.wait32 (i32.const 4) (i32.const 0) (i64.const -1)))
50             (i32.atomic.store (i32.const 0) (i32.const 42))
51             (drop (memory.atomic.notify (i32.const 0) (i32.const -1)))
52             (i32.atomic.load (i32.const 0))
53         )
54 
55         (func (export "second_thread") (result i32)
56             (i32.atomic.store (i32.const 4) (i32.const 21))
57             (drop (memory.atomic.notify (i32.const 4) (i32.const -1)))
58             (drop (memory.atomic.wait32 (i32.const 0) (i32.const 0) (i64.const -1)))
59             (i32.atomic.load (i32.const 0))
60         )
61 
62         (data (i32.const 0) "\00\00\00\00")
63         (data (i32.const 4) "\00\00\00\00")
64     )"#;
65     let Some(engine) = engine() else {
66         return Ok(());
67     };
68     let module = Module::new(&engine, wat)?;
69     let mut store = Store::new(&engine, ());
70     let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 1))?;
71     let instance1 = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
72 
73     let thread = {
74         let engine = engine.clone();
75         let module = module.clone();
76         let shared_memory = shared_memory.clone();
77         std::thread::spawn(move || {
78             let mut store = Store::new(&engine, ());
79             let instance2 = Instance::new(&mut store, &module, &[shared_memory.into()]).unwrap();
80 
81             let instance2_first_word = instance2
82                 .get_typed_func::<(), i32>(&mut store, "second_thread")
83                 .unwrap()
84                 .call(&mut store, ())
85                 .unwrap();
86 
87             assert_eq!(instance2_first_word, 42);
88         })
89     };
90 
91     let instance1_first_word = instance1
92         .get_typed_func::<(), i32>(&mut store, "first_thread")
93         .unwrap()
94         .call(&mut store, ())
95         .unwrap();
96     assert_eq!(instance1_first_word, 42);
97 
98     thread.join().unwrap();
99 
100     let data = shared_memory.data();
101     // Verify that the memory is the same in all shared locations.
102     let shared_memory_first_word = i32::from_le_bytes(unsafe {
103         [
104             *data[0].get(),
105             *data[1].get(),
106             *data[2].get(),
107             *data[3].get(),
108         ]
109     });
110     assert_eq!(shared_memory_first_word, 42);
111 
112     let shared_memory_second_word = i32::from_le_bytes(unsafe {
113         [
114             *data[4].get(),
115             *data[5].get(),
116             *data[6].get(),
117             *data[7].get(),
118         ]
119     });
120     assert_eq!(shared_memory_second_word, 21);
121     Ok(())
122 }
123