use crate::cap::Capability; use crate::syscall; use crate::zion; use alloc::boxed::Box; use core::ffi::c_void; pub struct JoinHandle { cap: Capability, } impl JoinHandle { pub fn join(&self) -> Result<(), zion::ZError> { syscall::thread_wait(&self.cap) } } #[no_mangle] extern "C" fn entry_point(func: *mut c_void) -> ! { unsafe { Box::from_raw(func as *mut Box)(); } syscall::thread_exit() } pub fn spawn(f: F) -> JoinHandle where F: FnOnce() + Send + 'static, { // This is very tricky. // If we have been passed a closure that doesn't capture // anything it will be 0 size and creating a Box of it // will create a pointer with address 0x1. // So we create this "main" closure that captures f to get around this. // Also somehow having the explicit type annotation here is important. let main: Box = Box::new(move || { f(); }); let raw_main = Box::into_raw(Box::new(main)); let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP }).unwrap(); let cap = syscall::thread_create(&proc_cap).unwrap(); syscall::thread_start(&cap, entry_point as usize as u64, raw_main as u64, 0).unwrap(); JoinHandle { cap } }