pub type SpinLockIrq<T> = Lock<T, SpinLockIrqBackend>;Expand description
A variant of SpinLock that ensures interrupts are disabled in the critical section.
This lock can be acquired in two ways:
- Using
lock()like any other type of lock, in which case the bindings will modify the interrupt state to ensure that local processor interrupts remain disabled for at least as long as theSpinLockIrqGuardexists. - Using
lock_with()in contexts where aLocalInterruptDisabledtoken is present and local processor interrupts are already known to be disabled, in which case the local interrupt state will not be touched. This method should be preferred if aLocalInterruptDisabledtoken is present in the scope.
For more info on spinlocks, see SpinLock. For more information on interrupts,
see the interrupt module.
§Examples
The following example shows how to declare, allocate initialise and access a struct (Example)
that contains an inner struct (Inner) that is protected by a spinlock that requires local
processor interrupts to be disabled.
use kernel::sync::{new_spinlock_irq, SpinLockIrq};
struct Inner {
a: u32,
b: u32,
}
#[pin_data]
struct Example {
#[pin]
c: SpinLockIrq<Inner>,
#[pin]
d: SpinLockIrq<Inner>,
}
impl Example {
fn new() -> impl PinInit<Self> {
pin_init!(Self {
c <- new_spinlock_irq!(Inner { a: 0, b: 10 }),
d <- new_spinlock_irq!(Inner { a: 20, b: 30 }),
})
}
}
// Allocate a boxed `Example`
let e = KBox::pin_init(Example::new(), GFP_KERNEL)?;
// Accessing an `Example` from a context where interrupts may not be disabled already.
let c_guard = e.c.lock(); // interrupts are disabled now, +1 interrupt disable refcount
let d_guard = e.d.lock(); // no interrupt state change, +1 interrupt disable refcount
assert_eq!(c_guard.a, 0);
assert_eq!(c_guard.b, 10);
assert_eq!(d_guard.a, 20);
assert_eq!(d_guard.b, 30);
drop(c_guard); // Dropping c_guard will not re-enable interrupts just yet, since d_guard is
// still in scope.
drop(d_guard); // Last interrupt disable reference dropped here, so interrupts are re-enabled
// nowThe next example demonstrates locking a SpinLockIrq using lock_with() in a function
which can only be called when local processor interrupts are already disabled.
use kernel::sync::{new_spinlock_irq, SpinLockIrq};
use kernel::interrupt::*;
struct Inner {
a: u32,
}
#[pin_data]
struct Example {
#[pin]
inner: SpinLockIrq<Inner>,
}
impl Example {
fn new() -> impl PinInit<Self> {
pin_init!(Self {
inner <- new_spinlock_irq!(Inner { a: 20 }),
})
}
}
// Accessing an `Example` from a function that can only be called in no-interrupt contexts.
fn noirq_work(e: &Example, interrupt_disabled: &LocalInterruptDisabled) {
// Because we know interrupts are disabled from interrupt_disable, we can skip toggling
// interrupt state using lock_with() and the provided token
assert_eq!(e.inner.lock_with(interrupt_disabled).a, 20);
}
Aliased Type§
pub struct SpinLockIrq<T> { /* private fields */ }