Add `Scheduler.move_to_head(pid)` to replace `Processor.next`

Rename `set_reschedule` to `yield_now`
master
WangRunji 6 years ago
parent 501ce6c4be
commit 7dd9494389

@ -33,8 +33,6 @@ pub struct Processor_<T: Context, S: Scheduler> {
procs: BTreeMap<Pid, Process<T>>,
current_pid: Pid,
event_hub: EventHub<Event>,
/// Choose what on next schedule ?
next: Option<Pid>,
// WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow
scheduler: S,
}
@ -65,7 +63,6 @@ impl<T: Context, S: Scheduler> Processor_<T, S> {
},
current_pid: 0,
event_hub: EventHub::new(),
next: None,
scheduler,
}
}
@ -74,7 +71,7 @@ impl<T: Context, S: Scheduler> Processor_<T, S> {
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<T: Context, S: Scheduler> Processor_<T, S> {
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<T: Context, S: Scheduler> Processor_<T, S> {
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<T: Context, S: Scheduler> Processor_<T, S> {
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<T: Context, S: Scheduler> Processor_<T, S> {
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);
}
}

@ -9,6 +9,7 @@ pub trait Scheduler {
fn select(&mut self) -> Option<Pid>;
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 {

@ -107,7 +107,7 @@ impl<S: ThreadSupport> ThreadMod<S> {
pub fn yield_now() {
info!("yield:");
let mut processor = S::processor();
processor.set_reschedule();
processor.yield_now();
processor.schedule();
}

Loading…
Cancel
Save