fix: per-CPU idle context race condition + nightly-2026-04-11 pin
- Add try_idle_context() to ContextSwitchPercpu (switch.rs) Cross-CPU paths (steal_work, migrate_one_context) use try_idle_context() instead of idle_context() to avoid panic when APs haven't called context::init() yet. Returns Option<context::Arc> instead of panicking. - Pin rust-toolchain.toml to nightly-2026-04-11 - Remove build artifacts (kernel, kernel.all, kernel.sym) from git tracking - This fixes the boot panic that occurred during multi-CPU scheduling
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
target
|
||||
/config.toml
|
||||
.gitlab-ci-local/
|
||||
kernel
|
||||
kernel.all
|
||||
kernel.sym
|
||||
|
||||
@@ -31,8 +31,8 @@ TARGET_SPEC=$(RUST_TARGET_PATH)/$(ARCH)-unknown-kernel.json
|
||||
KERNEL_CARGO_FEATURES?=
|
||||
|
||||
$(BUILD)/kernel.all: $(LD_SCRIPT) $(LOCKFILE) $(MANIFEST) $(TARGET_SPEC) $(shell find $(SOURCE) -name "*.rs" -type f)
|
||||
cd $(SOURCE) && RUSTUP_TOOLCHAIN=nightly-2025-10-03 cargo rustc \
|
||||
-Z build-std=core,alloc -Zbuild-std-features=compiler-builtins-mem \
|
||||
cd $(SOURCE) && RUSTUP_TOOLCHAIN=nightly-2026-04-11 RUSTFLAGS="-Zunstable-options" cargo rustc \
|
||||
-Z json-target-spec -Z build-std=core,alloc -Zbuild-std-features=compiler-builtins-mem \
|
||||
--bin kernel \
|
||||
--manifest-path "$(MANIFEST)" \
|
||||
--target "$(TARGET_SPEC)" \
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2025-10-03"
|
||||
channel = "nightly-2026-04-11"
|
||||
components = ["rust-src"]
|
||||
|
||||
+19
-2
@@ -399,7 +399,9 @@ fn steal_work(
|
||||
continue;
|
||||
};
|
||||
|
||||
let victim_idle = victim.switch_internals.idle_context();
|
||||
let Some(victim_idle) = victim.switch_internals.try_idle_context() else {
|
||||
continue;
|
||||
};
|
||||
let mut victim_lock = SchedQueuesLock::new(&victim.sched);
|
||||
let victim_queues = unsafe { victim_lock.queues_mut() };
|
||||
|
||||
@@ -469,7 +471,9 @@ fn migrate_one_context(
|
||||
return false;
|
||||
};
|
||||
|
||||
let source_idle = source.switch_internals.idle_context();
|
||||
let Some(source_idle) = source.switch_internals.try_idle_context() else {
|
||||
return false;
|
||||
};
|
||||
let moved = {
|
||||
let mut source_lock = SchedQueuesLock::new(&source.sched);
|
||||
let source_queues = unsafe { source_lock.queues_mut() };
|
||||
@@ -1174,4 +1178,17 @@ impl ContextSwitchPercpu {
|
||||
.expect("no idle context present"),
|
||||
)
|
||||
}
|
||||
|
||||
/// Retrieves the current idle context if it has been initialized.
|
||||
///
|
||||
/// This is the fallible variant of [`idle_context`], intended for
|
||||
/// cross-CPU paths (`steal_work`, `migrate_one_context`) that may
|
||||
/// access a PercpuBlock whose `context::init()` has not run yet
|
||||
/// during AP bring-up.
|
||||
///
|
||||
/// # Returns
|
||||
/// `Some(Arc<ContextLock>)` if the idle context is set, `None` otherwise.
|
||||
pub fn try_idle_context(&self) -> Option<Arc<ContextLock>> {
|
||||
self.idle_ctxt.borrow().as_ref().map(Arc::clone)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user