forked from AbleOS/ableos
198 lines
4.9 KiB
Rust
198 lines
4.9 KiB
Rust
// #![warn(missing_docs)]
|
|
|
|
//! The standard ableOS scheduler named
|
|
//!
|
|
//! # Notes
|
|
//! The scheduler is also responsible for choosing the priority of a process.
|
|
//! The scheduler is responsible for choosing which process to execute next.
|
|
|
|
pub mod capabilities;
|
|
pub mod proc;
|
|
|
|
mod new_sched;
|
|
use proc::{Process, PID};
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
use crate::{file::PathRep, kmain::generate_process_pass};
|
|
|
|
use self::capabilities::Capabilities;
|
|
|
|
lazy_static::lazy_static!(
|
|
/// The standard implementation for ableOS
|
|
pub static ref SCHEDULER: spin::Mutex<Scheduler> = spin::Mutex::new(Scheduler::new());
|
|
|
|
);
|
|
|
|
/// Scheduler priority model
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum Priority {
|
|
/// Exclusively Kernel space | 20 Timer Tick execution time
|
|
High,
|
|
/// Kernel / User space | 15 Timer Tick execution time
|
|
Medium,
|
|
/// low priority userspace code | 10 Timer Tick execution time
|
|
Low,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum FileAccessTypes {
|
|
All,
|
|
Some(Vec<PathRep>),
|
|
None,
|
|
}
|
|
|
|
/// This structure handles the process scheduling and execution
|
|
///
|
|
/// # Example
|
|
/// ```
|
|
/// use crate::scheduler::Priority;
|
|
/// use crate::scheduler::Scheduler;
|
|
///
|
|
/// let mut scheduler = Scheduler::new();
|
|
///
|
|
/// let pid = scheduler.new_process(Priority::High);
|
|
/// scheduler.run_process(pid);
|
|
/// ```
|
|
#[derive(Clone, Debug)]
|
|
pub struct Scheduler {
|
|
/// The highest free process ID
|
|
pub free_pid: PID,
|
|
/// The execution time of the current process in ticks
|
|
pub process_exec_time: u64,
|
|
/// The list of processes
|
|
pub list: Vec<Process>,
|
|
}
|
|
|
|
impl Scheduler {
|
|
/// Create a new scheduler
|
|
///
|
|
/// # Example
|
|
/// ```
|
|
/// use ableos::scheduler::Priority;
|
|
/// let mut scheduler = Scheduler::new();
|
|
/// ```
|
|
pub fn new() -> Self {
|
|
Self {
|
|
free_pid: PID(0),
|
|
process_exec_time: 0,
|
|
list: Vec::new(),
|
|
}
|
|
}
|
|
|
|
/// Change the current process to the next process in the list
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let mut scheduler = scheduler();
|
|
/// let mut process = scheduler.next_process();
|
|
/// ```
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if there are no processes in the list
|
|
pub fn next_process(&mut self) {
|
|
self.process_exec_time = 0;
|
|
let previous_task = self.list[0].clone();
|
|
self.list.remove(0);
|
|
self.list.push(previous_task);
|
|
}
|
|
|
|
/// Creates a new process
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `priority` - The priority of the process
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let mut scheduler = scheduler();
|
|
/// let mut process = scheduler.new_process(Priority::Medium);
|
|
/// ```
|
|
pub fn new_process(&mut self, priority: Priority) -> Process {
|
|
let process = Process {
|
|
id: self.free_pid.clone(),
|
|
password: generate_process_pass(),
|
|
capabilities: Capabilities::empty(),
|
|
priority,
|
|
working_dir: "todo!()".to_string(),
|
|
};
|
|
// self.free_pid.0 += 1;
|
|
// self.list.push(process);
|
|
process
|
|
}
|
|
/// Add a created process to the scheduler
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `process` - The process to add
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let mut scheduler = Scheduler::new();
|
|
/// let mut process = scheduler.new_process(Priority::Medium);
|
|
/// scheduler.add_process(process);
|
|
/// ```
|
|
pub fn add_process(&mut self, process: Process) {
|
|
self.list.push(process);
|
|
|
|
self.free_pid.0 += 1;
|
|
}
|
|
/// Terminate the process with the matching PID
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `pid` - The PID of the process to terminate
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let mut scheduler = scheduler();
|
|
/// let mut process = scheduler.new_process(Priority::Medium);
|
|
/// scheduler.terminate_process(process.id);
|
|
/// ```
|
|
pub fn term_process(&mut self, pid: PID) {
|
|
let mut process_index = 0;
|
|
for x in &self.list {
|
|
if x.id == pid {
|
|
self.list.remove(process_index);
|
|
break;
|
|
}
|
|
process_index += 1
|
|
}
|
|
}
|
|
/// Bump the current process' execution time
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let mut scheduler = scheduler();
|
|
/// let mut process = scheduler.new_process(Priority::Medium);
|
|
/// scheduler.bump_exec();
|
|
/// ```
|
|
pub fn bump_exec(&mut self) {
|
|
self.process_exec_time += 1;
|
|
|
|
use Priority::*;
|
|
if self.list.len() > 0 {
|
|
match (self.process_exec_time, self.list[0].priority) {
|
|
(20, High) => {
|
|
self.next_process();
|
|
}
|
|
(15, Medium) => {
|
|
self.next_process();
|
|
}
|
|
(10, Low) => {
|
|
self.next_process();
|
|
}
|
|
|
|
(_, _) => {}
|
|
}
|
|
}
|
|
}
|
|
}
|