Impl StrideScheduler, pass test `priority`

master
WangRunji 7 years ago
parent 9418d5de70
commit a74bb50b88

@ -17,7 +17,7 @@ pub struct Processor {
/// Choose what on next schedule ? /// Choose what on next schedule ?
next: Option<Pid>, next: Option<Pid>,
// WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow // WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow
scheduler: RRScheduler, scheduler: StrideScheduler,
} }
impl Processor { impl Processor {
@ -28,10 +28,15 @@ impl Processor {
event_hub: EventHub::new(), event_hub: EventHub::new(),
kernel_page_table: None, kernel_page_table: None,
next: 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) { pub fn set_reschedule(&mut self) {
let pid = self.current_pid; let pid = self.current_pid;
self.set_status(pid, Status::Ready); self.set_status(pid, Status::Ready);
@ -194,14 +199,13 @@ impl Processor {
return WaitResult::NotExist; return WaitResult::NotExist;
} }
let pid = self.try_wait(pid).unwrap_or_else(|| { let pid = self.try_wait(pid).unwrap_or_else(|| {
info!("Processor: {} wait for {}", self.current_pid, pid);
let current_pid = self.current_pid; let current_pid = self.current_pid;
self.set_status(current_pid, Status::Waiting(pid)); self.set_status(current_pid, Status::Waiting(pid));
self.schedule(); // yield self.schedule(); // yield
self.try_wait(pid).unwrap() self.try_wait(pid).unwrap()
}); });
let exit_code = self.get(pid).exit_code().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); self.procs.remove(&pid);
WaitResult::Ok(pid, exit_code) WaitResult::Ok(pid, exit_code)
} }

@ -1,11 +1,12 @@
use super::*; use super::*;
use consts::MAX_PROCESS_NUM; use consts::MAX_PROCESS_NUM;
use alloc::BinaryHeap;
/// ///
pub trait Scheduler { pub trait Scheduler {
fn insert(&mut self, pid: Pid); fn insert(&mut self, pid: Pid);
fn remove(&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? fn tick(&mut self, current: Pid) -> bool; // need reschedule?
} }
@ -34,7 +35,7 @@ impl Scheduler for RRScheduler {
} }
} }
self._list_add_before(pid, 0); self._list_add_before(pid, 0);
trace!("RRScheduler: insert {}", pid - 1); debug!("RRScheduler: insert {}", pid - 1);
} }
fn remove(&mut self, pid: Pid) { fn remove(&mut self, pid: Pid) {
@ -42,15 +43,15 @@ impl Scheduler for RRScheduler {
assert!(self.infos[pid].present); assert!(self.infos[pid].present);
self.infos[pid].present = false; self.infos[pid].present = false;
self._list_remove(pid); 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 { let ret = match self.infos[0].next {
0 => None, 0 => None,
i => Some(i - 1), i => Some(i - 1),
}; };
trace!("RRScheduler: select {:?}", ret); debug!("RRScheduler: select {:?}", ret);
ret ret
} }
@ -91,3 +92,94 @@ impl RRScheduler {
self.infos[i].prev = 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);
}
}

@ -44,6 +44,8 @@ pub fn syscall(tf: &TrapFrame, is32: bool) -> i32 {
sys_sleep(args[0]), sys_sleep(args[0]),
Syscall::Ucore(UCORE_SYS_GETTIME) => Syscall::Ucore(UCORE_SYS_GETTIME) =>
sys_get_time(), sys_get_time(),
Syscall::Ucore(UCORE_SYS_LAB6_SET_PRIORITY) =>
sys_lab6_set_priority(args[0]),
Syscall::Ucore(UCORE_SYS_PUTC) => Syscall::Ucore(UCORE_SYS_PUTC) =>
{ {
print!("{}", args[0] as u8 as char); print!("{}", args[0] as u8 as char);
@ -144,6 +146,12 @@ fn sys_get_time() -> i32 {
processor.get_time() as 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)] #[derive(Debug)]
enum Syscall { enum Syscall {
@ -199,3 +207,4 @@ const UCORE_SYS_FSYNC: usize = 111;
const UCORE_SYS_GETCWD: usize = 121; const UCORE_SYS_GETCWD: usize = 121;
const UCORE_SYS_GETDIRENTRY: usize = 128; const UCORE_SYS_GETDIRENTRY: usize = 128;
const UCORE_SYS_DUP: usize = 130; const UCORE_SYS_DUP: usize = 130;
const UCORE_SYS_LAB6_SET_PRIORITY: usize = 255;

@ -11,7 +11,7 @@
- [ ] ls - [ ] ls
- [x] matrix - [x] matrix
- [ ] pgdir - [ ] pgdir
- [ ] priority - [x] priority
- [ ] sh - [ ] sh
- [x] sleep - [x] sleep
- [x] sleepkill - [x] sleepkill

Loading…
Cancel
Save