diff --git a/crate/process/src/lib.rs b/crate/process/src/lib.rs index 07c2e2c..d6e4c7d 100644 --- a/crate/process/src/lib.rs +++ b/crate/process/src/lib.rs @@ -4,6 +4,7 @@ #![feature(linkage)] #![feature(nll)] #![feature(vec_resize_default)] +#![feature(exact_size_is_empty)] extern crate alloc; #[macro_use] diff --git a/crate/process/src/process_manager.rs b/crate/process/src/process_manager.rs index b8931e7..63878c1 100644 --- a/crate/process/src/process_manager.rs +++ b/crate/process/src/process_manager.rs @@ -56,9 +56,17 @@ impl ProcessManager { fn alloc_pid(&self) -> Pid { for (i, proc) in self.procs.iter().enumerate() { - if proc.lock().is_none() { + let mut proc_lock = proc.lock(); + if proc_lock.is_none() { return i; } + match proc_lock.as_mut().unwrap().status { + Status::Exited(_) => if self.wait_queue[i].lock().is_empty() { + *proc_lock = None; + return i; + }, + _ => {}, + } } panic!("Process number exceeded"); } @@ -130,7 +138,7 @@ impl ProcessManager { fn set_status(&self, pid: Pid, status: Status) { let mut proc_lock = self.procs[pid].lock(); let mut proc = proc_lock.as_mut().expect("process not exist"); - trace!("process {} {:?} -> {:?}", pid, proc.status, status); + //info!("process {} {:?} -> {:?}", pid, proc.status, status); { // limit the lifetime of scheduler let mut scheduler = self.scheduler.lock(); match (&proc.status, &status) { @@ -157,14 +165,25 @@ impl ProcessManager { pub fn get_status(&self, pid: Pid) -> Option { - self.procs[pid].lock().as_ref().map(|p| p.status.clone()) + let mut proc_lock = self.procs[pid].lock(); + if proc_lock.is_none() { + return None; + } + match proc_lock.as_ref().unwrap().status { + Status::Exited(_) => if self.wait_queue[pid].lock().is_empty() { + *proc_lock = None; + return None; + }, + _ => {}, + } + proc_lock.as_ref().map(|p| p.status.clone()) } - pub fn remove(&self, pid: Pid) { - let mut proc_lock = self.procs[pid].lock(); + pub fn wait_done(&self, pid: Pid, target: Pid) { + let mut proc_lock = self.procs[target].lock(); let proc = proc_lock.as_ref().expect("process not exist"); match proc.status { - Status::Exited(_) => *proc_lock = None, + Status::Exited(_) => self.wait_queue[target].lock().retain(|&i| i != pid), _ => panic!("can not remove non-exited process"), } } @@ -185,17 +204,28 @@ impl ProcessManager { self.set_status(pid, Status::Waiting(target)); self.wait_queue[target].lock().push(pid); } + pub fn wait_child(&self, pid: Pid) { + self.set_status(pid, Status::Waiting(0)); + } + + pub fn set_parent(&self, pid: Pid, target: Pid) { + self.wait_queue[target].lock().push(pid); + } + pub fn del_parent(&self, pid: Pid, target: Pid) { + self.wait_queue[target].lock().retain(|&i| i != pid); + } pub fn exit(&self, pid: Pid, code: ExitCode) { + (self.exit_handler)(pid); self.set_status(pid, Status::Exited(code)); } /// Called when a process exit fn exit_handler(&self, pid: Pid, proc: &mut Process) { - for waiter in self.wait_queue[pid].lock().drain(..) { - self.wakeup(waiter); + for waiter in self.wait_queue[pid].lock().iter() { + self.wakeup(*waiter); } - proc.context = None; - (self.exit_handler)(pid); + + //proc.context = None; } } fn new_vec_default(size: usize) -> Vec { diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index 7ffa0e6..3742a21 100644 --- a/crate/process/src/thread.rs +++ b/crate/process/src/thread.rs @@ -151,7 +151,7 @@ impl JoinHandle { loop { match processor().manager().get_status(self.thread.pid) { Some(Status::Exited(exit_code)) => { - processor().manager().remove(self.thread.pid); + processor().manager().wait_done(current().id(), self.thread.pid); // Find return value on the heap from the exit code. return Ok(unsafe { *Box::from_raw(exit_code as *mut T) }); } diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 938dff2..c90499d 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -63,9 +63,11 @@ pub fn shell() { //memory_set_map_swappable(processor().get_context_mut(pid).get_memory_set_mut()); processor().manager().wait(thread::current().id(), pid); processor().yield_now(); + processor().manager().wait_done(thread::current().id(), pid); } else { println!("Program not exist"); } + //break; } unsafe { dealloc(buf.as_mut_ptr(), layout) }; } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 8bdacc5..fdc197a 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -36,21 +36,19 @@ static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new( 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(); + info!("proc_exit"); + for child in PROCESS[pid].children.lock().clone() { + info!("del child {}", child); + processor().manager().del_parent(pid, child); + } } pub fn get_children() -> Vec { Self::current().children.lock().clone() diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index bcc9bf7..0b755d0 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -65,6 +65,7 @@ fn sys_fork(tf: &TrapFrame) -> i32 { let mut context = process().fork(tf); //memory_set_map_swappable(context.get_memory_set_mut()); let pid = processor().manager().add(context); + processor().manager().set_parent(thread::current().id(), pid); Process::new_fork(pid, thread::current().id()); //memory_set_map_swappable(processor.get_context_mut(pid).get_memory_set_mut()); info!("fork: {} -> {}", thread::current().id(), pid); @@ -88,7 +89,7 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 { if !code.is_null() { unsafe { code.write(exit_code as i32); } } - processor().manager().remove(pid); + processor().manager().wait_done(thread::current().id(), pid); Process::do_wait(pid); info!("wait: {} -> {}", thread::current().id(), pid); return 0; @@ -98,7 +99,8 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 { } } if pid == 0 { - Process::wait_child(); + processor().manager().wait_child(thread::current().id()); + processor().yield_now(); } else { processor().manager().wait(thread::current().id(), pid); processor().yield_now();