diff --git a/crate/process/src/processor.rs b/crate/process/src/processor.rs index 9083dad..7db17f6 100644 --- a/crate/process/src/processor.rs +++ b/crate/process/src/processor.rs @@ -33,8 +33,6 @@ pub struct Processor_ { procs: BTreeMap>, current_pid: Pid, event_hub: EventHub, - /// Choose what on next schedule ? - next: Option, // WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow scheduler: S, } @@ -65,7 +63,6 @@ impl Processor_ { }, current_pid: 0, event_hub: EventHub::new(), - next: None, scheduler, } } @@ -74,7 +71,7 @@ impl Processor_ { self.scheduler.set_priority(self.current_pid, priority); } - pub fn set_reschedule(&mut self) { + pub fn yield_now(&mut self) { let pid = self.current_pid; self.set_status(pid, Status::Ready); } @@ -108,7 +105,7 @@ impl Processor_ { pub fn tick(&mut self) { let current_pid = self.current_pid; if self.scheduler.tick(current_pid) { - self.set_reschedule(); + self.yield_now(); } self.event_hub.tick(); while let Some(event) = self.event_hub.pop() { @@ -116,12 +113,12 @@ impl Processor_ { match event { Event::Schedule => { self.event_hub.push(10, Event::Schedule); - self.set_reschedule(); + self.yield_now(); }, Event::Wakeup(pid) => { self.set_status(pid, Status::Ready); - self.set_reschedule(); - self.next = Some(pid); + self.yield_now(); + self.scheduler.move_to_head(pid); }, } } @@ -150,13 +147,13 @@ impl Processor_ { if self.get(self.current_pid).status == Status::Running { return; } - let pid = self.next.take().unwrap_or_else(|| self.scheduler.select().unwrap()); + let pid = self.scheduler.select().unwrap(); self.switch_to(pid); } - /// Switch process to `pid`, switch page table if necessary. - /// Store `rsp` and point it to target kernel stack. + /// Switch to process `pid`. /// The current status must be set before, and not be `Running`. + /// The target status must be `Ready`. fn switch_to(&mut self, pid: Pid) { // for debug print let pid0 = self.current_pid; @@ -203,7 +200,7 @@ impl Processor_ { if let Some(waiter) = self.find_waiter(pid) { info!(" then wakeup {}", waiter); self.set_status(waiter, Status::Ready); - self.next = Some(waiter); + self.scheduler.move_to_head(waiter); } } diff --git a/crate/process/src/scheduler.rs b/crate/process/src/scheduler.rs index 4d8e696..9ab52fa 100644 --- a/crate/process/src/scheduler.rs +++ b/crate/process/src/scheduler.rs @@ -9,6 +9,7 @@ pub trait Scheduler { fn select(&mut self) -> Option; fn tick(&mut self, current: Pid) -> bool; // need reschedule? fn set_priority(&mut self, pid: Pid, priority: u8); + fn move_to_head(&mut self, pid: Pid); } pub use self::rr::RRScheduler; @@ -79,6 +80,14 @@ mod rr { fn set_priority(&mut self, pid: usize, priority: u8) { } + + fn move_to_head(&mut self, pid: usize) { + let pid = pid + 1; + assert!(self.infos[pid].present); + self._list_remove(pid); + self._list_add_after(pid, 0); + trace!("rr move_to_head {}", pid - 1); + } } impl RRScheduler { @@ -95,6 +104,10 @@ mod rr { self.infos[prev].next = i; self.infos[at].prev = i; } + fn _list_add_after(&mut self, i: Pid, at: Pid) { + let next = self.infos[at].next; + self._list_add_before(i, next); + } fn _list_remove(&mut self, i: Pid) { let next = self.infos[i].next; let prev = self.infos[i].prev; @@ -156,13 +169,17 @@ mod stride { let info = &mut self.infos[pid]; assert!(info.present); info.present = false; - // BinaryHeap only support pop the top. - // So in order to remove an arbitrary element, - // we have to take all elements into a Vec, - // then push the rest back. - let rest: Vec<_> = self.queue.drain().filter(|&p| p.1 != pid).collect(); - use core::iter::FromIterator; - self.queue = BinaryHeap::from_iter(rest.into_iter()); + if self.queue.peek().is_some() && self.queue.peek().unwrap().1 == pid { + self.queue.pop(); + } else { + // BinaryHeap only support pop the top. + // So in order to remove an arbitrary element, + // we have to take all elements into a Vec, + // then push the rest back. + let rest: Vec<_> = self.queue.drain().filter(|&p| p.1 != pid).collect(); + use core::iter::FromIterator; + self.queue = BinaryHeap::from_iter(rest.into_iter()); + } trace!("stride remove {}", pid); } @@ -195,6 +212,15 @@ mod stride { self.infos[pid].priority = priority; trace!("stride {} priority = {}", pid, priority); } + + fn move_to_head(&mut self, pid: Pid) { + if self.queue.peek().is_some() { + let stride = -self.queue.peek().unwrap().0; + self.remove(pid); + self.infos[pid].stride = stride; + self.insert(pid); + } + } } impl StrideScheduler { diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index 1a93dd8..8786cc8 100644 --- a/crate/process/src/thread.rs +++ b/crate/process/src/thread.rs @@ -107,7 +107,7 @@ impl ThreadMod { pub fn yield_now() { info!("yield:"); let mut processor = S::processor(); - processor.set_reschedule(); + processor.yield_now(); processor.schedule(); }