Skip to content

Commit

Permalink
Port rq
Browse files Browse the repository at this point in the history
Signed-off-by: Klimenty Tsoutsman <klim@tsoutsman.com>
  • Loading branch information
tsoutsman committed Sep 8, 2023
1 parent 618b5ce commit cbe91ac
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 70 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions applications/rq/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
name = "rq"
version = "0.1.0"
authors = ["Christine Wang <chrissywang54@gmail.com>"]
edition = "2021"

[dependencies]
getopts = "0.2.21"

[dependencies.app_io]
path = "../../kernel/app_io"

[dependencies.apic]
path = "../../kernel/apic"
[dependencies.cpu]
path = "../../kernel/cpu"

[dependencies.task]
path = "../../kernel/task"
Expand Down
119 changes: 56 additions & 63 deletions applications/rq/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,76 +1,69 @@
#![no_std]

// extern crate alloc;
// #[macro_use] extern crate app_io;
extern crate alloc;

// extern crate apic;
// extern crate getopts;
// extern crate task;
use alloc::{
fmt::Write,
string::{String, ToString},
vec::Vec,
};

// use getopts::Options;
// use alloc::{
// fmt::Write,
// string::{
// String,
// ToString,
// },
// vec::Vec,
// };
// use apic::get_lapics;
use app_io::{print, println};
use getopts::Options;

// pub fn main(args: Vec<String>) -> isize {
// let mut opts = Options::new();
// opts.optflag("h", "help", "print this help menu");
pub fn main(args: Vec<String>) -> isize {
let mut opts = Options::new();
opts.optflag("h", "help", "print this help menu");

// let matches = match opts.parse(args) {
// Ok(m) => { m }
// Err(_f) => { println!("{} \n", _f);
// return -1; }
// };
let matches = match opts.parse(args) {
Ok(m) => m,
Err(_f) => {
println!("{} \n", _f);
return -1;
}
};

// if matches.opt_present("h") {
// return print_usage(opts)
// }
if matches.opt_present("h") {
return print_usage(opts);
}
let bootstrap_cpu = cpu::bootstrap_cpu();

// let all_lapics = get_lapics();
// for lapic in all_lapics.iter() {
// let lapic = lapic.1;
// let apic_id = lapic.read().apic_id();
// let processor = lapic.read().processor_id();
// let is_bootstrap_cpu = lapic.read().is_bootstrap_cpu();
// let core_type = if is_bootstrap_cpu { "Boot CPU" } else { "Secondary CPU" };
for (cpu, task_list) in task::scheduler::dump() {
let core_type = if Some(cpu) == bootstrap_cpu {
"Boot CPU"
} else {
"Secondary CPU"
};

// println!("\n{} (apic: {}, proc: {})", core_type, apic_id, processor);

// if let Some(runqueue) = runqueue::get_runqueue(apic_id.value() as u8).map(|rq| rq.read().clone()) {
// let mut runqueue_contents = String::new();
// for task in runqueue.iter() {
// writeln!(runqueue_contents, " {} ({}) {}",
// task.name,
// task.id,
// if task.is_running() { "*" } else { "" }
// )
// .expect("Failed to write to runqueue_contents");
// }
// print!("{}", runqueue_contents);
// }

// else {
// println!("Can't retrieve runqueue for core {}", apic_id);
// return -1;
// }
// }

// println!("");
// 0
// }
println!("\n{} (CPU: {})", core_type, cpu);

// fn print_usage(opts: Options) -> isize {
// let mut brief = "Usage: rq \n \n".to_string();
let mut runqueue_contents = String::new();
for task in task_list.iter() {
writeln!(
runqueue_contents,
" {} ({}) {}",
task.name,
task.id,
if task.is_running() { "*" } else { "" }
)
.expect("Failed to write to runqueue_contents");
}
print!("{}", runqueue_contents);
}

// brief.push_str("Prints each CPU's ID, the tasks on its runqueue ('*' identifies the currently running task), and whether it is the boot CPU or not");
println!("");
0
}

// println!("{} \n", opts.usage(&brief));
fn print_usage(opts: Options) -> isize {
let mut brief = "Usage: rq \n \n".to_string();

// 0
// }
brief.push_str(
"Prints each CPU's ID, the tasks on its runqueue ('*' identifies the currently running \
task), and whether it is the boot CPU or not",
);

println!("{} \n", opts.usage(&brief));

0
}
11 changes: 10 additions & 1 deletion kernel/scheduler_epoch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

