Skip to content

Commit

Permalink
kernel/scheduler/mlfq: fix lockup by immediately servicing kernel int…
Browse files Browse the repository at this point in the history
…errupts

Previously the MLFQ scheduler overwrote the `continue_process` method,
which can control whether the core kernel loop immediately continues
executing a process or is allowed to do other work first (such as
servicing interrupts and deferred calls). While this may be a fine
decision on some chips, it leads to a scheduler lockup with an
uncooperative process on LiteX (and likely other platforms).

This is because on some RISC-V platforms the scheduler timer is not a
dedicated system attached to its own interrupt source, but a virtual
scheduler timer based on an `Alarm` implementation that shares the
"machine external interrupt" CPU input. When a process' timeslice
expires, this alarm will raise an MEXT interrupt. To allow the kernel
to do actual work and not get stuck in the trap handler, we disable
MEXT interrupts by clearing the MIE::MEIE bit. Unfortunately, because
of the overriden `continue_process` method, we then never handle this
interrupt, which keeps the alarm interrupt asserted, and the MEXT CPU
interrupt source disabled. This can cause the kernel to never
interrupt and deschedule an uncooperative process.
  • Loading branch information
lschuermann committed Jan 5, 2025
1 parent 86cedf7 commit 875eb3f
Showing 1 changed file with 0 additions and 6 deletions.
6 changes: 0 additions & 6 deletions kernel/src/scheduler/mlfq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use crate::collections::list::{List, ListLink, ListNode};
use crate::hil::time::{self, ConvertTicks, Ticks};
use crate::platform::chip::Chip;
use crate::process::Process;
use crate::process::ProcessId;
use crate::process::StoppedExecutingReason;
use crate::scheduler::{Scheduler, SchedulingDecision};

Expand Down Expand Up @@ -183,9 +182,4 @@ impl<A: 'static + time::Alarm<'static>, C: Chip> Scheduler<C> for MLFQSched<'_,
self.processes[queue_idx].push_tail(self.processes[queue_idx].pop_head().unwrap());
}
}

unsafe fn continue_process(&self, _: ProcessId, _: &C) -> bool {
// This MLFQ scheduler only preempts processes if there is a timeslice expiration
true
}
}

0 comments on commit 875eb3f

Please sign in to comment.