Feature| afetch update, scheduler rework

This commit is contained in:
Able 2022-03-16 05:39:01 -05:00
parent c18035feb4
commit 8e66a677fa
22 changed files with 260 additions and 366 deletions

2
ableos/Cargo.lock generated
View file

@ -802,7 +802,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "versioning" name = "versioning"
version = "0.1.2" version = "0.1.2"
source = "git+https://git.ablecorp.us/able/versioning#ef472283e6e7a2e395ee56434087b3a6fad53ff2" source = "git+https://git.ablecorp.us/able/versioning#b86e53ab8461ee4f28807bf2254d543f6d8f4727"
[[package]] [[package]]
name = "vga" name = "vga"

View file

@ -41,6 +41,8 @@ test-args = [
"stdio", "stdio",
] ]
[dependencies] [dependencies]
linked_list_allocator = "0.9.0" linked_list_allocator = "0.9.0"
lliw = "0.2.0" lliw = "0.2.0"

View file

@ -70,3 +70,7 @@ pub fn shutdown() {}
use crate::print; use crate::print;
use crate::println; use crate::println;
pub fn generate_process_pass() -> u128 {
123
}

View file

@ -1,5 +1,9 @@
// #![allow(clippy::print_literal)] // #![allow(clippy::print_literal)]
use crate::{logger, scheduler::SCHEDULER, serial_println}; use crate::{
logger,
scheduler::{capabilities::Capabilities, SCHEDULER},
serial_println,
};
use super::{gdt, interrupts}; use super::{gdt, interrupts};
@ -20,10 +24,17 @@ pub fn init() {
} }
gdt::init(); gdt::init();
use crate::scheduler::Priority::High; use crate::scheduler::priority::Priority::High;
use crate::stdio::StdIO;
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
let process_0 = scheduler.new_process(High); let process_0 = scheduler.new_process(
Capabilities::empty(),
High,
"".to_string(),
StdIO::new(crate::stdio::Device::VTerm),
);
scheduler.add_process(process_0); scheduler.add_process(process_0);
drop(scheduler); drop(scheduler);
interrupts::init_idt(); interrupts::init_idt();

View file

@ -47,3 +47,13 @@ pub fn sloop() -> ! {
hlt(); hlt();
} }
} }
// TODO: Split up into the randomness and the password generation
pub fn generate_process_pass() -> u128 {
// TODO: Move this into entropy_pool module
use rdrand::RdRand;
let gen = RdRand::new().unwrap();
let ret = (gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128);
ret
}

View file

@ -1,4 +1,35 @@
pub trait Serial { use kernel::device_interface::character::CharacterDevice;
fn print();
fn recieve(); pub struct Serial {
pub base: usize,
}
impl CharacterDevice for Serial {
fn can_read(&self) -> bool {
true
}
fn can_write(&self) -> bool {
true
}
fn read_char(&mut self) -> Option<char> {
todo!()
}
fn write_char(&mut self, c: char) -> bool {
todo!()
}
fn reset(&mut self) {
todo!()
}
fn initialize(&mut self) -> bool {
false
}
}
pub fn new_serial_test() {
let mut serial = Serial { base: 0x3F8 };
serial.initialize();
serial.write_char('a');
} }

View file

@ -4,6 +4,7 @@ pub mod absi;
pub mod clip; pub mod clip;
pub mod futex; pub mod futex;
// pub mod info; // pub mod info;
pub mod info;
pub mod kinfo; pub mod kinfo;
pub mod mail; pub mod mail;
pub mod server; pub mod server;

View file

@ -30,13 +30,10 @@ pub fn kernel_main() -> ! {
log::set_max_level(log::LevelFilter::Off); log::set_max_level(log::LevelFilter::Off);
} }
let mut scheduler = SCHEDULER.lock(); let mut scheduler = SCHEDULER.lock();
use crate::scheduler::Priority::*; for proc in &scheduler.execution_queue {
let mut process_1 = scheduler.new_process(High); trace!("{:?}", proc);
process_1.capabilities.files = FileAccess::Some(vec![]);
scheduler.add_process(process_1);
for ref_process in &scheduler.list {
trace!("{:?}", ref_process);
} }
drop(scheduler); drop(scheduler);
// start_facepalm(); // start_facepalm();
@ -54,29 +51,18 @@ pub fn cpu_socket_startup() {
} }
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()
); );
} }
// TODO: Split up into the randomness and the password generation use crate::info::master;
pub fn generate_process_pass() -> u128 {
// TODO: Move this into entropy_pool module
// use rdrand::RdRand;
// let gen = RdRand::new().unwrap();
// TODO: Split off into process module
// let ret = (gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128);
// ret
123
}
use kernel::KERNEL_VERSION; use kernel::KERNEL_VERSION;
use crate::scheduler::SCHEDULER;
use crate::{ use crate::{
boot_conf::KernelConfig, boot_conf::KernelConfig, scheduler::capabilities::FileAccess, systeminfo::RELEASE_TYPE,
scheduler::{capabilities::FileAccess, SCHEDULER},
systeminfo::RELEASE_TYPE,
}; };

