Add initial scheduler
All checks were successful
Build / build (push) Successful in 3m16s

This commit is contained in:
Mathieu Strypsteen 2024-11-07 21:17:52 +01:00
parent c091706031
commit 91c449c099
4 changed files with 88 additions and 23 deletions

14
Cargo.lock generated
View file

@ -47,7 +47,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.86",
"syn 2.0.87",
]
[[package]]
@ -171,9 +171,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.161"
version = "0.2.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
[[package]]
name = "libloading"
@ -241,7 +241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [
"proc-macro2",
"syn 2.0.86",
"syn 2.0.87",
]
[[package]]
@ -366,9 +366,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.86"
version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
@ -414,7 +414,7 @@ checksum = "9b24e77d3fc1e617051e630f99da24bcae6328abab37b8f9216bb68d06804f9a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.86",
"syn 2.0.87",
]
[[package]]

View file

@ -65,11 +65,8 @@ extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! {
setup_lapic_timer();
setup_multitasking();
}
fn main() -> ! {
fn main() {
info!("Starting main kernel task");
loop {
hlt();
}
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {

View file

@ -1,14 +1,42 @@
use core::arch::asm;
use crate::{cpu::isr::ISRState, sys::task::MAIN_TASK};
use alloc::collections::vec_deque::VecDeque;
use spin::Mutex;
use super::task::switch_task;
use crate::cpu::isr::ISRState;
use super::task::{switch_task, Task, TaskState, CURRENT_TASK};
static SCHEDULER_LIST: Mutex<VecDeque<Task>> = Mutex::new(VecDeque::new());
pub static IDLE_TASK: Mutex<Option<Task>> = Mutex::new(None);
pub fn scheduler(state: &mut ISRState) {
let mut main_task = MAIN_TASK.lock();
if let Some(task) = main_task.take() {
switch_task(state, task);
let mut switch_to_task = None;
{
let mut scheduler_list = SCHEDULER_LIST.lock();
if !scheduler_list.is_empty() {
let task = scheduler_list.pop_front().unwrap();
switch_to_task = Some(task);
}
}
if let Some(task) = switch_to_task {
switch_task(state, task);
return;
}
let mut switch_idle = false;
{
let _current_task = CURRENT_TASK.lock();
let current_task = _current_task.as_ref().unwrap();
if current_task.task_state != TaskState::READY && current_task.task_state != TaskState::IDLE {
switch_idle = true;
}
}
if switch_idle {
switch_task(state, IDLE_TASK.lock().take().unwrap());
}
}
pub fn schedule_task(task: Task) {
SCHEDULER_LIST.lock().push_back(task);
}
pub fn yield_task() {
unsafe {

View file

@ -1,15 +1,29 @@
use core::{arch::asm, sync::atomic::AtomicU64};
use alloc::boxed::Box;
use kernel_common::instructions::hlt;
use spin::Mutex;
use crate::{cpu::isr::ISRState, main};
use crate::{
cpu::isr::ISRState,
main,
sys::scheduler::{schedule_task, IDLE_TASK},
};
use super::scheduler::yield_task;
#[derive(PartialEq)]
pub enum TaskState {
READY,
IDLE,
TERMINATED,
}
pub struct Task {
state: ISRState,
initial_func: fn() -> !,
kernel_stack: u64,
initial_func: fn(),
pub task_state: TaskState,
}
const STACK_SIZE: usize = 64 * 1024;
@ -18,22 +32,31 @@ const STACK_SIZE: usize = 64 * 1024;
#[repr(C)]
struct Stack([u8; STACK_SIZE]);
static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
pub static MAIN_TASK: Mutex<Option<Task>> = Mutex::new(None);
pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
static RFLAGS: AtomicU64 = AtomicU64::new(0);
pub fn allocate_stack() -> u64 {
Box::leak(Box::new(Stack([0; STACK_SIZE]))) as *mut Stack as u64 + STACK_SIZE as u64
}
fn destroy_task(task: Task) {
unsafe {
drop(Box::from_raw((task.kernel_stack - STACK_SIZE as u64) as *mut Stack));
}
}
pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
let mut _current_task = CURRENT_TASK.lock();
if let Some(current_task) = _current_task.as_mut() {
current_task.state = *current_state;
match current_task.task_state {
TaskState::READY => schedule_task(_current_task.take().unwrap()),
TaskState::IDLE => *IDLE_TASK.lock() = _current_task.take(),
TaskState::TERMINATED => destroy_task(_current_task.take().unwrap()),
}
}
*current_state = new_task.state;
*_current_task = Some(new_task);
}
fn create_task(func: fn() -> !) -> Task {
pub fn create_task(func: fn()) -> Task {
let stack_address = allocate_stack();
let task = Task {
state: ISRState {
@ -60,7 +83,9 @@ fn create_task(func: fn() -> !) -> Task {
rsp: stack_address,
ss: 16,
},
kernel_stack: stack_address,
initial_func: func,
task_state: TaskState::READY,
};
task
}
@ -70,7 +95,17 @@ extern "C" fn task_entry() -> ! {
let task = CURRENT_TASK.lock();
func = task.as_ref().unwrap().initial_func;
}
func()
func();
{
CURRENT_TASK.lock().as_mut().unwrap().task_state = TaskState::TERMINATED;
}
yield_task();
panic!("Failed to terminate task");
}
fn idle() {
loop {
hlt();
}
}
pub fn setup_multitasking() -> ! {
let mut rflags;
@ -78,8 +113,13 @@ pub fn setup_multitasking() -> ! {
asm!("pushf; pop {0:r}", out(reg) rflags);
}
RFLAGS.store(rflags, core::sync::atomic::Ordering::Relaxed);
let mut idle_task = create_task(idle);
idle_task.task_state = TaskState::IDLE;
{
*IDLE_TASK.lock() = Some(idle_task);
}
let task = create_task(main);
*MAIN_TASK.lock() = Some(task);
schedule_task(task);
yield_task();
panic!("Setting up multitasking failed");
}