extern crate alloc;

use alloc::{boxed::Box, collections::VecDeque};
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
use core::ops::{Deref, DerefMut};

use task::TaskRef;
Expand All @@ -21,6 +21,7 @@ const MAX_PRIORITY: u8 = 40;
const DEFAULT_PRIORITY: u8 = 20;
const INITIAL_TOKENS: usize = 10;

#[derive(Clone)]
pub struct Scheduler {
idle_task: TaskRef,
queue: VecDeque<EpochTaskRef>,
Expand Down Expand Up @@ -161,6 +162,14 @@ impl task::scheduler::Scheduler for Scheduler {
fn drain(&mut self) -> Box<dyn Iterator<Item = TaskRef> + '_> {
Box::new(self.queue.drain(..).map(|epoch_task| epoch_task.task))
}

fn dump(&self) -> Vec<TaskRef> {
self.queue
.clone()
.into_iter()
.map(|epoch_task| epoch_task.task)
.collect()
}
}

impl task::scheduler::PriorityScheduler for Scheduler {
Expand Down
9 changes: 9 additions & 0 deletions kernel/scheduler_priority/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use time::Instant;

const DEFAULT_PRIORITY: u8 = 0;

#[derive(Clone)]
pub struct Scheduler {
idle_task: TaskRef,
queue: BinaryHeap<PriorityTaskRef>,
Expand Down Expand Up @@ -79,6 +80,14 @@ impl task::scheduler::Scheduler for Scheduler {
fn drain(&mut self) -> alloc::boxed::Box<dyn Iterator<Item = TaskRef> + '_> {
Box::new(self.queue.drain().map(|priority_task| priority_task.task))
}

fn dump(&self) -> Vec<TaskRef> {
self.queue
.clone()
.into_iter()
.map(|priority_task| priority_task.task)
.collect()
}
}

impl task::scheduler::PriorityScheduler for Scheduler {
Expand Down
6 changes: 5 additions & 1 deletion kernel/scheduler_round_robin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

extern crate alloc;

use alloc::{boxed::Box, collections::VecDeque};
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};

use task::TaskRef;

Expand Down Expand Up @@ -72,4 +72,8 @@ impl task::scheduler::Scheduler for Scheduler {
fn drain(&mut self) -> Box<dyn Iterator<Item = TaskRef> + '_> {
Box::new(self.queue.drain(..))
}

fn dump(&self) -> Vec<TaskRef> {
self.queue.clone().into()
}
}
20 changes: 18 additions & 2 deletions kernel/task/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,14 @@ where
pub fn add_task(task: TaskRef) {
let locked = SCHEDULERS.lock();

let max_busyness = usize::MAX;
let mut min_busyness = usize::MAX;
let mut least_busy_index = None;

for (i, (_, scheduler)) in locked.iter().enumerate() {
if scheduler.lock().busyness() < max_busyness {
let busyness = scheduler.lock().busyness();
if busyness < min_busyness {
least_busy_index = Some(i);
min_busyness = busyness;
}
}

Expand Down Expand Up @@ -179,6 +181,8 @@ pub trait Scheduler: Send + Sync + 'static {
fn as_priority_scheduler(&mut self) -> Option<&mut dyn PriorityScheduler>;

fn drain(&mut self) -> Box<dyn Iterator<Item = TaskRef> + '_>;

fn dump(&self) -> Vec<TaskRef>;
}

pub trait PriorityScheduler {
Expand Down Expand Up @@ -271,3 +275,15 @@ impl<'a> Drop for PriorityInheritanceGuard<'a> {
}
}
}

/// Returns a list of
///
/// This should only be used for debugging.
pub fn dump() -> Vec<(CpuId, Vec<TaskRef>)> {
let schedulers = SCHEDULERS.lock().clone();
schedulers
.into_iter()
.map(|(cpu, scheduler)| (cpu, scheduler.lock().dump()))
// We want to eagerly collect so that all the locking predictably happens in this function.
.collect()
}

0 comments on commit cbe91ac

Please sign in to comment.