mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: scheduler: rewrite
This commit is contained in:
parent
8897e6467c
commit
5d5c18592f
@ -2,6 +2,7 @@ use crate::plat::console::{set_console, ConsoleDevice, ConsoleDriver, CONSOLE};
|
|||||||
use crate::plat::lowlevel::{Hardware, LowLevel};
|
use crate::plat::lowlevel::{Hardware, LowLevel};
|
||||||
use crate::plat::timer::{Timer, TimerOps};
|
use crate::plat::timer::{Timer, TimerOps};
|
||||||
use crate::plat::trap::{Trap, TrapOps};
|
use crate::plat::trap::{Trap, TrapOps};
|
||||||
|
use crate::scheduler::SCHEDULER;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use fdt::Fdt;
|
use fdt::Fdt;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
@ -28,7 +29,8 @@ pub fn rust_main() -> ! {
|
|||||||
|
|
||||||
Trap::init();
|
Trap::init();
|
||||||
Timer::init();
|
Timer::init();
|
||||||
Hardware::enable_interrupt();
|
|
||||||
|
SCHEDULER.schedule();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let data = CONSOLE.lock().try_read();
|
let data = CONSOLE.lock().try_read();
|
||||||
|
59
kernel/src/scheduler.rs
Normal file
59
kernel/src/scheduler.rs
Normal file
@ -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<TcbObject> = Lazy::new(|| {
|
||||||
|
let mut idle_thread = TcbObject::new();
|
||||||
|
idle_thread.configure_idle_thread();
|
||||||
|
idle_thread
|
||||||
|
});
|
||||||
|
|
||||||
|
#[thread_local]
|
||||||
|
pub static SCHEDULER: Lazy<Scheduler> = 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<TcbObject>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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?");
|
||||||
|
}
|
||||||
|
}
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user