diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index ee9ca0f..44ff6a1 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -25,8 +25,6 @@ use super::TrapFrame; #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) -> usize { - let mut rsp = tf as *const _ as usize; - // Dispatch match tf.trap_num as u8 { T_BRKPT => breakpoint(), @@ -36,7 +34,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) -> usize { T_IRQ0...64 => { let irq = tf.trap_num as u8 - T_IRQ0; match irq { - IRQ_TIMER => timer(tf, &mut rsp), + IRQ_TIMER => timer(), IRQ_KBD => keyboard(), IRQ_COM1 => com1(), IRQ_COM2 => com2(), @@ -50,11 +48,15 @@ pub extern fn rust_trap(tf: &mut TrapFrame) -> usize { } T_SWITCH_TOK => to_kernel(tf), T_SWITCH_TOU => to_user(tf), - T_SYSCALL => syscall(tf, &mut rsp), - 0x80 => syscall32(tf, &mut rsp), + T_SYSCALL => syscall(tf), + T_SYSCALL32 => syscall32(tf), _ => panic!("Unhandled interrupt {:x}", tf.trap_num), } + let mut rsp = tf as *const _ as usize; + use process::PROCESSOR; + PROCESSOR.try().unwrap().lock().schedule(&mut rsp); + // Set return rsp if to user let tf = unsafe { &*(rsp as *const TrapFrame) }; set_return_rsp(tf); @@ -115,9 +117,10 @@ fn com2() { COM2.lock().receive(); } -fn timer(tf: &mut TrapFrame, rsp: &mut usize) { - use process; - process::timer_handler(tf, rsp); +fn timer() { + use process::PROCESSOR; + let mut processor = PROCESSOR.try().unwrap().lock(); + processor.tick(); } fn to_user(tf: &mut TrapFrame) { @@ -135,17 +138,17 @@ fn to_kernel(tf: &mut TrapFrame) { tf.ss = gdt::KDATA_SELECTOR.0 as usize; } -fn syscall(tf: &mut TrapFrame, rsp: &mut usize) { +fn syscall(tf: &mut TrapFrame) { info!("\nInterupt: Syscall {:#x?}", tf.rax); use syscall::syscall; - let ret = syscall(tf, rsp, false); + let ret = syscall(tf, false); tf.rax = ret as usize; } -fn syscall32(tf: &mut TrapFrame, rsp: &mut usize) { +fn syscall32(tf: &mut TrapFrame) { // info!("\nInterupt: Syscall {:#x?}", tf.rax); use syscall::syscall; - let ret = syscall(tf, rsp, true); + let ret = syscall(tf, true); tf.rax = ret as usize; } diff --git a/src/process/mod.rs b/src/process/mod.rs index b7f33c3..928f1ea 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -36,11 +36,6 @@ extern fn idle_thread() { } } -pub fn timer_handler(tf: &TrapFrame, rsp: &mut usize) { - let mut processor = PROCESSOR.try().unwrap().lock(); - processor.tick(rsp); -} - pub fn add_user_process(name: impl AsRef, data: &[u8]) { let mut processor = PROCESSOR.try().unwrap().lock(); let mut mc = MC.try().unwrap().lock(); diff --git a/src/process/processor.rs b/src/process/processor.rs index ed91dd1..1ab7a16 100644 --- a/src/process/processor.rs +++ b/src/process/processor.rs @@ -12,6 +12,8 @@ pub struct Processor { /// All kernel threads share one page table. /// When running user process, it will be stored here. kernel_page_table: Option, + /// Choose what on next schedule ? + next: Option, } impl Processor { @@ -25,9 +27,15 @@ impl Processor { e }, kernel_page_table: None, + next: None, } } + pub fn set_reschedule(&mut self) { + let pid = self.current_pid; + self.get_mut(pid).status = Status::Ready; + } + fn alloc_pid(&self) -> Pid { let mut next: Pid = 0; for &i in self.procs.keys() { @@ -42,18 +50,19 @@ impl Processor { /// Called by timer. /// Handle events. - pub fn tick(&mut self, rsp: &mut usize) { + pub fn tick(&mut self) { self.event_hub.tick(); while let Some(event) = self.event_hub.pop() { debug!("Processor: event {:?}", event); match event { Event::Schedule => { self.event_hub.push(10, Event::Schedule); - self.schedule(rsp); + self.set_reschedule(); }, Event::Wakeup(pid) => { self.get_mut(pid).status = Status::Ready; - self.switch_to(pid, rsp); + self.set_reschedule(); + self.next = Some(pid); }, } } @@ -70,8 +79,13 @@ impl Processor { pid } + /// Called every interrupt end + /// Do schedule ONLY IF current status != Running pub fn schedule(&mut self, rsp: &mut usize) { - let pid = self.find_next(); + if self.current().status == Status::Running { + return; + } + let pid = self.next.take().unwrap_or_else(|| self.find_next()); self.switch_to(pid, rsp); } @@ -84,7 +98,7 @@ impl Processor { /// Switch process to `pid`, switch page table if necessary. /// Store `rsp` and point it to target kernel stack. - /// The current status will be set to `Ready` if it is `Running` now. + /// The current status must be set before, and not be `Running`. fn switch_to(&mut self, pid: Pid, rsp: &mut usize) { // for debug print let pid0 = self.current_pid; @@ -98,9 +112,7 @@ impl Processor { let (from, to) = self.procs.get_mut2(pid0, pid); // set `from` - if from.status == Status::Running { - from.status = Status::Ready; - } + assert_ne!(from.status, Status::Running); from.rsp = *rsp; // set `to` @@ -144,7 +156,6 @@ impl Processor { } pub fn exit(&mut self, pid: Pid, error_code: ErrorCode) { - assert_ne!(pid, self.current_pid); info!("Processor: {} exit, code: {}", pid, error_code); self.get_mut(pid).status = Status::Exited(error_code); if let Some(waiter) = self.find_waiter(pid) { @@ -153,8 +164,10 @@ impl Processor { p.status = Status::Ready; p.set_return_value(error_code); } - info!("Processor: remove {}", pid); - self.procs.remove(&pid); + // FIXME: remove this process + self.get_mut(pid).parent = 0; +// info!("Processor: remove {}", pid); +// self.procs.remove(&pid); } } diff --git a/src/syscall.rs b/src/syscall.rs index e973d41..06dbbd7 100644 --- a/src/syscall.rs +++ b/src/syscall.rs @@ -9,7 +9,7 @@ use util; /// 当发生系统调用中断时,中断服务例程将控制权转移到这里。 /// 它从中断帧中提取参数,根据系统调用号分发执行具体操作。 /// 它同时支持 xv6的64位程序 和 uCore的32位程序。 -pub fn syscall(tf: &TrapFrame, rsp: &mut usize, is32: bool) -> i32 { +pub fn syscall(tf: &TrapFrame, is32: bool) -> i32 { let id = match is32 { false => Syscall::Xv6(tf.rax), true => Syscall::Ucore(tf.rax), @@ -29,19 +29,19 @@ pub fn syscall(tf: &TrapFrame, rsp: &mut usize, is32: bool) -> i32 { Syscall::Xv6(SYS_CLOSE) | Syscall::Ucore(UCORE_SYS_CLOSE) => sys_close(args[0]), Syscall::Xv6(SYS_WAIT) | Syscall::Ucore(UCORE_SYS_WAIT) => - sys_wait(rsp, args[0], args[1] as *mut i32), + sys_wait(args[0], args[1] as *mut i32), Syscall::Xv6(SYS_FORK) | Syscall::Ucore(UCORE_SYS_FORK) => sys_fork(tf), Syscall::Xv6(SYS_KILL) | Syscall::Ucore(UCORE_SYS_KILL) => sys_kill(args[0]), Syscall::Xv6(SYS_EXIT) | Syscall::Ucore(UCORE_SYS_EXIT) => - sys_exit(rsp, args[0]), + sys_exit(args[0]), Syscall::Ucore(UCORE_SYS_YIELD) => - sys_yield(rsp), + sys_yield(), Syscall::Ucore(UCORE_SYS_GETPID) => sys_getpid(), Syscall::Ucore(UCORE_SYS_SLEEP) => - sys_sleep(rsp, args[0]), + sys_sleep(args[0]), Syscall::Ucore(UCORE_SYS_GETTIME) => sys_get_time(), Syscall::Ucore(UCORE_SYS_PUTC) => @@ -92,7 +92,7 @@ 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(rsp: &mut usize, pid: usize, code: *mut i32) -> i32 { +fn sys_wait(pid: usize, code: *mut i32) -> i32 { let mut processor = PROCESSOR.try().unwrap().lock(); let target = match pid { 0 => WaitTarget::AnyChild, @@ -105,18 +105,15 @@ fn sys_wait(rsp: &mut usize, pid: usize, code: *mut i32) -> i32 { } 0 // pid as i32 }, - WaitResult::Blocked => { - processor.schedule(rsp); - 0 /* unused */ - }, + WaitResult::Blocked => 0, // unused WaitResult::NotExist => -1, } } -fn sys_yield(rsp: &mut usize) -> i32 { +fn sys_yield() -> i32 { info!("yield:"); let mut processor = PROCESSOR.try().unwrap().lock(); - processor.schedule(rsp); + processor.set_reschedule(); 0 } @@ -132,19 +129,17 @@ fn sys_getpid() -> i32 { } /// Exit the current process -fn sys_exit(rsp: &mut usize, error_code: usize) -> i32 { +fn sys_exit(error_code: usize) -> i32 { let mut processor = PROCESSOR.try().unwrap().lock(); let pid = processor.current_pid(); - processor.schedule(rsp); processor.exit(pid, error_code); 0 } -fn sys_sleep(rsp: &mut usize, time: usize) -> i32 { +fn sys_sleep(time: usize) -> i32 { info!("sleep: {} ticks", time); let mut processor = PROCESSOR.try().unwrap().lock(); let pid = processor.current_pid(); - processor.schedule(rsp); processor.sleep(pid, time); 0 }