mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-30 17:11:47 -05:00
sched: remove force_resched()
This function is used to force the scheduler to reschedule another task, avoiding the fast-path exit. Given the sheer number of task state change points in the code, the fast-path exit code has become too brittle. Instead, check that the current task's state is still `Running` before taking the fast-path short-circuit. The cost of one spinlock uncontended lock-unlock cycle is worth the cost of avoiding many subtle scheduling logic bugs.
This commit is contained in:
@@ -76,12 +76,6 @@ fn schedule() {
|
||||
SCHED_STATE.borrow_mut().do_schedule();
|
||||
}
|
||||
|
||||
/// Set the force resched task for this CPU. This ensures that the next time
|
||||
/// schedule() is called a full run of the schduling algorithm will occur.
|
||||
fn force_resched() {
|
||||
SCHED_STATE.borrow_mut().force_resched = true;
|
||||
}
|
||||
|
||||
pub fn spawn_kernel_work(fut: impl Future<Output = ()> + 'static + Send) {
|
||||
current_task().ctx.put_kernel_work(Box::pin(fut));
|
||||
}
|
||||
@@ -282,15 +276,12 @@ impl SchedState {
|
||||
needs_resched = true;
|
||||
}
|
||||
|
||||
if !needs_resched {
|
||||
// Fast Path: Only return if we have a valid task, it has budget,
|
||||
// AND it's not the idle task.
|
||||
//
|
||||
// Ensure that, in a debug build, we are only taking the fast-path
|
||||
// on a *running* task.
|
||||
if let Some(current) = self.run_q.current_mut() {
|
||||
debug_assert_eq!(*current.state.lock_save_irq(), TaskState::Running);
|
||||
}
|
||||
if !needs_resched
|
||||
&& let Some(current) = self.run_q.current()
|
||||
&& matches!(*current.state.lock_save_irq(), TaskState::Running)
|
||||
{
|
||||
// Fast Path: Only return if we have a valid task (Running state),
|
||||
// it has budget, AND it's not the idle task.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{current::current_task, force_resched, schedule, waker::create_waker};
|
||||
use super::{current::current_task, schedule, waker::create_waker};
|
||||
use crate::{
|
||||
arch::{Arch, ArchImpl},
|
||||
process::{
|
||||
@@ -128,7 +128,6 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
// task.
|
||||
// Task is currently running or is runnable and will now sleep.
|
||||
TaskState::Running | TaskState::Runnable => {
|
||||
force_resched();
|
||||
*task_state = TaskState::Sleeping;
|
||||
}
|
||||
// If we were woken between the future returning
|
||||
@@ -142,9 +141,7 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
// If the task finished concurrently while we were
|
||||
// polling its signal work, let the scheduler
|
||||
// pick another task; no further work to do here.
|
||||
TaskState::Finished => {
|
||||
force_resched();
|
||||
}
|
||||
TaskState::Finished => {}
|
||||
// We should never get here for any other state.
|
||||
s => {
|
||||
unreachable!(
|
||||
@@ -178,9 +175,6 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
// find another task to execute, removing this task
|
||||
// from the runqueue, reaping it's resouces.
|
||||
if task.state.lock_save_irq().is_finished() {
|
||||
// Ensure we don't take the fast-path sched exit
|
||||
// for a finished task.
|
||||
force_resched();
|
||||
state = State::PickNewTask;
|
||||
continue;
|
||||
}
|
||||
@@ -207,7 +201,6 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
match *task_state {
|
||||
// Task is runnable or running, put it to sleep.
|
||||
TaskState::Running | TaskState::Runnable => {
|
||||
force_resched();
|
||||
*task_state = TaskState::Sleeping
|
||||
}
|
||||
// If we were woken between the future returning
|
||||
@@ -221,9 +214,7 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
// Task finished concurrently while we were trying
|
||||
// to put it to sleep; just reschedule and let
|
||||
// teardown handle it.
|
||||
TaskState::Finished => {
|
||||
force_resched();
|
||||
}
|
||||
TaskState::Finished => {}
|
||||
// We should never get here for any other state.
|
||||
s => {
|
||||
unreachable!(
|
||||
@@ -255,8 +246,6 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
ptrace.set_waker(create_waker(task.descriptor()));
|
||||
|
||||
*task.state.lock_save_irq() = TaskState::Stopped;
|
||||
force_resched();
|
||||
|
||||
state = State::PickNewTask;
|
||||
continue 'dispatch;
|
||||
}
|
||||
@@ -299,7 +288,6 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
force_resched();
|
||||
state = State::PickNewTask;
|
||||
continue 'dispatch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user