Add thread spawn with proper trait checks.

This commit is contained in:
Drew Galbraith 2025-01-25 21:49:28 -08:00
parent 14585c005c
commit 9da38d608a
2 changed files with 58 additions and 0 deletions

View file

@ -42,3 +42,43 @@ impl Thread {
syscall::thread_wait(&self.cap)
}
}
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<dyn FnOnce()>)();
}
syscall::thread_exit()
}
pub fn spawn<F>(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<dyn FnOnce()> = 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 u64, raw_main as u64, 0).unwrap();
JoinHandle { cap }
}