pub struct SpinLock<T: ?Sized> { /* private fields */ }
Expand description
Exposes the kernel’s spinlock_t
. When multiple CPUs attempt to lock the same spinlock, only
one at a time is allowed to progress, the others will block (spinning) until the spinlock is
unlocked, at which point another CPU will be allowed to make progress.
A SpinLock
must first be initialised with a call to SpinLock::init_lock
before it can be
used. The spinlock_init
macro is provided to automatically assign a new lock class to a
spinlock instance.
There are two ways to acquire the lock:
SpinLock::lock
, which doesn’t manage interrupt state, so it should be used in only two cases: (a) when the caller knows that interrupts are disabled, or (b) when callers never use it in atomic context (e.g., interrupt handlers), in which case it is ok for interrupts to be enabled.SpinLock::lock_irqdisable
, which disables interrupts if they are enabled before acquiring the lock. When the lock is released, the interrupt state is automatically returned to its value beforeSpinLock::lock_irqdisable
was called.
Examples
struct Example {
a: u32,
b: u32,
}
// Function that acquires spinlock without changing interrupt state.
fn lock_example(value: &SpinLock<Example>) {
let mut guard = value.lock();
guard.a = 10;
guard.b = 20;
}
// Function that acquires spinlock and disables interrupts while holding it.
fn lock_irqdisable_example(value: &SpinLock<Example>) {
let mut guard = value.lock_irqdisable();
guard.a = 30;
guard.b = 40;
}
// Initialises a spinlock.
// SAFETY: `spinlock_init` is called below.
let mut value = unsafe { SpinLock::new(Example { a: 1, b: 2 }) };
// SAFETY: We don't move `value`.
kernel::spinlock_init!(unsafe { Pin::new_unchecked(&mut value) }, "value");
// Calls the example functions.
assert_eq!(value.lock().a, 1);
lock_example(&value);
assert_eq!(value.lock().a, 10);
lock_irqdisable_example(&value);
assert_eq!(value.lock().a, 30);
Implementations
sourceimpl<T> SpinLock<T>
impl<T> SpinLock<T>
sourcepub const unsafe fn new(t: T) -> Self
pub const unsafe fn new(t: T) -> Self
Constructs a new spinlock.
Safety
The caller must call SpinLock::init_lock
before using the spinlock.
sourceimpl<T: ?Sized> SpinLock<T>
impl<T: ?Sized> SpinLock<T>
sourcepub fn lock(&self) -> Guard<'_, Self, WriteLock>
pub fn lock(&self) -> Guard<'_, Self, WriteLock>
Locks the spinlock and gives the caller access to the data protected by it. Only one thread at a time is allowed to access the protected data.
sourcepub fn lock_irqdisable(&self) -> Guard<'_, Self, DisabledInterrupts>
pub fn lock_irqdisable(&self) -> Guard<'_, Self, DisabledInterrupts>
Locks the spinlock and gives the caller access to the data protected by it. Additionally it disables interrupts (if they are enabled).
When the lock in unlocked, the interrupt state (enabled/disabled) is restored.
Trait Implementations
sourceimpl<T: ?Sized> Lock<WriteLock> for SpinLock<T>
impl<T: ?Sized> Lock<WriteLock> for SpinLock<T>
type Inner = T
type Inner = T
The type of the data protected by the lock.
type GuardContext = EmptyGuardContext
type GuardContext = EmptyGuardContext
The type of context, if any, that needs to be stored in the guard.
sourcefn lock_noguard(&self) -> EmptyGuardContext
fn lock_noguard(&self) -> EmptyGuardContext
Acquires the lock, making the caller its owner.
sourceunsafe fn unlock(&self, _: &mut EmptyGuardContext)
unsafe fn unlock(&self, _: &mut EmptyGuardContext)
Releases the lock, giving up ownership of the lock. Read more
sourcefn locked_data(&self) -> &UnsafeCell<T>
fn locked_data(&self) -> &UnsafeCell<T>
Returns the data protected by the lock.
sourcefn relock(&self, ctx: &mut Self::GuardContext)
fn relock(&self, ctx: &mut Self::GuardContext)
Reacquires the lock, making the caller its owner. Read more
sourceimpl<T> LockFactory for SpinLock<T>
impl<T> LockFactory for SpinLock<T>
sourceimpl<T> LockIniter for SpinLock<T>
impl<T> LockIniter for SpinLock<T>
impl<T: ?Sized + Send> Send for SpinLock<T>
impl<T: ?Sized + Send> Sync for SpinLock<T>
Auto Trait Implementations
impl<T> !RefUnwindSafe for SpinLock<T>
impl<T> !Unpin for SpinLock<T>
impl<T: ?Sized> UnwindSafe for SpinLock<T> where
T: UnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<L> NeedsLockClass for L where
L: LockIniter,
impl<L> NeedsLockClass for L where
L: LockIniter,
sourcefn init(
self: Pin<&mut L>,
name: &'static CStr,
key: &'static LockClassKey,
&'static LockClassKey
)
fn init(
self: Pin<&mut L>,
name: &'static CStr,
key: &'static LockClassKey,
&'static LockClassKey
)
Initialises the type instance so that it can be safely used. Read more