From 6fc23e1134f782d7592c135b01a3402133526ff3 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 1 Nov 2018 00:45:02 +0800 Subject: [PATCH] Ugly impl sys_wait(0) --- kernel/src/lib.rs | 1 + kernel/src/process/mod.rs | 51 ++++++++++++++++++++++++++++++++++++++ kernel/src/sync/condvar.rs | 3 +++ kernel/src/syscall.rs | 51 ++++++++++++++++++++++++++------------ 4 files changed, 90 insertions(+), 16 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 1e5d83cd..9c540648 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -10,6 +10,7 @@ #![feature(global_asm)] #![feature(compiler_builtins_lib)] #![feature(raw)] +#![feature(vec_resize_default)] #![no_std] diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 5aaa6b37..85312787 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -4,6 +4,8 @@ pub use ucore_process::*; use consts::{MAX_CPU_NUM, MAX_PROCESS_NUM}; use arch::cpu; use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use sync::Condvar; +use core::sync::atomic::*; mod context; @@ -29,6 +31,55 @@ pub fn init() { static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new()]; +/// Ugly solution for sys_wait(0) (wait for any child) +#[derive(Default)] +pub struct Process { + parent: AtomicUsize, + children: Mutex>, + subproc_exit: Condvar, // Trigger parent's when exit +} + +impl Process { + pub fn new_fork(pid: usize, parent: usize) { + PROCESS[pid].parent.store(parent, Ordering::Relaxed); + PROCESS[pid].subproc_exit._clear(); + PROCESS[parent].children.lock().push(pid); + } + pub fn proc_exit(pid: usize) { + let parent = PROCESS[pid].parent.load(Ordering::Relaxed); + PROCESS[parent].subproc_exit.notify_all(); + } + pub fn wait_child() { + Self::current().subproc_exit._wait(); + } + pub fn get_children() -> Vec { + Self::current().children.lock().clone() + } + pub fn do_wait(pid: usize) { + Self::current().children.lock().retain(|&p| p != pid); + } + fn current() -> &'static Self { + &PROCESS[thread::current().id()] + } +} + +lazy_static! { + pub static ref PROCESS: Vec = { + let mut vec = Vec::new(); + vec.resize_default(MAX_PROCESS_NUM); + vec + }; +} + +/// Get current thread struct +pub fn process() -> &'static mut ContextImpl { + use core::mem::transmute; + let (process, _): (&mut ContextImpl, *const ()) = unsafe { + transmute(processor().context()) + }; + process +} + // Implement dependencies for std::thread diff --git a/kernel/src/sync/condvar.rs b/kernel/src/sync/condvar.rs index 5e14d2e6..98d5675f 100644 --- a/kernel/src/sync/condvar.rs +++ b/kernel/src/sync/condvar.rs @@ -33,4 +33,7 @@ impl Condvar { t.unpark(); } } + pub fn _clear(&self) { + self.wait_queue.lock().clear(); + } } \ No newline at end of file diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index f1216887..79c4ea45 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -58,9 +58,9 @@ fn sys_close(fd: usize) -> i32 { /// Fork the current process. Return the child's PID. fn sys_fork(tf: &TrapFrame) -> i32 { - use core::mem::transmute; - let (context, _): (&ContextImpl, *const ()) = unsafe { transmute(processor().context()) }; - let pid = processor().manager().add(context.fork(tf)); + let mut context = process().fork(tf); + let pid = processor().manager().add(context); + Process::new_fork(pid, thread::current().id()); info!("fork: {} -> {}", thread::current().id(), pid); pid as i32 } @@ -68,21 +68,35 @@ fn sys_fork(tf: &TrapFrame) -> i32 { /// Wait the process exit. /// Return the PID. Store exit code to `code` if it's not null. fn sys_wait(pid: usize, code: *mut i32) -> i32 { - assert_ne!(pid, 0, "wait for 0 is not supported yet"); loop { - match processor().manager().get_status(pid) { - Some(Status::Exited(exit_code)) => { - if !code.is_null() { - unsafe { code.write(exit_code as i32); } - } - processor().manager().remove(pid); - return 0; - } - None => return -1, - _ => {} + let wait_procs = match pid { + 0 => Process::get_children(), + _ => vec![pid], + }; + if wait_procs.is_empty() { + return -1; + } + for pid in wait_procs { + match processor().manager().get_status(pid) { + Some(Status::Exited(exit_code)) => { + if !code.is_null() { + unsafe { code.write(exit_code as i32); } + } + processor().manager().remove(pid); + Process::do_wait(pid); + info!("wait: {} -> {}", thread::current().id(), pid); + return 0; + } + None => return -1, + _ => {} + } + } + if pid == 0 { + Process::wait_child(); + } else { + processor().manager().wait(thread::current().id(), pid); + processor().yield_now(); } - processor().manager().wait(thread::current().id(), pid); - processor().yield_now(); } } @@ -94,6 +108,10 @@ fn sys_yield() -> i32 { /// Kill the process fn sys_kill(pid: usize) -> i32 { processor().manager().exit(pid, 0x100); + Process::proc_exit(pid); + if pid == thread::current().id() { + processor().yield_now(); + } 0 } @@ -106,6 +124,7 @@ fn sys_getpid() -> i32 { fn sys_exit(exit_code: usize) -> i32 { let pid = thread::current().id(); processor().manager().exit(pid, exit_code); + Process::proc_exit(pid); processor().yield_now(); unreachable!(); }