Don't race between enabling IRQs and halting CPU

This commit is contained in:
Ruihan Li
2025-04-09 10:23:58 +08:00
committed by Tate, Hongliang Tian
parent b96c8f9ed2
commit 35e0918bce
11 changed files with 105 additions and 42 deletions

View File

@ -4,3 +4,34 @@ pub(super) mod cpu_local;
mod guard;
pub use self::guard::{disable_preempt, DisabledPreemptGuard};
/// Halts the CPU until interrupts if no preemption is required.
///
/// This function will return if:
/// - preemption is required when calling this function,
/// - preemption is required during halting the CPU, or
/// - interrupts occur during halting the CPU.
///
/// This function will perform preemption before returning if
/// preemption is required.
///
/// # Panics
///
/// This function will panic if it is called in the atomic mode
/// ([`crate::task::atomic_mode`]).
#[track_caller]
pub fn halt_cpu() {
crate::task::atomic_mode::might_sleep();
let irq_guard = crate::trap::irq::disable_local();
if cpu_local::need_preempt() {
drop(irq_guard);
} else {
core::mem::forget(irq_guard);
// IRQs were previously enabled (checked by `might_sleep`). So we can re-enable them now.
crate::arch::irq::enable_local_and_halt();
}
super::scheduler::might_preempt();
}