use { alloc::{collections::VecDeque, rc::Rc, slice, vec::Vec}, hbvm::validate::validate, }; use {crate::host::TrapHandler, hbvm::Vm}; const TIMER_QUOTIENT: usize = 100; pub struct Scheduler<'a> { data: VecDeque>, } // 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) { 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::VmRunOk::End => { log::info!( "Program ended. {} programs remaining.", // Add one here because we pop a program self.data.len() + 1 ) } hbvm::VmRunOk::Timer => { log::info!("Timer exhausted. Scheduled program"); self.data.push_back(prog); } hbvm::VmRunOk::Ecall => { // panic!(); log::info!("{:?}", prog.registers); self.data.push_back(prog); } }, Err(_) => {} } } } }