1use core::panic::UnwindSafe;
8
9use crate::{abort, panicking::catch_unwind, Termination};
10
11#[cfg(target_thread_local)]
12#[no_mangle]
13unsafe extern "C" fn sel4_runtime_rust_entry(bootinfo: *const sel4::BootInfo) -> ! {
14 fn cont_fn(cont_arg: *mut sel4_runtime_common::ContArg) -> ! {
15 inner_entry(cont_arg.cast_const().cast())
16 }
17
18 sel4_runtime_common::initialize_tls_on_stack_and_continue(cont_fn, bootinfo.cast_mut().cast())
19}
20
21#[cfg(not(target_thread_local))]
22#[no_mangle]
23unsafe extern "C" fn sel4_runtime_rust_entry(bootinfo: *const sel4::BootInfo) -> ! {
24 inner_entry(bootinfo)
25}
26
27#[allow(unreachable_code)]
28fn inner_entry(bootinfo: *const sel4::BootInfo) -> ! {
29 #[cfg(panic = "unwind")]
30 {
31 sel4_runtime_common::set_eh_frame_finder().unwrap();
32 }
33
34 let bootinfo = unsafe { sel4::BootInfoPtr::new(bootinfo) };
35
36 let ipc_buffer = unsafe { bootinfo.ipc_buffer().as_mut().unwrap() };
37 sel4::set_ipc_buffer(ipc_buffer);
38
39 sel4_ctors_dtors::run_ctors();
40
41 unsafe {
42 __sel4_root_task__main(&bootinfo);
43 }
44
45 abort!("__sel4_root_task__main returned")
46}
47
48extern "Rust" {
49 fn __sel4_root_task__main(bootinfo: &sel4::BootInfoPtr) -> !;
50}
51
52#[doc(hidden)]
53#[macro_export]
54macro_rules! declare_main {
55 ($main:expr) => {
56 #[allow(non_snake_case)]
57 #[no_mangle]
58 fn __sel4_root_task__main(bootinfo: &$crate::_private::BootInfoPtr) -> ! {
59 $crate::_private::run_main($main, bootinfo);
60 }
61 };
62}
63
64#[doc(hidden)]
65#[allow(clippy::missing_safety_doc)]
66pub fn run_main<F, T>(f: F, bootinfo: &sel4::BootInfoPtr) -> !
67where
68 F: FnOnce(&sel4::BootInfoPtr) -> T + UnwindSafe,
69 T: Termination,
70{
71 let result = catch_unwind(move || f(bootinfo).report());
72 match result {
73 Ok(err) => abort!("main thread terminated with error: {err:?}"),
74 Err(_) => abort!("uncaught panic in main thread"),
75 }
76}