Reimplement the DisableLocalIrqGuard

This commit is contained in:
Chuandong Li
2023-07-02 18:35:05 +08:00
committed by Tate, Hongliang Tian
parent 78de1af348
commit 7401eee455

View File

@ -197,60 +197,24 @@ pub fn disable_local() -> DisabledLocalIrqGuard {
/// A guard for disabled local IRQs. /// A guard for disabled local IRQs.
pub struct DisabledLocalIrqGuard { pub struct DisabledLocalIrqGuard {
// Having a private field prevents user from constructing values of this type directly. was_enabled: bool,
private: (),
} }
impl !Send for DisabledLocalIrqGuard {} impl !Send for DisabledLocalIrqGuard {}
cpu_local! {
static IRQ_OFF_COUNT: IrqInfo = IrqInfo::new();
}
impl DisabledLocalIrqGuard { impl DisabledLocalIrqGuard {
fn new() -> Self { fn new() -> Self {
IRQ_OFF_COUNT.inc(); let was_enabled = irq::is_local_enabled();
Self { private: () } if was_enabled {
irq::disable_local();
}
Self { was_enabled }
} }
} }
impl Drop for DisabledLocalIrqGuard { impl Drop for DisabledLocalIrqGuard {
fn drop(&mut self) { fn drop(&mut self) {
IRQ_OFF_COUNT.dec(); if self.was_enabled {
}
}
#[derive(Debug, Default)]
struct IrqInfo {
// interrupt disabling level
level: AtomicU32,
// interrupt state before calling dec()/inc()
is_irq_enabled: AtomicBool,
}
impl IrqInfo {
const fn new() -> Self {
Self {
level: AtomicU32::new(0),
is_irq_enabled: AtomicBool::new(false),
}
}
fn inc(&self) {
let enabled = irq::is_local_enabled();
let level = self.level.load(Relaxed);
if level == 0 {
self.is_irq_enabled.store(enabled, Relaxed);
}
if enabled {
irq::disable_local();
}
self.level.fetch_add(1, Relaxed);
}
fn dec(&self) {
let level = self.level.fetch_sub(1, Relaxed) - 1;
if level == 0 && self.is_irq_enabled.load(Relaxed) {
irq::enable_local(); irq::enable_local();
} }
} }