don't loop from idle to kernel context

This commit is contained in:
Wildan M
2026-04-23 16:40:12 +07:00
parent 8262fa7da9
commit f773d3e50d
+24 -11
View File
@@ -208,11 +208,23 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
let cpu_id = crate::cpu_id();
let mut switch_context_opt =
match select_next_context(token, percpu, cpu_id, switch_time, &mut prev_context_guard) {
Ok(opt) => opt,
Err(early_ret) => return early_ret,
};
// Update per-cpu times
let percpu_nanos = switch_time.saturating_sub(percpu.switch_internals.switch_time.get()) as u64;
let percpu_ms = percpu_nanos / 1_000_000;
let was_idle = percpu.stats.add_time(percpu_ms) == CpuState::Idle as u8;
percpu.switch_internals.switch_time.set(switch_time);
let mut switch_context_opt = match select_next_context(
token,
percpu,
cpu_id,
switch_time,
was_idle,
&mut prev_context_guard,
) {
Ok(opt) => opt,
Err(early_ret) => return early_ret,
};
if switch_context_opt.is_none() {
let mut this_contexts = contexts_mut(token.token());
@@ -233,12 +245,6 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
}
}
// Update per-cpu times
let percpu_nanos = switch_time.saturating_sub(percpu.switch_internals.switch_time.get()) as u64;
let percpu_ms = percpu_nanos / 1_000_000;
let was_idle = percpu.stats.add_time(percpu_ms) == CpuState::Idle as u8;
percpu.switch_internals.switch_time.set(switch_time);
// Switch process states, TSS stack pointer, and store new context ID
match switch_context_opt {
Some(mut next_context_guard) => {
@@ -343,6 +349,7 @@ fn select_next_context(
percpu: &PercpuBlock,
cpu_id: LogicalCpuId,
switch_time: u128,
was_idle: bool,
prev_context_guard: &mut ArcRwLockWriteGuard<L4, Context>,
) -> Result<Option<ArcContextLockWriteGuard>, SwitchResult> {
let mut contexts_data = run_contexts(token.token());
@@ -424,6 +431,12 @@ fn select_next_context(
continue; // Lazy removal of blocked contexts
}
// Do not spawn the kernel (the idle context) again after idling,
// otherwise the next switch will idling again
if was_idle && !next_context_guard.userspace {
continue;
}
// Is this context runnable on this CPU?
if let UpdateResult::CanSwitch =
unsafe { update_runnable(&mut next_context_guard, cpu_id, switch_time) }