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 }
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 }
49 _ => twizzler_abi::syscall::sys_thread_exit(128 + sig),
50 },
51 _ => {
52 panic!("unexpected supervisor upcall in runtime: {:?}", info);
53 }
54 }
55}