diff --git a/src/context/mod.rs b/src/context/mod.rs
index 40bac5190b..88d238773a 100644
--- a/src/context/mod.rs
+++ b/src/context/mod.rs
@@ -132,6 +132,7 @@ pub fn init(token: &mut CleanLockToken) {
percpu
.switch_internals
.set_current_context(Arc::clone(&context_lock));
+ percpu.switch_internals.set_idle_context(context_lock);
}
run_contexts(token.downgrade()).set[priority].push_back(context_ref);
diff --git a/src/context/switch.rs b/src/context/switch.rs
index 601991f6e5..904f506bf5 100644
--- a/src/context/switch.rs
+++ b/src/context/switch.rs
@@ -177,6 +177,7 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
let mut wakeups = Vec::new();
{
let current_context = context::current();
+ let idle_context = percpu.switch_internals.idle_context();
let mut contexts_guard = contexts(token.downgrade());
let (context, mut token) = contexts_guard.token_split();
@@ -184,6 +185,9 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
if Arc::ptr_eq(&context_ref, ¤t_context) {
continue;
}
+ if Arc::ptr_eq(&context_ref, &idle_context) {
+ continue;
+ }
let guard = context_ref.read(token.token());
if guard.status.is_soft_blocked() {
if let Some(wake) = guard.wake {
@@ -447,8 +451,14 @@ fn select_next_context(
return Ok(Some(next_context_guard));
} else {
- // We found no other process to run.
- Ok(None)
+ let idle_context = percpu.switch_internals.idle_context();
+ if !Arc::ptr_eq(&prev_context_lock, &idle_context) {
+ // We switch into the idle context
+ Ok(Some(unsafe { idle_context.write_arc() }))
+ } else {
+ // We found no other process to run.
+ Ok(None)
+ }
}
}
@@ -463,6 +473,8 @@ pub struct ContextSwitchPercpu {
current_ctxt: RefCell