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 before SpinLock::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

Constructs a new spinlock.

Safety

The caller must call SpinLock::init_lock before using the spinlock.

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.

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

The type of the data protected by the lock.

The type of context, if any, that needs to be stored in the guard.

Acquires the lock, making the caller its owner.

Releases the lock, giving up ownership of the lock. Read more

Returns the data protected by the lock.

Reacquires the lock, making the caller its owner. Read more

The parametrised type of the mutual exclusion primitive that can be created by this factory.

Constructs a new instance of the mutual exclusion primitive. Read more

Initialises the lock instance so that it can be safely used.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Initialises the type instance so that it can be safely used. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.