#![allow(dead_code)]
use alloc::collections::VecDeque;
use crate::{prelude::*, sync::SpinLock, task::Task};
static DEFAULT_SCHEDULER: FifoScheduler = FifoScheduler::new();
pub(crate) static GLOBAL_SCHEDULER: SpinLock<GlobalScheduler> = SpinLock::new(GlobalScheduler {
scheduler: &DEFAULT_SCHEDULER,
});
pub trait Scheduler: Sync + Send {
fn enqueue(&self, task: Arc<Task>);
fn dequeue(&self) -> Option<Arc<Task>>;
fn should_preempt(&self, task: &Arc<Task>) -> bool;
}
pub struct GlobalScheduler {
scheduler: &'static dyn Scheduler,
}
impl GlobalScheduler {
pub const fn new(scheduler: &'static dyn Scheduler) -> Self {
Self { scheduler }
}
pub fn dequeue(&mut self) -> Option<Arc<Task>> {
self.scheduler.dequeue()
}
pub fn enqueue(&mut self, task: Arc<Task>) {
self.scheduler.enqueue(task)
}
pub fn should_preempt(&self, task: &Arc<Task>) -> bool {
self.scheduler.should_preempt(task)
}
}
pub fn set_scheduler(scheduler: &'static dyn Scheduler) {
let mut global_scheduler = GLOBAL_SCHEDULER.lock_irq_disabled();
assert!(global_scheduler.dequeue().is_none());
global_scheduler.scheduler = scheduler;
}
pub fn fetch_task() -> Option<Arc<Task>> {
GLOBAL_SCHEDULER.lock_irq_disabled().dequeue()
}
pub fn add_task(task: Arc<Task>) {
GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(task);
}
pub struct FifoScheduler {
task_queue: SpinLock<VecDeque<Arc<Task>>>,
}
impl FifoScheduler {
pub const fn new() -> Self {
FifoScheduler {
task_queue: SpinLock::new(VecDeque::new()),
}
}
}
impl Default for FifoScheduler {
fn default() -> Self {
Self::new()
}
}
impl Scheduler for FifoScheduler {
fn enqueue(&self, task: Arc<Task>) {
self.task_queue.lock_irq_disabled().push_back(task);
}
fn dequeue(&self) -> Option<Arc<Task>> {
self.task_queue.lock_irq_disabled().pop_front()
}
fn should_preempt(&self, _task: &Arc<Task>) -> bool {
false
}
}