diff --git a/kernel/src/entry.rs b/kernel/src/entry.rs index 29291d4..f414475 100644 --- a/kernel/src/entry.rs +++ b/kernel/src/entry.rs @@ -2,6 +2,7 @@ use crate::plat::console::{set_console, ConsoleDevice, ConsoleDriver, CONSOLE}; use crate::plat::lowlevel::{Hardware, LowLevel}; use crate::plat::timer::{Timer, TimerOps}; use crate::plat::trap::{Trap, TrapOps}; +use crate::scheduler::SCHEDULER; use core::cell::Cell; use fdt::Fdt; use log::{debug, error, info, warn}; @@ -28,7 +29,8 @@ pub fn rust_main() -> ! { Trap::init(); Timer::init(); - Hardware::enable_interrupt(); + + SCHEDULER.schedule(); loop { let data = CONSOLE.lock().try_read(); diff --git a/kernel/src/scheduler.rs b/kernel/src/scheduler.rs new file mode 100644 index 0000000..52aa23e --- /dev/null +++ b/kernel/src/scheduler.rs @@ -0,0 +1,59 @@ +use crate::objects::tcb::TcbObject; +use core::ptr::NonNull; +use log::error; +use spin::lazy::Lazy; +use utils::linked_list::Link; + +#[thread_local] +static IDLE_THREAD: Lazy = Lazy::new(|| { + let mut idle_thread = TcbObject::new(); + idle_thread.configure_idle_thread(); + idle_thread +}); + +#[thread_local] +pub static SCHEDULER: Lazy = Lazy::new(|| Scheduler::new(&IDLE_THREAD)); + +// TODO: add a shared buffer to transfer TCB between cores + +// one process can run for 10 ticks +pub const TIME_SLICE: usize = 10; + +pub struct Scheduler { + head: Link, +} + +impl Scheduler { + pub fn new(idle_thread: &TcbObject) -> Self { + // link idle_thread + idle_thread.link.set_prev(Some(NonNull::from(idle_thread))); + idle_thread.link.set_next(Some(NonNull::from(idle_thread))); + + Self { + head: idle_thread.link.clone(), + } + } + + pub fn add(&self, tcb: &TcbObject) { + self.head.prepend(tcb); + } + + pub fn schedule(&self) { + while let Some(next) = self.head.next_mut() { + // TODO: also need to check whether it is schedulable + if next.timeslice() > 0 { + // Available to run, activate it + next.activate(); + } else if next.timeslice() == 0 { + // No time left, refill timeslice and move to the end of the queue + next.set_timeslice(TIME_SLICE); + } + + // put to the end of the queue + next.link.detach(); + self.head.prepend(next); + } + + error!("[Scheduler] No thread to schedule! Where is IDLE thread?"); + } +} diff --git a/kernel/src/scheduler/mod.rs b/kernel/src/scheduler/mod.rs deleted file mode 100644 index 60cdcf3..0000000 --- a/kernel/src/scheduler/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub static SCHEDULER: Scheduler = Scheduler::new(); - -pub struct Scheduler {} - -impl Scheduler { - pub const fn new() -> Self { - // TODO: implement Scheduler::new - Self {} - } - - #[inline(never)] - pub fn schedule(&self) { - todo!("Scheduler::schedule"); - } -}