deterministic_wasi_ctx/
scheduling.rs1use std::{mem, ptr, slice};
2
3use crate::wasi_abi::{
4 Event, EventFdReadwrite, Subscription, ERRNO_SUCCESS, EVENTTYPE_CLOCK, EVENTTYPE_FD_READ,
5 EVENTTYPE_FD_WRITE,
6};
7use wasmtime::{format_err, Caller, Linker, Result};
8
9pub fn replace_scheduling_functions<T>(linker: &mut Linker<T>) -> Result<()>
13where
14 T: Send + 'static,
15{
16 override_scheduling_functions(linker, "wasi_snapshot_preview1")
17}
18
19pub fn replace_scheduling_functions_for_wasi_preview_0<T>(linker: &mut Linker<T>) -> Result<()>
23where
24 T: Send + 'static,
25{
26 override_scheduling_functions(linker, "wasi_unstable")
27}
28
29fn override_scheduling_functions<T: 'static>(linker: &mut Linker<T>, module: &str) -> Result<()> {
30 linker.allow_shadowing(true);
31 linker.func_wrap(
32 module,
33 "poll_oneoff",
34 |mut caller: Caller<'_, T>,
35 in_ptr: i32,
36 out_ptr: i32,
37 nsubscriptions: i32,
38 nevents_ptr: i32|
39 -> Result<i32> {
40 let in_ptr = in_ptr as usize;
41 let out_ptr = out_ptr as usize;
42 let nsubscriptions = nsubscriptions as usize;
43 let nevents_ptr = nevents_ptr as usize;
44 let memory = caller
46 .get_export("memory")
47 .map_or_else(|| Err(format_err!("missing required memory export")), Ok)?
48 .into_memory()
49 .map_or_else(|| Err(format_err!("missing required memory export")), Ok)?;
50
51 for i in 0..nsubscriptions {
52 let offset = in_ptr + (i * mem::size_of::<Subscription>());
54 let mut subscription_buffer = [0u8; mem::size_of::<Subscription>()];
55 memory.read(&caller, offset, &mut subscription_buffer)?;
56 let subscription =
57 unsafe { ptr::read(subscription_buffer.as_ptr() as *const Subscription) };
58
59 let event = Event {
61 userdata: subscription.userdata,
62 error: ERRNO_SUCCESS,
63 type_: match subscription.u.tag {
66 0 => EVENTTYPE_CLOCK,
67 1 => EVENTTYPE_FD_READ,
68 2 => EVENTTYPE_FD_WRITE,
69 _ => unreachable!(),
70 },
71 fd_readwrite: EventFdReadwrite {
72 nbytes: 0,
73 flags: 0,
74 },
75 };
76
77 let offset = out_ptr + (i * mem::size_of::<Event>());
79 let event_buffer = unsafe {
80 slice::from_raw_parts(
81 &event as *const Event as *const u8,
82 mem::size_of::<Event>(),
83 )
84 };
85 memory.write(&mut caller, offset, event_buffer)?
86 }
87
88 let buffer = nsubscriptions.to_le_bytes();
90 memory.write(&mut caller, nevents_ptr, &buffer)?;
91
92 Ok(ERRNO_SUCCESS as i32)
93 },
94 )?;
95
96 linker.func_wrap(module, "sched_yield", || ERRNO_SUCCESS as i32)?;
97
98 Ok(())
99}