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:
2026-07-02 16:53:19 +03:00
parent 5098d1651f
commit e812356cf0
4 changed files with 25 additions and 5 deletions
+3
View File
@@ -1,3 +1,6 @@
target
/config.toml
.gitlab-ci-local/
kernel
kernel.all
kernel.sym
+2 -2
View File
@@ -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
View File
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-10-03"
channel = "nightly-2026-04-11"
components = ["rust-src"]
+19 -2
View File
@@ -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)
}
}