46 lines
1.2 KiB
Rust
46 lines
1.2 KiB
Rust
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<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 usize as u64, raw_main as u64, 0).unwrap();
|
|
|
|
JoinHandle { cap }
|
|
}
|