diff --git a/crate/process/src/process_manager.rs b/crate/process/src/process_manager.rs index beca345..b03bff1 100644 --- a/crate/process/src/process_manager.rs +++ b/crate/process/src/process_manager.rs @@ -39,23 +39,17 @@ pub struct ProcessManager { scheduler: Mutex>, wait_queue: Vec>>, event_hub: Mutex>, + exit_handler: fn(Pid), } impl ProcessManager { - pub fn new(scheduler: Box, max_proc_num: usize) -> Self { + pub fn new(scheduler: Box, max_proc_num: usize, exit_handler: fn(Pid)) -> Self { ProcessManager { - procs: { - let mut vec = Vec::new(); - vec.resize_default(max_proc_num); - vec - }, + procs: new_vec_default(max_proc_num), scheduler: Mutex::new(scheduler), - wait_queue: { - let mut vec = Vec::new(); - vec.resize_default(max_proc_num); - vec - }, + wait_queue: new_vec_default(max_proc_num), event_hub: Mutex::new(EventHub::new()), + exit_handler, } } @@ -124,7 +118,7 @@ impl ProcessManager { proc.context = Some(context); match proc.status { Status::Ready => self.scheduler.lock().insert(pid), - Status::Exited(_) => proc.context = None, + Status::Exited(_) => self.exit_handler(pid, proc), _ => {} } } @@ -152,7 +146,7 @@ impl ProcessManager { _ => proc.status = status, } match proc.status { - Status::Exited(_) => proc.context = None, + Status::Exited(_) => self.exit_handler(pid, proc), _ => {} } } @@ -189,8 +183,20 @@ impl ProcessManager { pub fn exit(&self, pid: Pid, code: ExitCode) { 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); } + proc.context = None; + (self.exit_handler)(pid); } } + +fn new_vec_default(size: usize) -> Vec { + let mut vec = Vec::new(); + vec.resize_default(size); + vec +} diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index 2b8b188..a9e9ecf 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -80,6 +80,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { T_PGFLT => page_fault(tf), T_IRQ0...63 => { let irq = tf.trap_num as u8 - T_IRQ0; + super::ack(irq); // must ack before switching match irq { IRQ_TIMER => ::trap::timer(), IRQ_KBD => keyboard(), @@ -88,7 +89,6 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { IRQ_IDE => ide(), _ => panic!("Invalid IRQ number: {}", irq), } - super::ack(irq); } T_SWITCH_TOK => to_kernel(tf), T_SWITCH_TOU => to_user(tf), diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 8531278..c5b3413 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -12,7 +12,7 @@ mod context; pub fn init() { // NOTE: max_time_slice <= 5 to ensure 'priority' test pass let scheduler = Box::new(scheduler::RRScheduler::new(5)); - let manager = Arc::new(ProcessManager::new(scheduler, MAX_PROCESS_NUM)); + let manager = Arc::new(ProcessManager::new(scheduler, MAX_PROCESS_NUM, Process::proc_exit)); extern fn idle(_arg: usize) -> ! { loop { cpu::halt(); } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 79c4ea4..80037c8 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -91,6 +91,7 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 { _ => {} } } + info!("wait: {} -> {}, sleep", thread::current().id(), pid); if pid == 0 { Process::wait_child(); } else { @@ -107,8 +108,8 @@ fn sys_yield() -> i32 { /// Kill the process fn sys_kill(pid: usize) -> i32 { + info!("kill: {}", pid); processor().manager().exit(pid, 0x100); - Process::proc_exit(pid); if pid == thread::current().id() { processor().yield_now(); } @@ -123,8 +124,8 @@ fn sys_getpid() -> i32 { /// Exit the current process fn sys_exit(exit_code: usize) -> i32 { let pid = thread::current().id(); + info!("exit: {}", pid); processor().manager().exit(pid, exit_code); - Process::proc_exit(pid); processor().yield_now(); unreachable!(); }