Compare commits

...

1 commit

Author SHA1 Message Date
Elfein Landers ab39b02bb9 Refactor of scheduler's 2022-02-02 01:52:42 -08:00
5 changed files with 362 additions and 325 deletions

View file

@ -5,22 +5,22 @@ use super::{gdt, interrupts};
/// x86_64 initialization /// x86_64 initialization
pub fn init() { pub fn init() {
let result = logger::init(); let result = logger::init();
match result { match result {
Ok(_) => {} Ok(_) => {}
Err(err) => error!("{}", err), Err(err) => error!("{}", err),
} }
gdt::init(); gdt::init();
use crate::scheduler::Priority; use crate::scheduler::Priority;
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
use Priority::*; use Priority::*;
let process_0 = scheduler.new_process(High); let process_0 = scheduler.new_process(High);
scheduler.add_process(process_0); scheduler.add_process(process_0);
drop(scheduler); drop(scheduler);
interrupts::init_idt(); interrupts::init_idt();
unsafe { interrupts::PICS.lock().initialize() }; unsafe { interrupts::PICS.lock().initialize() };
x86_64::instructions::interrupts::enable(); x86_64::instructions::interrupts::enable();
} }

View file

@ -3,110 +3,110 @@
// use crate::scheduler; // use crate::scheduler;
use { use {
crate::{ crate::{
arch::{init, sloop}, arch::{init, sloop},
boot_conf, boot_conf,
boot_conf::BootConfig, boot_conf::BootConfig,
capabilities::FileAccess, capabilities,
experiments::{ experiments::{
info::master, info::master,
systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, systeminfo::{KERNEL_VERSION, RELEASE_TYPE},
}, },
file::{File, PathRep}, file::{File, PathRep},
relib::network::socket::SimpleSock, relib::network::socket::SimpleSock,
relib::network::socket::Socket, relib::network::socket::Socket,
scheduler::SCHEDULER, scheduler::SCHEDULER,
}, },
alloc::{ alloc::{
string::{String, ToString}, string::{String, ToString},
vec, vec,
}, },
core::sync::atomic::{AtomicU64, Ordering::*}, core::sync::atomic::{AtomicU64, Ordering::*},
lazy_static::lazy_static, lazy_static::lazy_static,
log::*, log::*,
}; };
lazy_static! { lazy_static! {
pub static ref TICK: AtomicU64 = AtomicU64::new(0); pub static ref TICK: AtomicU64 = AtomicU64::new(0);
pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new(); pub static ref BOOT_CONF: BootConfig = boot_conf::BootConfig::new();
} }
/// The main entry point of the kernel /// The main entry point of the kernel
#[no_mangle] #[no_mangle]
pub fn kernel_main() -> ! { pub fn kernel_main() -> ! {
init::init(); init::init();
log::set_max_level(BOOT_CONF.log_level()); log::set_max_level(BOOT_CONF.log_level());
use crate::scheduler::Priority; use crate::scheduler::Priority;
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
use Priority::*; use Priority::*;
let mut process_1 = scheduler.new_process(High); let mut process_1 = scheduler.new_process(High);
process_1.capabilities.files = FileAccess::Some(vec![PathRep { process_1.capabilities.set_file_access(vec![PathRep {
location: FileLocations::Home, location: FileLocations::Home,
file_name: "test".to_string(), file_name: "test".to_string(),
}]); }]);
scheduler.add_process(process_1); scheduler.add_process(process_1);
for ref_process in &scheduler.list { for ref_process in &scheduler.list {
trace!("{:?}", ref_process); trace!("{:?}", ref_process);
} }
drop(scheduler); drop(scheduler);
use crate::proto_filetable::contain::FILE_TABLE; use crate::proto_filetable::contain::FILE_TABLE;
use crate::proto_filetable::file::FileLocations; use crate::proto_filetable::file::FileLocations;
let mut file_table = FILE_TABLE.lock(); let mut file_table = FILE_TABLE.lock();
let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string()); let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string());
new_file.write_bytes(b"Hello, world!"); new_file.write_bytes(b"Hello, world!");
file_table.add_file("test", new_file); file_table.add_file("test", new_file);
let file = file_table.get_file("test"); let file = file_table.get_file("test");
match file { match file {
Some(file) => { Some(file) => {
let file_bytes = &file.data_pointer; let file_bytes = &file.data_pointer;
let file_string = String::from_utf8(file_bytes.to_vec()).unwrap(); let file_string = String::from_utf8(file_bytes.to_vec()).unwrap();
info!("{}", file_string); info!("{}", file_string);
} }
None => { None => {
info!("File not found"); info!("File not found");
} }
} }
use crate::wasm::WasmProgram; use crate::wasm::WasmProgram;
let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]); let ret = WasmProgram::new_from_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]);
trace!("Binary Valid: {:?}", ret.validate_header()); trace!("Binary Valid: {:?}", ret.validate_header());
sloop() sloop()
} }
/// called by arch specific timers to tick up all kernel related functions /// called by arch specific timers to tick up all kernel related functions
pub fn tick() { pub fn tick() {
let mut data = TICK.load(Relaxed); let mut data = TICK.load(Relaxed);
data += 1; data += 1;
crate::kernel_state::KERNEL_STATE.lock().update_state(); crate::kernel_state::KERNEL_STATE.lock().update_state();
// let mut scheduler = SCHEDULER.lock(); // let mut scheduler = SCHEDULER.lock();
// scheduler.bump_exec(); // scheduler.bump_exec();
TICK.store(data, Relaxed) TICK.store(data, Relaxed)
} }
pub fn cpu_socket_startup() { pub fn cpu_socket_startup() {
let mut cpu_info_socket = SimpleSock::new(); let mut cpu_info_socket = SimpleSock::new();
cpu_info_socket.register_protocol("CPU_INFO".to_string()); cpu_info_socket.register_protocol("CPU_INFO".to_string());
let x = master().unwrap(); let x = master().unwrap();
let _xyz = x.brand_string().unwrap(); let _xyz = x.brand_string().unwrap();
} }
pub fn log_version_data() { pub fn log_version_data() {
info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION); info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION);
info!( info!(
"Brand String: {:?}", "Brand String: {:?}",
master().unwrap().brand_string().unwrap() master().unwrap().brand_string().unwrap()
); );
} }

