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}