twz_rt/runtime/
upcall.rs

1use std::{ffi::c_void, sync::OnceLock};
2
3use twizzler_abi::upcall::{UpcallData, UpcallFrame, UpcallHandlerFlags};
4
5pub(crate) fn upcall_rust_entry(frame: &mut UpcallFrame, info: &UpcallData) {
6    let imp = UPCALL_IMPL.get();
7    if let Some(Some(imp)) = imp {
8        unsafe {
9            imp(
10                frame as *mut _ as *mut c_void,
11                info as *const _ as *const c_void,
12            )
13        }
14    } else {
15        upcall_def_handler(frame, info)
16    }
17}
18
19pub type HandlerType = unsafe extern "C-unwind" fn(frame: *mut c_void, info: *const c_void);
20static UPCALL_IMPL: OnceLock<Option<HandlerType>> = OnceLock::new();
21
22pub fn set_upcall_handler(handler: Option<HandlerType>) -> Result<(), HandlerSetError> {
23    UPCALL_IMPL.set(handler).map_err(|_| HandlerSetError)
24}
25
26#[derive(Clone, Copy, Debug)]
27pub struct HandlerSetError;
28
29fn print_status(_frame: &mut UpcallFrame) {
30    //tracing::info!("status request");
31}
32
33pub(crate) fn upcall_def_handler(frame: &mut UpcallFrame, info: &UpcallData) {
34    if info.flags.contains(UpcallHandlerFlags::SWITCHED_CONTEXT) {
35        twizzler_abi::klog_println!("got supervisor upcall");
36    }
37    match info.info {
38        twizzler_abi::upcall::UpcallInfo::Mailbox(sig) => match sig as i32 {
39            libc::SIGINFO => {
40                print_status(frame);
41            }
42            libc::SIGINT => {
43                twizzler_abi::klog_println!("interrupted");
44                twizzler_abi::syscall::sys_thread_exit(128 + sig);
45            }
46            libc::SIGWINCH => {
47                // Ignore SIGWINCH by default to prevent crashing
48            }
49            _ => twizzler_abi::syscall::sys_thread_exit(128 + sig),
50        },
51        _ => {
52            panic!("unexpected supervisor upcall in runtime: {:?}", info);
53        }
54    }
55}