Skip to content

Commit e5aa829

Browse files
committed
rust: lock: add support for Lock::lock_irqsave
This allows locks like spinlocks and raw spinlocks to expose a `lock_irqsave` variant in Rust that corresponds to the C version. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent acd91b2 commit e5aa829

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

rust/kernel/sync/lock.rs

+38
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,29 @@ pub unsafe trait Backend {
5757
unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState);
5858
}
5959

60+
/// The "backend" of a lock that supports the irq-save variant.
61+
///
62+
/// # Safety
63+
///
64+
/// The same requirements wrt mutual exclusion in [`Backend`] apply for acquiring the lock via
65+
/// [`IrqSaveBackend::lock_irqsave`].
66+
///
67+
/// Additionally, when [`IrqSaveBackend::lock_irqsave`] is used to acquire the lock, implementers
68+
/// must disable interrupts on lock, and restore interrupt state on unlock. Implementers may use
69+
/// [`Backend::GuardState`] to store state needed to keep track of the interrupt state.
70+
pub unsafe trait IrqSaveBackend: Backend {
71+
/// Acquires the lock, making the caller its owner.
72+
///
73+
/// Before acquiring the lock, it disables interrupts, and returns the previous interrupt state
74+
/// as its guard state so that the guard can restore it when it is dropped.
75+
///
76+
/// # Safety
77+
///
78+
/// Callers must ensure that [`Backend::init`] has been previously called.
79+
#[must_use]
80+
unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState;
81+
}
82+
6083
/// A mutual exclusion primitive.
6184
///
6285
/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend
@@ -109,6 +132,21 @@ impl<T: ?Sized, B: Backend> Lock<T, B> {
109132
}
110133
}
111134

135+
impl<T: ?Sized, B: IrqSaveBackend> Lock<T, B> {
136+
/// Acquires the lock and gives the caller access to the data protected by it.
137+
///
138+
/// Before acquiring the lock, it disables interrupts. When the guard is dropped, the interrupt
139+
/// state (either enabled or disabled) is restored to its state before
140+
/// [`lock_irqsave`](Self::lock_irqsave) was called.
141+
pub fn lock_irqsave(&self) -> Guard<'_, T, B> {
142+
// SAFETY: The constructor of the type calls `init`, so the existence of the object proves
143+
// that `init` was called.
144+
let state = unsafe { B::lock_irqsave(self.state.get()) };
145+
// SAFETY: The lock was just acquired.
146+
unsafe { Guard::new(self, state) }
147+
}
148+
}
149+
112150
/// A lock guard.
113151
///
114152
/// Allows mutual exclusion primitives that implement the `Backend` trait to automatically unlock

0 commit comments

Comments
 (0)