monitor/
upcall.rs

1use std::{
2    ffi::c_void,
3    sync::atomic::{AtomicBool, Ordering},
4};
5
6use twizzler_abi::upcall::{UpcallData, UpcallFrame, UpcallHandlerFlags};
7
8use crate::mon::get_monitor;
9#[thread_local]
10static IN_UPCALL_HANDLER: AtomicBool = AtomicBool::new(false);
11
12pub fn upcall_monitor_handler(frame: &mut UpcallFrame, info: &UpcallData) {
13    let _nested = IN_UPCALL_HANDLER.swap(true, Ordering::SeqCst);
14
15    if info.flags.contains(UpcallHandlerFlags::SWITCHED_CONTEXT) {
16        let mon = get_monitor();
17        match mon.upcall_handle(frame, info) {
18            Ok(Some(flags)) => {
19                IN_UPCALL_HANDLER.store(false, Ordering::SeqCst);
20                unsafe { twizzler_abi::syscall::sys_thread_resume_from_upcall(frame, flags) };
21            }
22            _ => {
23                twizzler_abi::syscall::sys_thread_exit(101);
24            }
25        }
26    } else {
27        twizzler_abi::klog_println!(
28            "monitor got unexpected upcall while in supervisor context: {:?} {:?}",
29            frame,
30            info
31        );
32        twizzler_abi::syscall::sys_thread_exit(101);
33    }
34}
35
36pub extern "C-unwind" fn upcall_monitor_handler_entry(frame: *mut c_void, info: *const c_void) {
37    unsafe {
38        upcall_monitor_handler(
39            frame.cast::<UpcallFrame>().as_mut().unwrap(),
40            info.cast::<UpcallData>().as_ref().unwrap(),
41        );
42    }
43}