|
|
|
@ -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<Pid>;
|
|
|
|
|
fn select(&mut self) -> Option<Pid>;
|
|
|
|
|
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<Pid> {
|
|
|
|
|
fn select(&mut self) -> Option<Pid> {
|
|
|
|
|
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<Pid> {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|