xref: /linux/rust/kernel/sync/rcu.rs (revision 07046958f6ddaa1e05ac64d1e11e77b6db9a00ce)
151158207SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0
251158207SWedson Almeida Filho 
351158207SWedson Almeida Filho //! RCU support.
451158207SWedson Almeida Filho //!
551158207SWedson Almeida Filho //! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
651158207SWedson Almeida Filho 
751158207SWedson Almeida Filho use crate::{bindings, types::NotThreadSafe};
851158207SWedson Almeida Filho 
951158207SWedson Almeida Filho /// Evidence that the RCU read side lock is held on the current thread/CPU.
1051158207SWedson Almeida Filho ///
1151158207SWedson Almeida Filho /// The type is explicitly not `Send` because this property is per-thread/CPU.
1251158207SWedson Almeida Filho ///
1351158207SWedson Almeida Filho /// # Invariants
1451158207SWedson Almeida Filho ///
1551158207SWedson Almeida Filho /// The RCU read side lock is actually held while instances of this guard exist.
1651158207SWedson Almeida Filho pub struct Guard(NotThreadSafe);
1751158207SWedson Almeida Filho 
1851158207SWedson Almeida Filho impl Guard {
1951158207SWedson Almeida Filho     /// Acquires the RCU read side lock and returns a guard.
20*9520371eSI Hsin Cheng     #[inline]
2151158207SWedson Almeida Filho     pub fn new() -> Self {
2251158207SWedson Almeida Filho         // SAFETY: An FFI call with no additional requirements.
2351158207SWedson Almeida Filho         unsafe { bindings::rcu_read_lock() };
2451158207SWedson Almeida Filho         // INVARIANT: The RCU read side lock was just acquired above.
2551158207SWedson Almeida Filho         Self(NotThreadSafe)
2651158207SWedson Almeida Filho     }
2751158207SWedson Almeida Filho 
2851158207SWedson Almeida Filho     /// Explicitly releases the RCU read side lock.
29*9520371eSI Hsin Cheng     #[inline]
3051158207SWedson Almeida Filho     pub fn unlock(self) {}
3151158207SWedson Almeida Filho }
3251158207SWedson Almeida Filho 
3351158207SWedson Almeida Filho impl Default for Guard {
34*9520371eSI Hsin Cheng     #[inline]
3551158207SWedson Almeida Filho     fn default() -> Self {
3651158207SWedson Almeida Filho         Self::new()
3751158207SWedson Almeida Filho     }
3851158207SWedson Almeida Filho }
3951158207SWedson Almeida Filho 
4051158207SWedson Almeida Filho impl Drop for Guard {
41*9520371eSI Hsin Cheng     #[inline]
4251158207SWedson Almeida Filho     fn drop(&mut self) {
4351158207SWedson Almeida Filho         // SAFETY: By the type invariants, the RCU read side is locked, so it is ok to unlock it.
4451158207SWedson Almeida Filho         unsafe { bindings::rcu_read_unlock() };
4551158207SWedson Almeida Filho     }
4651158207SWedson Almeida Filho }
4751158207SWedson Almeida Filho 
4851158207SWedson Almeida Filho /// Acquires the RCU read side lock.
49*9520371eSI Hsin Cheng #[inline]
5051158207SWedson Almeida Filho pub fn read_lock() -> Guard {
5151158207SWedson Almeida Filho     Guard::new()
5251158207SWedson Almeida Filho }
53