View file

@ -1,88 +1,129 @@
use core::ops::BitOr;
use alloc::vec::Vec; use alloc::vec::Vec;
use crate::file::PathRep; use crate::file::PathRep;
// TODO: Get Able to document this
///
pub type SoundCardID = u8; pub type SoundCardID = u8;
// TODO: Get Able to document this
///
pub type DeviceID = u8; pub type DeviceID = u8;
// TODO: Get Able to document this
///
pub type ControllerID = u8; pub type ControllerID = u8;
#[repr(u8)]
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum FileAccess { /// Enum that specifies which abilities a program can have.
All, pub enum Ability {
Some(Vec<PathRep>), // TODO: Get Able to document this
None, ///
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)] #[derive(Clone, Debug, Default, PartialEq)]
pub enum ControllerAccess { /// Wrapper for bit mask of Ability.
All, pub struct Permissions(u8);
Some(Vec<ControllerID>),
None,
}
#[derive(Clone, Debug, PartialEq)] /// The capabilities of a program. This must only be handled by kernel code.
pub enum SoundCardAccess { /// Capabilities should never be set by user code, either directly or indirectly.
All, #[derive(Clone, Debug, Default, PartialEq)]
Some(Vec<SoundCardID>),
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)]
pub struct Capabilities { pub struct Capabilities {
// TODO: Add more capabilities perms: Permissions,
pub files: FileAccess, files: Vec<PathRep>,
pub mouse: MouseAccess, controllers: Vec<ControllerID>,
pub keyboard: KeyboardAccess, soundcards: Vec<SoundCardID>,
pub controllers: ControllerAccess,
pub sound_cards: SoundCardAccess,
pub network_access: NetworkAccess,
} }
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 impl Capabilities {
/// to all devices /// Generate a set of empty capabilities
/// pub fn empty() -> Self {
/// # Safety Self::default()
/// This is a very dangerous function and should not be used }
/// unless you know what you are doing
pub unsafe fn all() -> Self { /// Generate a set of capabilities that allows all access
Self { /// to all devices
files: FileAccess::All, ///
mouse: MouseAccess::Yes, /// # Safety
keyboard: KeyboardAccess::Yes, /// This is a very dangerous function and should not be used
controllers: ControllerAccess::All, /// unless you know what you are doing
sound_cards: SoundCardAccess::All, pub unsafe fn all() -> Self {
network_access: NetworkAccess::Yes, 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<PathRep>) {
self.files = files;
}
/// Sets which individual controllers this capabilities grants access to.
pub fn set_controller_access(&mut self, controllers: Vec<ControllerID>) {
self.controllers = controllers;
}
/// Sets which individual soundcards this capabilities grants access to.
pub fn set_soundcard_access(&mut self, soundcards: Vec<SoundCardID>) {
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<u8> for Ability {
type Output = u8;
fn bitor(self, rhs: u8) -> u8 {
self as u8 | rhs
}
}
impl BitOr<Ability> 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
}
}

View file

@ -19,7 +19,7 @@ mod tests;
use crate::file::PathRep; use crate::file::PathRep;
use self::capabilities::Capabilities; use capabilities::Capabilities;
lazy_static::lazy_static!( lazy_static::lazy_static!(
/// The standard implementation for ableOS /// The standard implementation for ableOS
@ -30,19 +30,19 @@ lazy_static::lazy_static!(
/// Scheduler priority model /// Scheduler priority model
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum Priority { pub enum Priority {
/// Exclusively Kernel space | 20 Timer Tick execution time /// Exclusively Kernel space | 20 Timer Tick execution time
High, High,
/// Kernel / User space | 15 Timer Tick execution time /// Kernel / User space | 15 Timer Tick execution time
Medium, Medium,
/// low priority userspace code | 10 Timer Tick execution time /// low priority userspace code | 10 Timer Tick execution time
Low, Low,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum FileAccessTypes { pub enum FileAccessTypes {
All, All,
Some(Vec<PathRep>), Some(Vec<PathRep>),
None, None,
} }
/// This structure handles the process scheduling and execution /// This structure handles the process scheduling and execution
@ -59,139 +59,139 @@ pub enum FileAccessTypes {
/// ``` /// ```
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Scheduler { pub struct Scheduler {
/// The highest free process ID /// The highest free process ID
pub free_pid: PID, pub free_pid: PID,
/// The execution time of the current process in ticks /// The execution time of the current process in ticks
pub process_exec_time: u64, pub process_exec_time: u64,
/// The list of processes /// The list of processes
pub list: Vec<Process>, pub list: Vec<Process>,
} }
impl Scheduler { impl Scheduler {
/// Create a new scheduler /// Create a new scheduler
/// ///
/// # Example /// # Example
/// ``` /// ```
/// use ableos::scheduler::Priority; /// use ableos::scheduler::Priority;
/// let mut scheduler = Scheduler::new(); /// let mut scheduler = Scheduler::new();
/// ``` /// ```
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
free_pid: PID(0), free_pid: PID(0),
process_exec_time: 0, process_exec_time: 0,
list: Vec::new(), list: Vec::new(),
} }
} }
/// Change the current process to the next process in the list /// Change the current process to the next process in the list
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let mut scheduler = scheduler(); /// let mut scheduler = scheduler();
/// let mut process = scheduler.next_process(); /// let mut process = scheduler.next_process();
/// ``` /// ```
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if there are no processes in the list /// Panics if there are no processes in the list
pub fn next_process(&mut self) { pub fn next_process(&mut self) {
self.process_exec_time = 0; self.process_exec_time = 0;
let previous_task = self.list[0].clone(); let previous_task = self.list[0].clone();
self.list.remove(0); self.list.remove(0);
self.list.push(previous_task); self.list.push(previous_task);
} }
/// Creates a new process /// Creates a new process
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `priority` - The priority of the process /// * `priority` - The priority of the process
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let mut scheduler = scheduler(); /// let mut scheduler = scheduler();
/// let mut process = scheduler.new_process(Priority::Medium); /// let mut process = scheduler.new_process(Priority::Medium);
/// ``` /// ```
pub fn new_process(&mut self, priority: Priority) -> Process { pub fn new_process(&mut self, priority: Priority) -> Process {
let process = Process { let process = Process {
id: self.free_pid.clone(), id: self.free_pid.clone(),
capabilities: Capabilities::empty(), capabilities: Capabilities::empty(),
priority, priority,
}; };
// self.free_pid.0 += 1; // self.free_pid.0 += 1;
// self.list.push(process); // self.list.push(process);
process process
} }
/// Add a created process to the scheduler /// Add a created process to the scheduler
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `process` - The process to add /// * `process` - The process to add
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let mut scheduler = Scheduler::new(); /// let mut scheduler = Scheduler::new();
/// let mut process = scheduler.new_process(Priority::Medium); /// let mut process = scheduler.new_process(Priority::Medium);
/// scheduler.add_process(process); /// scheduler.add_process(process);
/// ``` /// ```
pub fn add_process(&mut self, process: Process) { pub fn add_process(&mut self, process: Process) {
self.list.push(process); self.list.push(process);
self.free_pid.0 += 1; self.free_pid.0 += 1;
} }
/// Terminate the process with the matching PID /// Terminate the process with the matching PID
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `pid` - The PID of the process to terminate /// * `pid` - The PID of the process to terminate
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// let mut scheduler = scheduler(); /// let mut scheduler = scheduler();
/// let mut process = scheduler.new_process(Priority::Medium); /// let mut process = scheduler.new_process(Priority::Medium);
/// scheduler.terminate_process(process.id); /// scheduler.terminate_process(process.id);
/// ``` /// ```
pub fn term_process(&mut self, pid: PID) { pub fn term_process(&mut self, pid: PID) {
let mut process_index = 0; let mut process_index = 0;
for x in &self.list { for x in &self.list {
if x.id == pid { if x.id == pid {
self.list.remove(process_index); self.list.remove(process_index);
break; 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 (15, Medium) => {
} self.next_process();
}
/// 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();
}
(_, _) => {}
} }
} (10, Low) => {
} self.next_process();
}
(_, _) => {}
}
}
}
} }

View file

@ -1,49 +1,45 @@
use super::*; use super::*;
use crate::scheduler::{ use crate::{scheduler::{proc::PID, Priority::*, Scheduler}, capabilities::Ability};
capabilities::{ControllerAccess, FileAccess, KeyboardAccess, MouseAccess, SoundCardAccess},
proc::PID,
Priority::*,
Scheduler,
};
// #[test] // #[test]
fn test_new_process() { fn test_new_process() {
let mut scheduler = Scheduler::new(); let mut scheduler = Scheduler::new();
scheduler.new_process(High); scheduler.new_process(High);
assert_eq!(scheduler.list.len(), 1); assert_eq!(scheduler.list.len(), 1);
} }
// #[test] // #[test]
fn test_next_process() { fn test_next_process() {
let mut scheduler = Scheduler::new(); let mut scheduler = Scheduler::new();
scheduler.new_process(High); scheduler.new_process(High);
scheduler.next_process(); scheduler.next_process();
assert_eq!(scheduler.list.len(), 0); assert_eq!(scheduler.list.len(), 0);
} }
// #[test] // #[test]
fn test_term_process() { fn test_term_process() {
let mut scheduler = Scheduler::new(); let mut scheduler = Scheduler::new();
scheduler.new_process(High); scheduler.new_process(High);
scheduler.term_process(PID(1)); scheduler.term_process(PID(1));
assert_eq!(scheduler.list.len(), 0); assert_eq!(scheduler.list.len(), 0);
} }
// #[test] // #[test]
fn test_bump_exec() { fn test_bump_exec() {
let mut scheduler = Scheduler::new(); let mut scheduler = Scheduler::new();
scheduler.new_process(High); scheduler.new_process(High);
scheduler.bump_exec(); scheduler.bump_exec();
assert_eq!(scheduler.process_exec_time, 1); assert_eq!(scheduler.process_exec_time, 1);
} }
// #[test] // #[test]
fn test_capabilities() { fn test_capabilities() {
let caps = Capabilities::empty(); let caps = Capabilities::empty();
assert_eq!(caps.files, FileAccess::None); assert!(!caps.has_ability(Ability::AllControllers));
assert_eq!(caps.mouse, MouseAccess::No); assert!(!caps.has_ability(Ability::AllFiles));
assert_eq!(caps.keyboard, KeyboardAccess::No); assert!(!caps.has_ability(Ability::AllSoundCards));
assert_eq!(caps.controllers, ControllerAccess::None); assert!(!caps.has_ability(Ability::Keyboard));
assert_eq!(caps.sound_cards, SoundCardAccess::None); assert!(!caps.has_ability(Ability::Mouse));
assert!(!caps.has_ability(Ability::Telecomms));
} }