forked from AbleOS/ableos
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
use {
|
|
alloc::{collections::VecDeque, rc::Rc, slice, vec::Vec},
|
|
hbvm::validate::validate,
|
|
};
|
|
|
|
use {crate::host::TrapHandler, hbvm::vm::Vm};
|
|
const TIMER_QUOTIENT: usize = 100;
|
|
|
|
pub struct Scheduler<'a> {
|
|
data: VecDeque<Vm<'a, TrapHandler, TIMER_QUOTIENT>>,
|
|
}
|
|
|
|
// NOTE: This is a very simple schduler and it sucks and should be replaced with a better one
|
|
// Written By Yours Truly: Munir
|
|
|
|
impl Scheduler<'_> {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
data: VecDeque::new(),
|
|
}
|
|
}
|
|
pub fn new_process(&mut self, program: Vec<u8>) {
|
|
let prog = program.clone();
|
|
let prog_arc = Rc::new(prog);
|
|
|
|
let binding = Rc::try_unwrap(prog_arc).ok().unwrap();
|
|
|
|
#[allow(clippy::redundant_else)]
|
|
if let Err(e) = validate(&program.as_slice()) {
|
|
log::error!("Program validation error: {e:?}");
|
|
} else {
|
|
log::info!("valid program");
|
|
unsafe {
|
|
let slice = slice::from_raw_parts(binding.as_ptr(), binding.len());
|
|
let mut vm = Vm::new_unchecked(&*slice, TrapHandler);
|
|
vm.memory.insert_test_page();
|
|
self.data.push_front(vm);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn run(&mut self) -> ! {
|
|
loop {
|
|
// If there are no programs to run then sleep.
|
|
if self.data.is_empty() {
|
|
use crate::arch::spin_loop;
|
|
spin_loop();
|
|
}
|
|
|
|
let mut prog = self.data.pop_front().unwrap();
|
|
let ret = prog.run();
|
|
match ret {
|
|
Ok(oki) => match oki {
|
|
hbvm::vm::VmRunOk::End => {
|
|
log::info!(
|
|
"Program ended. {} programs remaining.",
|
|
// Add one here because we pop a program
|
|
self.data.len() + 1
|
|
)
|
|
}
|
|
hbvm::vm::VmRunOk::Timer => {
|
|
log::info!("Timer exhausted. Scheduled program");
|
|
self.data.push_back(prog);
|
|
}
|
|
hbvm::vm::VmRunOk::Ecall => {
|
|
// panic!();
|
|
log::info!("{:?}", prog.registers);
|
|
self.data.push_back(prog);
|
|
}
|
|
},
|
|
|
|
Err(_) => {}
|
|
}
|
|
}
|
|
}
|
|
}
|