View file

@ -110,3 +110,5 @@ pub mod prelude;
#[prelude_import] #[prelude_import]
pub use prelude::rust_2021::*; pub use prelude::rust_2021::*;
pub mod stdio;

View file

@ -0,0 +1,11 @@
,-""""-. OS: AbleOS
,' _ `. Host: {}
/ )_) \ Kernel: AKern-{}-v{}
: : Uptime: {}
\ / Packages: None
\ / Shell: RhaiShell
`. ,' Resolution: 640x480
`. ,' Terminal: VGABuffer
`.,' CPU: {}
/\`. ,-._ GPU: VGA Compatible
`-' Memory: {}/{}

View file

@ -35,9 +35,12 @@ lazy_static::lazy_static!(
); );
use rhai::Engine; use rhai::Engine;
use x86_64::instructions::interrupts::{disable, enable};
use crate::info::master;
use crate::time::fetch_time; use crate::time::fetch_time;
use crate::wasm_jumploader::interp; use crate::wasm_jumploader::interp;
use crate::{allocator, ALLOCATOR};
use crate::{ use crate::{
arch::{shutdown, sloop}, arch::{shutdown, sloop},
systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, systeminfo::{KERNEL_VERSION, RELEASE_TYPE},
@ -49,14 +52,24 @@ pub fn afetch() {
let tick_time = fetch_time(); let tick_time = fetch_time();
println!( disable();
"OS: AbleOS let allocator = ALLOCATOR.lock();
Host: {} let size = allocator.size();
Kernel: AKern-{}-v{} let used = allocator.used();
Uptime: {}", enable();
kstate.hostname, RELEASE_TYPE, KERNEL_VERSION, tick_time
);
// let mem = format!("{}/{}", used, size);
println!(
include_str!("balloon.txt"),
kstate.hostname,
RELEASE_TYPE,
KERNEL_VERSION,
tick_time,
master().unwrap().brand_string().unwrap(),
// mem
used,
size
);
drop(kstate); drop(kstate);
} }
pub fn set_hostname(name: String) { pub fn set_hostname(name: String) {

View file

@ -1,197 +1,96 @@
// #![warn(missing_docs)] use crate::{arch::generate_process_pass, stdio::StdIO};
//! The standard ableOS scheduler named use crate::scheduler::capabilities::Capabilities;
//!
//! # Notes
//! The scheduler is also responsible for choosing the priority of a process.
//! The scheduler is responsible for choosing which process to execute next.
use kernel::proccess::PID;
pub mod capabilities; pub mod capabilities;
pub mod priority;
pub mod proc; pub mod proc;
use priority::Priority;
mod new_sched; use proc::Process;
use proc::{Process, PID}; /// Add additional wake conditions to the list
#[derive(Clone, Debug)]
#[cfg(test)] pub enum WakeCondition {
mod tests; /// Wake when the process has been blocked for a certain amount of time
TimerInterrupt(u64),
use crate::kmain::generate_process_pass; SocketRead(PID),
SocketWrite(PID),
use self::capabilities::Capabilities; SocketOpen(PID),
SocketClose(PID),
lazy_static::lazy_static!( // HardwareEvent,
/// 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,
} }
// NOTE: Define what is a sleeping process in the context of the ableOS kernel.
// Blocked processes are processes that are waiting for a certain event to occur.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum FileAccessTypes { pub struct BlockedProcess {
All, pub pid: PID,
Some(Vec<u8>), pub wake_condition: WakeCondition,
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 { pub struct Scheduler {
/// The highest free process ID
pub free_pid: PID, pub free_pid: PID,
/// The execution time of the current process in ticks
pub process_exec_time: u64, pub process_exec_time: u64,
/// The list of processes pub execution_queue: Vec<Process>,
pub list: Vec<Process>, pub sleeping_queue: Vec<BlockedProcess>,
pub blocked_queue: Vec<BlockedProcess>,
// / All timed processes sorted by wake time
} }
impl Scheduler { impl Scheduler {
/// Create a new scheduler /// Create a new scheduler
///
/// # Example
/// ```
/// use ableos::scheduler::Priority;
/// let mut scheduler = Scheduler::new();
/// ```
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
free_pid: PID(0), free_pid: 0,
process_exec_time: 0, process_exec_time: 0,
list: Vec::new(), execution_queue: Vec::new(),
sleeping_queue: Vec::new(),
blocked_queue: 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
///
/// ```
/// 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) { 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.execution_queue[0].clone();
self.list.remove(0); self.execution_queue.remove(0);
self.list.push(previous_task); self.execution_queue.push(previous_task);
} }
/// Creates a new process pub fn add_process(&mut self, mut process: Process) {
/// process.pid = self.free_pid;
/// # Arguments self.free_pid += 1;
/// self.execution_queue.push(process);
/// * `priority` - The priority of the process }
///
/// # Example pub fn new_process(
/// &mut self,
/// ``` capabilities: Capabilities,
/// let mut scheduler = scheduler(); priority: Priority,
/// let mut process = scheduler.new_process(Priority::Medium); working_dir: String,
/// ``` stdio: StdIO,
pub fn new_process(&mut self, priority: Priority) -> Process { ) -> Process {
let process = Process { let mut process = Process {
id: self.free_pid.clone(), pid: 0,
password: generate_process_pass(),
capabilities: Capabilities::empty(),
priority, priority,
working_dir: "todo!()".to_string(), working_dir,
stdio,
password: generate_process_pass(),
capabilities,
}; };
// self.free_pid.0 += 1;
// self.list.push(process);
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; pub fn sleep_process(&mut self, process: &mut Process) {
} let sleeping_process = BlockedProcess {
/// Terminate the process with the matching PID pid: process.pid,
/// wake_condition: WakeCondition::TimerInterrupt(0),
/// # 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::*; self.sleeping_queue.push(sleeping_process.clone());
if self.list.len() > 0 { self.execution_queue.remove(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();
}
(_, _) => {}
}
}
} }
} }
lazy_static::lazy_static! {
pub static ref SCHEDULER: spin::Mutex<Scheduler> = spin::Mutex::new(Scheduler::new());
}

View file

@ -1,86 +0,0 @@
use crate::{
kmain::generate_process_pass,
scheduler::capabilities::Capabilities,
scheduler::proc::{Process, PID},
scheduler::Priority,
};
/// Add additional wake conditions to the list
pub enum WakeCondition {
/// Wake when the process has been blocked for a certain amount of time
TimerInterrupt(u64),
SocketRead(PID),
SocketWrite(PID),
SocketOpen(PID),
SocketClose(PID),
// HardwareEvent,
}
// NOTE: Define what is a sleeping process in the context of the ableOS kernel.
// Blocked processes are processes that are waiting for a certain event to occur.
pub struct BlockedProcess {
pub pid: PID,
pub wake_time: u64,
}
pub struct Scheduler {
pub free_pid: PID,
pub process_exec_time: u64,
pub execution_queue: Vec<Process>,
pub sleeping_queue: Vec<Process>,
// pub blocked_queue: Vec<BlockedProcess>,
// / All timed processes sorted by wake time
// pub timed_blocked_queue: Vec<BlockedProcess>,
}
impl Scheduler {
/// Create a new scheduler
pub fn new() -> Self {
Self {
free_pid: PID(0),
process_exec_time: 0,
execution_queue: Vec::new(),
sleeping_queue: Vec::new(),
}
}
/// Change the current process to the next process in the list
pub fn next_process(&mut self) {
self.process_exec_time = 0;
let previous_task = self.execution_queue[0].clone();
self.execution_queue.remove(0);
self.execution_queue.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);
/// ```
///
/// TODO: Add a priority queue
/// TODO: Add a process queue
pub fn new_process(&mut self, priority: Priority) -> Process {
let process = Process {
id: self.free_pid,
password: generate_process_pass(),
priority,
capabilities: Capabilities::empty(),
working_dir: "todo!()".to_string(),
};
self.free_pid.0 += 1;
process
}
pub fn sleep_process(&mut self, process: &mut Process) {
let sleeping_process = BlockedProcess {
pid: process.id,
wake_time: 0,
};
self.sleeping_queue.push(process.clone());
self.execution_queue.remove(0);
}
}

View file

@ -0,0 +1,10 @@
/// 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,
}

View file

@ -1,17 +1,15 @@
//! Process definition and general utilities surrounding them //! Process definition and general utilities surrounding them
use super::{capabilities::Capabilities, Priority}; use super::capabilities::Capabilities;
use super::priority::Priority;
/// Process Identification use crate::stdio::StdIO;
#[derive(Clone, Copy, PartialEq, Debug)] use kernel::proccess::PID;
#[repr(C)]
pub struct PID(pub usize);
/// A process /// A process
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Process { pub struct Process {
/// Internal PID /// Internal PID
pub id: PID, pub pid: PID,
/// Process password /// Process password
pub password: u128, pub password: u128,
@ -20,8 +18,9 @@ pub struct Process {
/// A process's priority /// A process's priority
pub priority: Priority, pub priority: Priority,
/// /// A process's current working directory
pub working_dir: String, pub working_dir: String,
pub stdio: StdIO,
} }
impl Process {} impl Process {}

View file

@ -1,49 +0,0 @@
use super::*;
use crate::scheduler::{
capabilities::{ControllerAccess, FileAccess, KeyboardAccess, MouseAccess, SoundCardAccess},
proc::PID,
Priority::*,
Scheduler,
};
// #[test]
fn test_new_process() {
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);
}
// #[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);
}
// #[test]
fn test_bump_exec() {
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);
}

View file

@ -2,13 +2,17 @@ use acpi::AcpiTables;
use crate::rhai_shell::shell; use crate::rhai_shell::shell;
use crate::stdio::StdIO;
/// Experimental scratchpad for testing. /// Experimental scratchpad for testing.
pub fn scratchpad() { pub fn scratchpad() {
// pci_fun(); let mut stdio = StdIO::new(crate::stdio::Device::Serial);
stdio.write();
shell(); shell();
} }
use core::fmt::Write;
pub fn pci_fun() {} pub fn pci_fun() {}
pub fn acpi() { pub fn acpi() {

34
ableos/src/stdio.rs Normal file
View file

@ -0,0 +1,34 @@
use core::fmt::Arguments;
use core::fmt::Error;
use core::fmt::Write;
use crate::kprintln;
#[derive(Debug, Clone, Copy)]
pub enum Device {
VTerm,
Serial,
}
#[derive(Debug, Clone, Copy)]
pub struct StdIO {
device: Device,
}
impl StdIO {
pub fn new(device: Device) -> StdIO {
StdIO { device }
}
pub fn write(&mut self) {
match self.device {
Device::VTerm => {
println!("Hello, world!");
}
Device::Serial => {
serial_println!("Hello, world!");
}
}
}
pub fn read(&mut self) {
todo!();
}
}

22
kernel/Cargo.lock generated
View file

@ -1,22 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "kernel"
version = "0.1.2"
dependencies = [
"lazy_static",
"versioning",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "versioning"
version = "0.1.2"
source = "git+https://git.ablecorp.us/able/versioning#ef472283e6e7a2e395ee56434087b3a6fad53ff2"

View file

@ -8,6 +8,7 @@ pub mod device_interface;
pub mod messaging; pub mod messaging;
pub mod panic; pub mod panic;
pub mod proccess; pub mod proccess;
pub mod syscalls;
pub mod time; pub mod time;
use core::sync::atomic::{AtomicU64, Ordering::Relaxed}; use core::sync::atomic::{AtomicU64, Ordering::Relaxed};

View file

@ -2,3 +2,12 @@
/// A process ID /// A process ID
pub type PID = u64; pub type PID = u64;
#[repr(C)]
/// Signals that can be sent to a process
pub enum Signals {
/// Terminate the process
Terminate,
/// Shutdown the process and allow it to shutdown cleanly
Quit,
}

24
kernel/src/syscalls.rs Normal file
View file

@ -0,0 +1,24 @@
//!
use crate::proccess::{Signals, PID};
/// All possible system calls
pub enum Syscall {
/// Create a new process and return its PID
CreateProcess,
/// Send a signal to a process
SendSignal(PID, Signals),
/// Get the current process ID
GetPID,
/// Get the current time
GetTime,
/// Set the time
SetTime,
/*
ListInodes,
CreateInode,
RemoveInode,
OpenInode,
CloseInode,
*/
}