Messages in this thread | | | Date | Sun, 9 Apr 2023 13:48:17 -0300 | From | Martin Rodriguez Reboredo <> | Subject | Re: [PATCH v3 06/13] rust: lock: add support for `Lock::lock_irqsave` |
| |
On 4/8/23 04:53, Wedson Almeida Filho wrote: > From: Wedson Almeida Filho <walmeida@microsoft.com> > > 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 <walmeida@microsoft.com> > --- > v1 -> v2: No changes > v2 -> v3: No changes > > rust/kernel/sync/lock.rs | 38 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 38 insertions(+) > > diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs > index df43dff5af5c..690429561f0e 100644 > --- a/rust/kernel/sync/lock.rs > +++ b/rust/kernel/sync/lock.rs > @@ -57,6 +57,29 @@ pub unsafe trait Backend { > unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState); > } > > +/// The "backend" of a lock that supports the irq-save variant. > +/// > +/// # Safety > +/// > +/// The same requirements wrt mutual exclusion in [`Backend`] apply for acquiring the lock via > +/// [`IrqSaveBackend::lock_irqsave`]. > +/// > +/// Additionally, when [`IrqSaveBackend::lock_irqsave`] is used to acquire the lock, implementers > +/// must disable interrupts on lock, and restore interrupt state on unlock. Implementers may use > +/// [`Backend::GuardState`] to store state needed to keep track of the interrupt state. > +pub unsafe trait IrqSaveBackend: Backend { > + /// Acquires the lock, making the caller its owner. > + /// > + /// Before acquiring the lock, it disables interrupts, and returns the previous interrupt state > + /// as its guard state so that the guard can restore it when it is dropped. > + /// > + /// # Safety > + /// > + /// Callers must ensure that [`Backend::init`] has been previously called. > + #[must_use] > + unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState; > +} > + > /// A mutual exclusion primitive. > /// > /// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend > @@ -111,6 +134,21 @@ impl<T: ?Sized, B: Backend> Lock<T, B> { > } > } > > +impl<T: ?Sized, B: IrqSaveBackend> Lock<T, B> { > + /// Acquires the lock and gives the caller access to the data protected by it. > + /// > + /// Before acquiring the lock, it disables interrupts. When the guard is dropped, the interrupt > + /// state (either enabled or disabled) is restored to its state before > + /// [`lock_irqsave`](Self::lock_irqsave) was called. > + pub fn lock_irqsave(&self) -> Guard<'_, T, B> { > + // SAFETY: The constructor of the type calls `init`, so the existence of the object proves > + // that `init` was called. > + let state = unsafe { B::lock_irqsave(self.state.get()) }; > + // SAFETY: The lock was just acquired. > + unsafe { Guard::new(self, state) } > + } > +} > + > /// A lock guard. > /// > /// Allows mutual exclusion primitives that implement the `Backend` trait to automatically unlock
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
| |