Skip to main content

selium_kernel/
guest_async.rs

1use std::sync::Arc;
2
3use tokio::{select, sync::Notify};
4use wasmtime::{Caller, Linker};
5
6use crate::{KernelError, mailbox::GuestMailbox, registry::InstanceRegistry};
7
8/// Host-side support for guest async helpers.
9pub struct GuestAsync {
10    shutdown: Arc<Notify>,
11}
12
13impl GuestAsync {
14    /// Create a new guest async capability.
15    pub fn new(notify: Arc<Notify>) -> Self {
16        Self { shutdown: notify }
17    }
18
19    /// Link the `selium::async` host functions into the Wasmtime linker.
20    pub fn link(&self, linker: &mut Linker<InstanceRegistry>) -> Result<(), KernelError> {
21        let shutdown = Arc::clone(&self.shutdown);
22        linker.func_wrap_async(
23            "selium::async",
24            "yield_now",
25            move |caller: Caller<'_, InstanceRegistry>, ()| {
26                let mailbox_ref: &'static GuestMailbox =
27                    caller.data().mailbox().expect("guest mailbox missing");
28                let shutdown = Arc::clone(&shutdown);
29                Box::new(async move {
30                    loop {
31                        if mailbox_ref.is_closed() || mailbox_ref.is_signalled() {
32                            break;
33                        }
34                        select! {
35                            _ = shutdown.notified() => {
36                                break;
37                            }
38                            _ = mailbox_ref.wait_for_signal() => {}
39                        }
40                    }
41                })
42            },
43        )?;
44        Ok(())
45    }
46
47    /// Signal all waiting guests that the host is shutting down.
48    pub fn shutdown(&self) {
49        self.shutdown.notify_waiters();
50    }
51}