diff --git a/src/process/process.rs b/src/process/process.rs index f04347d..005fdb1 100644 --- a/src/process/process.rs +++ b/src/process/process.rs @@ -15,6 +15,9 @@ pub struct Process { pub(in process) status: Status, pub(in process) rsp: usize, pub(in process) is_user: bool, + /// Set (addr, value) after switch. + /// Used to set wait error code. + pub(in process) set_value: Option<(usize, usize)>, } pub type Pid = usize; @@ -46,6 +49,7 @@ impl Process { status: Status::Ready, rsp, is_user: false, + set_value: None, } } @@ -63,6 +67,7 @@ impl Process { status: Status::Running, rsp: 0, // will be set at first schedule is_user: false, + set_value: None, } } @@ -133,6 +138,7 @@ impl Process { status: Status::Ready, rsp, is_user: true, + set_value: None, } } @@ -173,6 +179,7 @@ impl Process { status: Status::Ready, rsp, is_user: true, + set_value: None, } } diff --git a/src/process/processor.rs b/src/process/processor.rs index 1ab7a16..aebe287 100644 --- a/src/process/processor.rs +++ b/src/process/processor.rs @@ -135,6 +135,10 @@ impl Processor { *from_pt = Some(old_table); } + if let Some((addr, value)) = to.set_value.take() { + unsafe { *(addr as *mut usize) = value; } + } + info!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp); } @@ -159,10 +163,13 @@ impl Processor { info!("Processor: {} exit, code: {}", pid, error_code); self.get_mut(pid).status = Status::Exited(error_code); if let Some(waiter) = self.find_waiter(pid) { + info!(" then wakeup {}", waiter); + self.next = Some(waiter); { let p = self.get_mut(waiter); + p.set_value.as_mut().unwrap().1 = error_code; p.status = Status::Ready; - p.set_return_value(error_code); + p.set_return_value(0); } // FIXME: remove this process self.get_mut(pid).parent = 0; @@ -177,7 +184,7 @@ impl Processor { } /// Let current process wait for another - pub fn current_wait_for(&mut self, target: WaitTarget) -> WaitResult { + pub fn current_wait_for(&mut self, target: WaitTarget, code: *mut i32) -> WaitResult { info!("Processor: current {} wait for {:?}", self.current_pid, target); // Find one target process and it's exit code let (pid, exit_code) = match target { @@ -197,11 +204,17 @@ impl Processor { if let Some(exit_code) = exit_code { info!("Processor: {} wait find and remove {}", self.current_pid, pid); self.procs.remove(&pid); + if !code.is_null() { + // WARNING: must be current! (page table) + unsafe { *code = exit_code as i32 }; + } WaitResult::Ok(pid, exit_code) } else { info!("Processor: {} wait for {}", self.current_pid, pid); let current_pid = self.current_pid; - self.get_mut(current_pid).status = Status::Waiting(pid); + let p = self.get_mut(current_pid); + p.status = Status::Waiting(pid); + p.set_value = Some((code as usize, 0)); WaitResult::Blocked } } diff --git a/src/syscall.rs b/src/syscall.rs index 06dbbd7..2176a32 100644 --- a/src/syscall.rs +++ b/src/syscall.rs @@ -98,14 +98,9 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 { 0 => WaitTarget::AnyChild, _ => WaitTarget::Proc(pid), }; - match processor.current_wait_for(target) { - WaitResult::Ok(pid, error_code) => { - if !code.is_null() { - unsafe { *code = error_code as i32 }; - } - 0 // pid as i32 - }, - WaitResult::Blocked => 0, // unused + match processor.current_wait_for(target, code) { + WaitResult::Ok(pid, error_code) => 0, + WaitResult::Blocked => 0, WaitResult::NotExist => -1, } } diff --git a/status.md b/status.md index 4e1747e..d0a088d 100644 --- a/status.md +++ b/status.md @@ -2,7 +2,7 @@ - [ ] badarg - [ ] badsegment - [x] divzero -- [ ] exit +- [x] exit - [x] faultread - [x] faultreadkernel - [x] forktest @@ -13,10 +13,28 @@ - [ ] pgdir - [ ] priority - [ ] sh -- [ ] sleep +- [x] sleep - [x] sleepkill - [x] softint - [x] spin - [x] testbss - [x] waitkill - [x] yield + +## xv6 64bit user programs pass status +- [ ] cat +- [ ] chmod +- [ ] echo +- [ ] forktest +- [ ] grep +- [ ] init +- [ ] kill +- [ ] ln +- [ ] ls +- [ ] mkdir +- [ ] rm +- [ ] sh +- [ ] stressfs +- [ ] usertests +- [ ] wc +- [ ] zombie