Add thread spawn with proper trait checks.
This commit is contained in:
parent
14585c005c
commit
9da38d608a
|
@ -42,3 +42,43 @@ impl Thread {
|
||||||
syscall::thread_wait(&self.cap)
|
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 }
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use mammoth::debug;
|
use mammoth::debug;
|
||||||
use mammoth::define_entry;
|
use mammoth::define_entry;
|
||||||
|
@ -12,6 +13,10 @@ use yellowstone_yunq::GetEndpointRequest;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
|
||||||
|
pub fn testthread() {
|
||||||
|
debug!("Testing 1, 8 ,9");
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn main() -> z_err_t {
|
pub extern "C" fn main() -> z_err_t {
|
||||||
debug!("Testing!");
|
debug!("Testing!");
|
||||||
|
@ -28,11 +33,24 @@ pub extern "C" fn main() -> z_err_t {
|
||||||
|
|
||||||
debug!("Got endpoint w/ cap: {:#x}", endpoint.endpoint);
|
debug!("Got endpoint w/ cap: {:#x}", endpoint.endpoint);
|
||||||
|
|
||||||
|
let a = Box::new(1);
|
||||||
|
let b = Box::new(1);
|
||||||
|
debug!("Addrs: {:p} {:p}", a, b);
|
||||||
|
|
||||||
let e: thread::ThreadEntry = |_| {
|
let e: thread::ThreadEntry = |_| {
|
||||||
debug!("Testing 1 2 3");
|
debug!("Testing 1 2 3");
|
||||||
};
|
};
|
||||||
let t = thread::Thread::spawn(e, core::ptr::null()).expect("Failed to spawn thread");
|
let t = thread::Thread::spawn(e, core::ptr::null()).expect("Failed to spawn thread");
|
||||||
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
|
let x = Box::new(|| 1);
|
||||||
|
debug!("Addr: {:p}", x);
|
||||||
|
debug!("Addr: {:p}", &x);
|
||||||
|
|
||||||
|
let t = thread::spawn(testthread);
|
||||||
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
|
let t = thread::spawn(|| debug!("Testing 4, 5, 6"));
|
||||||
t.join().expect("Failed to wait.");
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
0
|
0
|
||||||
|
|
Loading…
Reference in New Issue