From a74bb50b8822eabf954d03e92f79c303e20a7b69 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 23 May 2018 12:41:13 +0800 Subject: [PATCH] Impl StrideScheduler, pass test `priority` --- src/process/processor.rs | 12 +++-- src/process/scheduler.rs | 102 +++++++++++++++++++++++++++++++++++++-- src/syscall.rs | 9 ++++ status.md | 2 +- 4 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/process/processor.rs b/src/process/processor.rs index 322d830..5c30abc 100644 --- a/src/process/processor.rs +++ b/src/process/processor.rs @@ -17,7 +17,7 @@ pub struct Processor { /// Choose what on next schedule ? next: Option, // WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow - scheduler: RRScheduler, + scheduler: StrideScheduler, } impl Processor { @@ -28,10 +28,15 @@ impl Processor { event_hub: EventHub::new(), kernel_page_table: None, next: None, - scheduler: RRScheduler::new(100), + // NOTE: max_time_slice <= 5 to ensure 'priority' test pass + scheduler: StrideScheduler::new(5), } } + pub fn lab6_set_priority(&mut self, priority: u8) { + self.scheduler.set_priority(self.current_pid, priority); + } + pub fn set_reschedule(&mut self) { let pid = self.current_pid; self.set_status(pid, Status::Ready); @@ -194,14 +199,13 @@ impl Processor { return WaitResult::NotExist; } let pid = self.try_wait(pid).unwrap_or_else(|| { - info!("Processor: {} wait for {}", self.current_pid, pid); let current_pid = self.current_pid; self.set_status(current_pid, Status::Waiting(pid)); self.schedule(); // yield self.try_wait(pid).unwrap() }); let exit_code = self.get(pid).exit_code().unwrap(); - info!("Processor: {} wait find and remove {}", self.current_pid, pid); + info!("Processor: {} wait end and remove {}", self.current_pid, pid); self.procs.remove(&pid); WaitResult::Ok(pid, exit_code) } diff --git a/src/process/scheduler.rs b/src/process/scheduler.rs index 4e420c4..cc87cd2 100644 --- a/src/process/scheduler.rs +++ b/src/process/scheduler.rs @@ -1,11 +1,12 @@ use super::*; use consts::MAX_PROCESS_NUM; +use alloc::BinaryHeap; /// pub trait Scheduler { fn insert(&mut self, pid: Pid); fn remove(&mut self, pid: Pid); - fn select(&self) -> Option; + fn select(&mut self) -> Option; fn tick(&mut self, current: Pid) -> bool; // need reschedule? } @@ -34,7 +35,7 @@ impl Scheduler for RRScheduler { } } self._list_add_before(pid, 0); - trace!("RRScheduler: insert {}", pid - 1); + debug!("RRScheduler: insert {}", pid - 1); } fn remove(&mut self, pid: Pid) { @@ -42,15 +43,15 @@ impl Scheduler for RRScheduler { assert!(self.infos[pid].present); self.infos[pid].present = false; self._list_remove(pid); - trace!("RRScheduler: remove {}", pid - 1); + debug!("RRScheduler: remove {}", pid - 1); } - fn select(&self) -> Option { + fn select(&mut self) -> Option { let ret = match self.infos[0].next { 0 => None, i => Some(i - 1), }; - trace!("RRScheduler: select {:?}", ret); + debug!("RRScheduler: select {:?}", ret); ret } @@ -90,4 +91,95 @@ impl RRScheduler { self.infos[i].next = 0; self.infos[i].prev = 0; } +} + + +pub struct StrideScheduler { + max_time_slice: usize, + infos: [StrideProcInfo; MAX_PROCESS_NUM], + queue: BinaryHeap<(Stride, Pid)>, // It's max heap, so pass < 0 +} + +#[derive(Debug, Default, Copy, Clone)] +struct StrideProcInfo { + present: bool, + rest_slice: usize, + stride: Stride, + priority: u8, +} + +impl StrideProcInfo { + fn pass(&mut self) { + const BIG_STRIDE: Stride = 1 << 20; + let pass = if self.priority == 0 { + BIG_STRIDE + } else { + BIG_STRIDE / self.priority as Stride + }; + // FIXME: overflowing_add is not working ??? + // self.stride.overflowing_add(pass); + self.stride += pass; + } +} + +type Stride = i32; + +impl Scheduler for StrideScheduler { + fn insert(&mut self, pid: Pid) { + let info = &mut self.infos[pid]; + assert!(!info.present); + info.present = true; + if info.rest_slice == 0 { + info.rest_slice = self.max_time_slice; + } + self.queue.push((-info.stride, pid)); + debug!("StrideScheduler: insert {}", pid); + } + + fn remove(&mut self, pid: Pid) { + let info = &mut self.infos[pid]; + assert!(info.present); + info.present = false; + // FIXME: Support removing any element + assert_eq!(self.queue.pop().unwrap().1, pid, "Can only remove the top"); + debug!("StrideScheduler: remove {}", pid); + } + + fn select(&mut self) -> Option { + let ret = self.queue.peek().map(|&(_, pid)| pid); + if let Some(pid) = ret { + let old_stride = self.infos[pid].stride; + self.infos[pid].pass(); + let stride = self.infos[pid].stride; + debug!("StrideScheduler: {} stride {:#x} -> {:#x}", pid, old_stride, stride); + } + debug!("StrideScheduler: select {:?}", ret); + ret + } + + fn tick(&mut self, current: Pid) -> bool { + assert!(!self.infos[current].present); + + let rest = &mut self.infos[current].rest_slice; + if *rest > 0 { + *rest -= 1; + } else { + warn!("current process rest_slice = 0, need reschedule") + } + *rest == 0 + } +} + +impl StrideScheduler { + pub fn new(max_time_slice: usize) -> Self { + StrideScheduler { + max_time_slice, + infos: [StrideProcInfo::default(); MAX_PROCESS_NUM], + queue: BinaryHeap::new(), + } + } + pub fn set_priority(&mut self, pid: Pid, priority: u8) { + self.infos[pid].priority = priority; + debug!("StrideScheduler: {} priority = {}", pid, priority); + } } \ No newline at end of file diff --git a/src/syscall.rs b/src/syscall.rs index ec2d87a..f8ec6ee 100644 --- a/src/syscall.rs +++ b/src/syscall.rs @@ -44,6 +44,8 @@ pub fn syscall(tf: &TrapFrame, is32: bool) -> i32 { sys_sleep(args[0]), Syscall::Ucore(UCORE_SYS_GETTIME) => sys_get_time(), + Syscall::Ucore(UCORE_SYS_LAB6_SET_PRIORITY) => + sys_lab6_set_priority(args[0]), Syscall::Ucore(UCORE_SYS_PUTC) => { print!("{}", args[0] as u8 as char); @@ -144,6 +146,12 @@ fn sys_get_time() -> i32 { processor.get_time() as i32 } +fn sys_lab6_set_priority(priority: usize) -> i32 { + let mut processor = PROCESSOR.try().unwrap().lock(); + processor.lab6_set_priority(priority as u8); + 0 +} + #[derive(Debug)] enum Syscall { @@ -199,3 +207,4 @@ const UCORE_SYS_FSYNC: usize = 111; const UCORE_SYS_GETCWD: usize = 121; const UCORE_SYS_GETDIRENTRY: usize = 128; const UCORE_SYS_DUP: usize = 130; +const UCORE_SYS_LAB6_SET_PRIORITY: usize = 255; diff --git a/status.md b/status.md index d0a088d..da7b497 100644 --- a/status.md +++ b/status.md @@ -11,7 +11,7 @@ - [ ] ls - [x] matrix - [ ] pgdir -- [ ] priority +- [x] priority - [ ] sh - [x] sleep - [x] sleepkill