This commit is contained in:
parent
c091706031
commit
91c449c099
4 changed files with 88 additions and 23 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -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]]
|
||||
|
|
|
@ -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) -> ! {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue