From ab39b02bb9ac47bfe13dbd993f0922d121b62c00 Mon Sep 17 00:00:00 2001 From: Elfein Landers Date: Wed, 2 Feb 2022 01:52:42 -0800 Subject: [PATCH] Refactor of scheduler's --- ableos/src/arch/x86_64/init.rs | 30 +-- ableos/src/kmain.rs | 148 +++++++-------- ableos/src/scheduler/capabilities.rs | 185 +++++++++++------- ableos/src/scheduler/mod.rs | 274 +++++++++++++-------------- ableos/src/scheduler/tests.rs | 50 +++-- 5 files changed, 362 insertions(+), 325 deletions(-) diff --git a/ableos/src/arch/x86_64/init.rs b/ableos/src/arch/x86_64/init.rs index bc80f9b..20cc2f0 100644 --- a/ableos/src/arch/x86_64/init.rs +++ b/ableos/src/arch/x86_64/init.rs @@ -5,22 +5,22 @@ use super::{gdt, interrupts}; /// x86_64 initialization pub fn init() { - let result = logger::init(); - match result { - Ok(_) => {} - Err(err) => error!("{}", err), - } - gdt::init(); + let result = logger::init(); + match result { + Ok(_) => {} + Err(err) => error!("{}", err), + } + gdt::init(); - use crate::scheduler::Priority; - let mut scheduler = SCHEDULER.lock(); - use Priority::*; - let process_0 = scheduler.new_process(High); - scheduler.add_process(process_0); - drop(scheduler); + use crate::scheduler::Priority; + let mut scheduler = SCHEDULER.lock(); + use Priority::*; + let process_0 = scheduler.new_process(High); + scheduler.add_process(process_0); + drop(scheduler); - interrupts::init_idt(); + interrupts::init_idt(); - unsafe { interrupts::PICS.lock().initialize() }; - x86_64::instructions::interrupts::enable(); + unsafe { interrupts::PICS.lock().initialize() }; + x86_64::instructions::interrupts::enable(); } diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index c793262..3d0bf0b 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -3,110 +3,110 @@ // use crate::scheduler; use { - crate::{ - arch::{init, sloop}, - boot_conf, - boot_conf::BootConfig, - capabilities::FileAccess, - experiments::{ - info::master, - systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, - }, - file::{File, PathRep}, - relib::network::socket::SimpleSock, - relib::network::socket::Socket, - scheduler::SCHEDULER, - }, - alloc::{ - string::{String, ToString}, - vec, - }, - core::sync::atomic::{AtomicU64, Ordering::*}, - lazy_static::lazy_static, - log::*, + crate::{ + arch::{init, sloop}, + boot_conf, + boot_conf::BootConfig, + capabilities, + experiments::{ + info::master, + systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, + }, + file::{File, PathRep}, + relib::network::socket::SimpleSock, + relib::network::socket::Socket, + scheduler::SCHEDULER, + }, + alloc::{ + string::{String, ToString}, + vec, + }, + core::sync::atomic::{AtomicU64, Ordering::*}, + lazy_static::lazy_static, + log::*, }; lazy_static! { - pub static ref TICK: AtomicU64 = AtomicU64::new(0); - pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new(); + pub static ref TICK: AtomicU64 = AtomicU64::new(0); + pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new(); } /// The main entry point of the kernel #[no_mangle] pub fn kernel_main() -> ! { - init::init(); - log::set_max_level(BOOT_CONF.log_level()); + init::init(); + log::set_max_level(BOOT_CONF.log_level()); - use crate::scheduler::Priority; - let mut scheduler = SCHEDULER.lock(); + use crate::scheduler::Priority; + let mut scheduler = SCHEDULER.lock(); - use Priority::*; + use Priority::*; - let mut process_1 = scheduler.new_process(High); - process_1.capabilities.files = FileAccess::Some(vec![PathRep { - location: FileLocations::Home, - file_name: "test".to_string(), - }]); - scheduler.add_process(process_1); - for ref_process in &scheduler.list { - trace!("{:?}", ref_process); - } - drop(scheduler); + let mut process_1 = scheduler.new_process(High); + process_1.capabilities.set_file_access(vec![PathRep { + location: FileLocations::Home, + file_name: "test".to_string(), + }]); + scheduler.add_process(process_1); + for ref_process in &scheduler.list { + trace!("{:?}", ref_process); + } + drop(scheduler); - use crate::proto_filetable::contain::FILE_TABLE; - use crate::proto_filetable::file::FileLocations; + use crate::proto_filetable::contain::FILE_TABLE; + use crate::proto_filetable::file::FileLocations; - let mut file_table = FILE_TABLE.lock(); - let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string()); + let mut file_table = FILE_TABLE.lock(); + let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string()); - new_file.write_bytes(b"Hello, world!"); - file_table.add_file("test", new_file); + new_file.write_bytes(b"Hello, world!"); + file_table.add_file("test", new_file); - let file = file_table.get_file("test"); + let file = file_table.get_file("test"); - match file { - Some(file) => { - let file_bytes = &file.data_pointer; - let file_string = String::from_utf8(file_bytes.to_vec()).unwrap(); - info!("{}", file_string); - } - None => { - info!("File not found"); - } - } + match file { + Some(file) => { + let file_bytes = &file.data_pointer; + let file_string = String::from_utf8(file_bytes.to_vec()).unwrap(); + info!("{}", file_string); + } + None => { + info!("File not found"); + } + } - use crate::wasm::WasmProgram; - let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]); - trace!("Binary Valid: {:?}", ret.validate_header()); + use crate::wasm::WasmProgram; + let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]); + trace!("Binary Valid: {:?}", ret.validate_header()); - sloop() + sloop() } /// called by arch specific timers to tick up all kernel related functions pub fn tick() { - let mut data = TICK.load(Relaxed); - data += 1; + let mut data = TICK.load(Relaxed); + data += 1; - crate::kernel_state::KERNEL_STATE.lock().update_state(); + crate::kernel_state::KERNEL_STATE.lock().update_state(); - // let mut scheduler = SCHEDULER.lock(); - // scheduler.bump_exec(); + // let mut scheduler = SCHEDULER.lock(); + // scheduler.bump_exec(); - TICK.store(data, Relaxed) + TICK.store(data, Relaxed) } pub fn cpu_socket_startup() { - let mut cpu_info_socket = SimpleSock::new(); - cpu_info_socket.register_protocol("CPU_INFO".to_string()); + let mut cpu_info_socket = SimpleSock::new(); + cpu_info_socket.register_protocol("CPU_INFO".to_string()); - let x = master().unwrap(); - let _xyz = x.brand_string().unwrap(); + let x = master().unwrap(); + let _xyz = x.brand_string().unwrap(); } pub fn log_version_data() { - info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION); - info!( - "Brand String: {:?}", - master().unwrap().brand_string().unwrap() - ); + info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION); + info!( + "Brand String: {:?}", + master().unwrap().brand_string().unwrap() + ); } diff --git a/ableos/src/scheduler/capabilities.rs b/ableos/src/scheduler/capabilities.rs index 0ba1b87..73098c9 100644 --- a/ableos/src/scheduler/capabilities.rs +++ b/ableos/src/scheduler/capabilities.rs @@ -1,88 +1,129 @@ +use core::ops::BitOr; + use alloc::vec::Vec; use crate::file::PathRep; +// TODO: Get Able to document this +/// pub type SoundCardID = u8; +// TODO: Get Able to document this +/// pub type DeviceID = u8; +// TODO: Get Able to document this +/// pub type ControllerID = u8; +#[repr(u8)] #[derive(Clone, Debug, PartialEq)] -pub enum FileAccess { - All, - Some(Vec), - None, +/// Enum that specifies which abilities a program can have. +pub enum Ability { + // TODO: Get Able to document this + /// + AllControllers = 0x01, + // TODO: Get Able to document this + /// + AllFiles = 0x02, + // TODO: Get Able to document this + /// + AllSoundCards = 0x04, + // TODO: Get Able to document this + /// + Keyboard = 0x08, + // TODO: Get Able to document this + /// + Mouse = 0x10, + // TODO: Get Able to document this + /// + Telecomms = 0x20, } -#[derive(Clone, Debug, PartialEq)] -pub enum ControllerAccess { - All, - Some(Vec), - None, -} +#[derive(Clone, Debug, Default, PartialEq)] +/// Wrapper for bit mask of Ability. +pub struct Permissions(u8); -#[derive(Clone, Debug, PartialEq)] -pub enum SoundCardAccess { - All, - Some(Vec), - None, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum MouseAccess { - Yes, - No, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum KeyboardAccess { - Yes, - No, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum NetworkAccess { - Yes, - No, -} - -/// A set of capabilities that a process has -#[derive(Clone, Debug, PartialEq)] +/// The capabilities of a program. This must only be handled by kernel code. +/// Capabilities should never be set by user code, either directly or indirectly. +#[derive(Clone, Debug, Default, PartialEq)] pub struct Capabilities { - // TODO: Add more capabilities - pub files: FileAccess, - pub mouse: MouseAccess, - pub keyboard: KeyboardAccess, - pub controllers: ControllerAccess, - pub sound_cards: SoundCardAccess, - pub network_access: NetworkAccess, + perms: Permissions, + files: Vec, + controllers: Vec, + soundcards: Vec, } -impl Capabilities { - /// Generate a set of empty capabilities - pub fn empty() -> Self { - Self { - files: FileAccess::None, - mouse: MouseAccess::No, - keyboard: KeyboardAccess::No, - controllers: ControllerAccess::None, - sound_cards: SoundCardAccess::None, - network_access: NetworkAccess::No, - } - } - /// Generate a set of capabilities that allows all access - /// to all devices - /// - /// # Safety - /// This is a very dangerous function and should not be used - /// unless you know what you are doing - pub unsafe fn all() -> Self { - Self { - files: FileAccess::All, - mouse: MouseAccess::Yes, - keyboard: KeyboardAccess::Yes, - controllers: ControllerAccess::All, - sound_cards: SoundCardAccess::All, - network_access: NetworkAccess::Yes, - } - } +impl Capabilities { + /// Generate a set of empty capabilities + pub fn empty() -> Self { + Self::default() + } + + /// Generate a set of capabilities that allows all access + /// to all devices + /// + /// # Safety + /// This is a very dangerous function and should not be used + /// unless you know what you are doing + pub unsafe fn all() -> Self { + Self { + perms: Permissions::all(), + ..Default::default() + } + } + /// Checks if capabilities has this ability. + pub fn has_ability(&self, ability: Ability) -> bool { + self.perms.has_ability(ability) + } + /// Sets which individual files this capabilities grants access to. + pub fn set_file_access(&mut self, files: Vec) { + self.files = files; + } + /// Sets which individual controllers this capabilities grants access to. + pub fn set_controller_access(&mut self, controllers: Vec) { + self.controllers = controllers; + } + /// Sets which individual soundcards this capabilities grants access to. + pub fn set_soundcard_access(&mut self, soundcards: Vec) { + self.soundcards = soundcards; + } } + +impl Ability { + /// Returns a bit mask with all abilities enabled. + pub fn all() -> u8 { + use Ability::*; + AllControllers | AllFiles | AllSoundCards | Keyboard | Mouse | Telecomms + } +} + +impl BitOr for Ability { + type Output = u8; + fn bitor(self, rhs: Self) -> u8 { + self as u8 | rhs as u8 + } +} + +impl BitOr for Ability { + type Output = u8; + fn bitor(self, rhs: u8) -> u8 { + self as u8 | rhs + } +} + +impl BitOr for u8 { + type Output = u8; + fn bitor(self, rhs: Ability) -> u8 { + self | rhs as u8 + } +} + +impl Permissions { + /// Returns self with all abilities enabled. + pub fn all() -> Self { + Self(Ability::all()) + } + /// Checks if permissions has ability. + pub fn has_ability(&self, ability: Ability) -> bool { + self.0 & ability.clone() as u8 == ability as u8 + } +} \ No newline at end of file diff --git a/ableos/src/scheduler/mod.rs b/ableos/src/scheduler/mod.rs index 776f6b6..a9a2cc8 100644 --- a/ableos/src/scheduler/mod.rs +++ b/ableos/src/scheduler/mod.rs @@ -19,7 +19,7 @@ mod tests; use crate::file::PathRep; -use self::capabilities::Capabilities; +use capabilities::Capabilities; lazy_static::lazy_static!( /// The standard implementation for ableOS @@ -30,19 +30,19 @@ lazy_static::lazy_static!( /// 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, + /// 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), - None, + All, + Some(Vec), + None, } /// This structure handles the process scheduling and execution @@ -59,139 +59,139 @@ pub enum FileAccessTypes { /// ``` #[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, + /// 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, } 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(), - } - } + /// 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); - } + /// 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(), - capabilities: Capabilities::empty(), - priority, - }; - // 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); + /// 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(), + capabilities: Capabilities::empty(), + priority, + }; + // 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; + 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(); } - 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(); - } - - (_, _) => {} + (15, Medium) => { + self.next_process(); } - } - } + (10, Low) => { + self.next_process(); + } + + (_, _) => {} + } + } + } } diff --git a/ableos/src/scheduler/tests.rs b/ableos/src/scheduler/tests.rs index f76799e..b04c84f 100644 --- a/ableos/src/scheduler/tests.rs +++ b/ableos/src/scheduler/tests.rs @@ -1,49 +1,45 @@ use super::*; -use crate::scheduler::{ - capabilities::{ControllerAccess, FileAccess, KeyboardAccess, MouseAccess, SoundCardAccess}, - proc::PID, - Priority::*, - Scheduler, -}; +use crate::{scheduler::{proc::PID, Priority::*, Scheduler}, capabilities::Ability}; // #[test] fn test_new_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - assert_eq!(scheduler.list.len(), 1); + let mut scheduler = Scheduler::new(); + scheduler.new_process(High); + assert_eq!(scheduler.list.len(), 1); } // #[test] fn test_next_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.next_process(); - assert_eq!(scheduler.list.len(), 0); + let mut scheduler = Scheduler::new(); + scheduler.new_process(High); + scheduler.next_process(); + assert_eq!(scheduler.list.len(), 0); } // #[test] fn test_term_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.term_process(PID(1)); - assert_eq!(scheduler.list.len(), 0); + let mut scheduler = Scheduler::new(); + scheduler.new_process(High); + scheduler.term_process(PID(1)); + assert_eq!(scheduler.list.len(), 0); } // #[test] fn test_bump_exec() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.bump_exec(); - assert_eq!(scheduler.process_exec_time, 1); + let mut scheduler = Scheduler::new(); + scheduler.new_process(High); + scheduler.bump_exec(); + assert_eq!(scheduler.process_exec_time, 1); } // #[test] fn test_capabilities() { - let caps = Capabilities::empty(); - assert_eq!(caps.files, FileAccess::None); - assert_eq!(caps.mouse, MouseAccess::No); - assert_eq!(caps.keyboard, KeyboardAccess::No); - assert_eq!(caps.controllers, ControllerAccess::None); - assert_eq!(caps.sound_cards, SoundCardAccess::None); + let caps = Capabilities::empty(); + assert!(!caps.has_ability(Ability::AllControllers)); + assert!(!caps.has_ability(Ability::AllFiles)); + assert!(!caps.has_ability(Ability::AllSoundCards)); + assert!(!caps.has_ability(Ability::Keyboard)); + assert!(!caps.has_ability(Ability::Mouse)); + assert!(!caps.has_ability(Ability::Telecomms)); }