feature: thread join() with exit value
This commit is contained in:
parent
d582a9b58b
commit
87c13d3920
@ -35,6 +35,7 @@ struct ThreadInner {
|
||||
|
||||
pub struct Thread {
|
||||
inner: IrqSafeSpinLock<ThreadInner>,
|
||||
exit_wait: Wait,
|
||||
pub(super) ctx: UnsafeCell<Context>,
|
||||
signal_ctx: UnsafeCell<Context>,
|
||||
signal_pending: AtomicU32,
|
||||
@ -68,6 +69,7 @@ impl Thread {
|
||||
ctx: UnsafeCell::new(Context::kernel(entry as usize, arg)),
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -97,6 +99,7 @@ impl Thread {
|
||||
ctx: UnsafeCell::new(Context::user(entry, arg, ttbr0, stack)),
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -123,6 +126,7 @@ impl Thread {
|
||||
ctx: UnsafeCell::new(Context::fork(frame, ttbr0)),
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -213,6 +217,23 @@ impl Thread {
|
||||
lock.wait_flag = true;
|
||||
}
|
||||
|
||||
pub fn waittid(tid: u32) -> Result<(), Errno> {
|
||||
loop {
|
||||
let thread = THREADS
|
||||
.lock()
|
||||
.get(&tid)
|
||||
.cloned()
|
||||
.ok_or(Errno::DoesNotExist)?;
|
||||
|
||||
if thread.state() == State::Finished {
|
||||
// TODO remove thread from its parent?
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
thread.exit_wait.wait(None)?;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_wait_reached(&self) {
|
||||
let mut lock = self.inner.lock();
|
||||
lock.wait_flag = false;
|
||||
@ -308,6 +329,7 @@ impl Thread {
|
||||
if let Some(wait) = wait {
|
||||
wait.abort(tid);
|
||||
}
|
||||
self.exit_wait.wakeup_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,16 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
abi::SYS_EX_THREAD_WAIT => {
|
||||
let tid = args[0] as u32;
|
||||
|
||||
match Thread::waittid(tid) {
|
||||
Ok(_) => {
|
||||
Ok(0)
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
},
|
||||
abi::SYS_IOCTL => {
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
let cmd = IoctlCmd::try_from(args[1] as u32)?;
|
||||
|
@ -7,6 +7,7 @@ pub const SYS_EX_KILL: usize = 132;
|
||||
pub const SYS_EX_CLONE: usize = 133;
|
||||
pub const SYS_EX_YIELD: usize = 134;
|
||||
pub const SYS_EX_THREAD_EXIT: usize = 135;
|
||||
pub const SYS_EX_THREAD_WAIT: usize = 136;
|
||||
|
||||
pub const SYS_EXIT: usize = 1;
|
||||
pub const SYS_READ: usize = 2;
|
||||
|
@ -274,12 +274,7 @@ pub fn sys_ex_kill(pid: SignalDestination, signum: Signal) -> Result<(), Errno>
|
||||
#[inline(always)]
|
||||
pub fn sys_ex_clone(entry: usize, stack: usize, arg: usize) -> Result<usize, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_EX_CLONE,
|
||||
argn!(entry),
|
||||
argn!(stack),
|
||||
argn!(arg)
|
||||
)
|
||||
syscall!(abi::SYS_EX_CLONE, argn!(entry), argn!(stack), argn!(arg))
|
||||
})
|
||||
}
|
||||
|
||||
@ -291,6 +286,12 @@ pub fn sys_ex_thread_exit(status: ExitCode) -> ! {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_ex_thread_wait(tid: u32) -> Result<ExitCode, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(abi::SYS_EX_THREAD_WAIT, argn!(tid)) })
|
||||
.map(|_| ExitCode::from(0))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_ex_yield() {
|
||||
unsafe {
|
||||
|
@ -53,6 +53,7 @@ extern "C" fn _start(_arg: usize) -> ! {
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||
// TODO handle non-main thread panics
|
||||
// TODO print to stdout/stderr (if available)
|
||||
trace!("Panic ocurred: {}", pi);
|
||||
sys::sys_exit(ExitCode::from(-1));
|
||||
|
@ -1,9 +1,8 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec;
|
||||
use alloc::{boxed::Box, sync::Arc, vec};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use libsys::{
|
||||
calls::{sys_ex_clone, sys_ex_thread_exit, sys_ex_signal},
|
||||
calls::{sys_ex_clone, sys_ex_signal, sys_ex_thread_exit, sys_ex_thread_wait},
|
||||
error::Errno,
|
||||
proc::ExitCode,
|
||||
};
|
||||
@ -17,12 +16,24 @@ where
|
||||
T: Send + 'static,
|
||||
{
|
||||
closure: F,
|
||||
result: Arc<UnsafeCell<MaybeUninit<T>>>,
|
||||
stack: usize,
|
||||
}
|
||||
|
||||
pub struct JoinHandle<T> {
|
||||
native: u32,
|
||||
_pd: PhantomData<T>,
|
||||
result: Arc<UnsafeCell<MaybeUninit<T>>>,
|
||||
}
|
||||
|
||||
impl<T> JoinHandle<T> {
|
||||
pub fn join(self) -> Result<T, ()> {
|
||||
sys_ex_thread_wait(self.native).unwrap();
|
||||
if let Ok(result) = Arc::try_unwrap(self.result) {
|
||||
Ok(unsafe { result.into_inner().assume_init() })
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
|
||||
@ -32,6 +43,7 @@ where
|
||||
T: Send + 'static,
|
||||
{
|
||||
let stack = vec![0u8; 8192].leak();
|
||||
let result = Arc::new(UnsafeCell::new(MaybeUninit::uninit()));
|
||||
|
||||
#[inline(never)]
|
||||
extern "C" fn thread_entry<F, T>(data: *mut NativeData<F, T>) -> !
|
||||
@ -53,9 +65,12 @@ where
|
||||
}
|
||||
|
||||
let data: Box<NativeData<F, T>> = unsafe { Box::from_raw(data) };
|
||||
|
||||
let res = (data.closure)();
|
||||
|
||||
unsafe {
|
||||
(&mut *data.result.get()).write(res);
|
||||
}
|
||||
|
||||
(data.stack, 8192)
|
||||
};
|
||||
|
||||
@ -65,13 +80,14 @@ where
|
||||
|
||||
let native = unsafe {
|
||||
let stack = stack.as_mut_ptr() as usize + stack.len();
|
||||
let data: *mut NativeData<F, T> = Box::into_raw(Box::new(NativeData { closure: f, stack }));
|
||||
let data: *mut NativeData<F, T> = Box::into_raw(Box::new(NativeData {
|
||||
closure: f,
|
||||
stack,
|
||||
result: result.clone(),
|
||||
}));
|
||||
|
||||
sys_ex_clone(thread_entry::<F, T> as usize, stack, data as usize).unwrap() as u32
|
||||
};
|
||||
|
||||
JoinHandle {
|
||||
native,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
JoinHandle { native, result }
|
||||
}
|
||||
|
@ -23,12 +23,14 @@ fn main() -> i32 {
|
||||
trace!("Closure is alive: {}", value);
|
||||
sleep(2_000_000_000);
|
||||
trace!("Closure will now exit");
|
||||
|
||||
value - 100
|
||||
});
|
||||
sleep(1_000_000_000);
|
||||
|
||||
trace!("???");
|
||||
|
||||
loop {}
|
||||
trace!("Thread joined: {:?}", thread.join());
|
||||
|
||||
0
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user