Implement O(1) scheduler and add comments for other schedulers

toolchain_update
Jiajie Chen 6 years ago
parent 394afa493e
commit 3a6803af9b

@ -6,4 +6,4 @@ members = [
"crate/sync",
"crate/thread",
]
exclude = ["kernel"]
exclude = ["kernel", "user/rust"]

@ -3,10 +3,12 @@ use alloc::{collections::BinaryHeap, vec::Vec};
use log::*;
use spin::Mutex;
pub use self::o1::O1Scheduler;
pub use self::rr::RRScheduler;
pub use self::stride::StrideScheduler;
pub use self::work_stealing::WorkStealingScheduler;
mod o1;
mod rr;
mod stride;
mod work_stealing;

@ -0,0 +1,65 @@
//! O(1) scheduler introduced in Linux 2.6
//!
//! Two queues are maintained, one is active, another is inactive.
//! Take the first task from the active queue to run. When it is empty, swap active and inactive queues.
use super::*;
pub struct O1Scheduler {
inner: Mutex<O1SchedulerInner>,
}
struct O1SchedulerInner {
active_queue: usize,
queues: [Vec<Tid>; 2],
}
impl Scheduler for O1Scheduler {
fn push(&self, tid: usize) {
self.inner.lock().push(tid);
}
fn pop(&self, _cpu_id: usize) -> Option<usize> {
self.inner.lock().pop()
}
fn tick(&self, current_tid: usize) -> bool {
self.inner.lock().tick(current_tid)
}
fn set_priority(&self, _tid: usize, _priority: u8) {}
}
impl O1Scheduler {
pub fn new() -> Self {
let inner = O1SchedulerInner {
active_queue: 0,
queues: [Vec::new(), Vec::new()],
};
O1Scheduler {
inner: Mutex::new(inner),
}
}
}
impl O1SchedulerInner {
fn push(&mut self, tid: Tid) {
let inactive_queue = 1 - self.active_queue;
self.queues[inactive_queue].push(tid);
trace!("o1 push {}", tid - 1);
}
fn pop(&mut self) -> Option<Tid> {
let ret = match self.queues[self.active_queue].pop() {
Some(tid) => return Some(tid),
None => {
// active queue is empty, swap 'em
self.active_queue = 1 - self.active_queue;
self.queues[self.active_queue].pop()
}
};
trace!("o1 pop {:?}", ret);
ret
}
fn tick(&mut self, _current: Tid) -> bool {
true
}
}

@ -1,3 +1,9 @@
//! Stride scheduler
//!
//! Each task is assigned a priority. Each task has a running stride.
//! The task with least stride is selected to run.
//! When a task is rescheduled, its stride is added to proportional to 1 / priority.
use super::*;
pub struct StrideScheduler {

@ -1,5 +1,10 @@
//! Work stealing scheduler
//!
//! Each CPU has its own queue, and each CPU takes new jobs from its own queue.
//! When its queue is empty, steal jobs from other CPU's queue.
use super::*;
use deque::{self, Stealer, Worker, Stolen};
use deque::{self, Stealer, Stolen, Worker};
pub struct WorkStealingScheduler {
/// The ready queue of each processors
@ -53,7 +58,12 @@ impl Scheduler for WorkStealingScheduler {
Stolen::Abort => {} // retry
Stolen::Empty => break,
Stolen::Data(tid) => {
trace!("work-stealing: cpu{} steal thread {} from cpu{}", cpu_id, tid, other_id);
trace!(
"work-stealing: cpu{} steal thread {} from cpu{}",
cpu_id,
tid,
other_id
);
return Some(tid);
}
}

Loading…
Cancel
Save