Files
k-os/crates/kernel/src/interrupt.rs

64 lines
2.1 KiB
Rust

use domain::scheduler::{Scheduler, SchedulerDecision};
use platform::Platform;
use types::id::{CoreId, IrqId, ThreadId};
use crate::Kernel;
impl<P: Platform> Kernel<P> {
pub fn handle_tick(&mut self, core: CoreId) -> SchedulerDecision {
let current_tid = match self.scheduler.current(core) {
Some(tid) => tid,
None => return SchedulerDecision::Continue,
};
let thread = match self.threads.get_mut(current_tid) {
Ok(t) => t,
Err(_) => return SchedulerDecision::Continue,
};
let expired = thread.time_slice_mut().tick();
if expired {
thread.time_slice_mut().reset();
let priority = thread.priority();
if thread.preempt().is_err() {
return SchedulerDecision::Continue;
}
self.scheduler.add(current_tid, priority, core);
match self.scheduler.next(core) {
Some(next) => {
if self.threads.get_mut(next).and_then(|t| t.set_running(core)).is_ok() {
SchedulerDecision::Preempt(next)
} else {
let _ = self.threads.get_mut(current_tid).map(|t| t.set_running(core));
SchedulerDecision::Continue
}
}
None => {
let _ = self.threads.get_mut(current_tid).map(|t| t.set_running(core));
SchedulerDecision::Continue
}
}
} else {
self.scheduler.tick(core, current_tid)
}
}
pub fn handle_interrupt(&mut self, irq: IrqId) -> Option<ThreadId> {
self.platform.mask_irq(irq);
let tid = self.irqs.owner(irq)?;
let thread = self.threads.get_mut(tid).ok()?;
if !matches!(thread.state(), domain::thread::ThreadState::Blocked(_)) {
return None;
}
let priority = thread.priority();
let core = self.platform.core_id();
let _ = thread.unblock();
self.scheduler.add(tid, priority, core);
Some(tid)
}
}