xref: /linux-6.15/rust/kernel/sync/rcu.rs (revision 51158207)
1*51158207SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0
2*51158207SWedson Almeida Filho 
3*51158207SWedson Almeida Filho //! RCU support.
4*51158207SWedson Almeida Filho //!
5*51158207SWedson Almeida Filho //! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
6*51158207SWedson Almeida Filho 
7*51158207SWedson Almeida Filho use crate::{bindings, types::NotThreadSafe};
8*51158207SWedson Almeida Filho 
9*51158207SWedson Almeida Filho /// Evidence that the RCU read side lock is held on the current thread/CPU.
10*51158207SWedson Almeida Filho ///
11*51158207SWedson Almeida Filho /// The type is explicitly not `Send` because this property is per-thread/CPU.
12*51158207SWedson Almeida Filho ///
13*51158207SWedson Almeida Filho /// # Invariants
14*51158207SWedson Almeida Filho ///
15*51158207SWedson Almeida Filho /// The RCU read side lock is actually held while instances of this guard exist.
16*51158207SWedson Almeida Filho pub struct Guard(NotThreadSafe);
17*51158207SWedson Almeida Filho 
18*51158207SWedson Almeida Filho impl Guard {
19*51158207SWedson Almeida Filho     /// Acquires the RCU read side lock and returns a guard.
new() -> Self20*51158207SWedson Almeida Filho     pub fn new() -> Self {
21*51158207SWedson Almeida Filho         // SAFETY: An FFI call with no additional requirements.
22*51158207SWedson Almeida Filho         unsafe { bindings::rcu_read_lock() };
23*51158207SWedson Almeida Filho         // INVARIANT: The RCU read side lock was just acquired above.
24*51158207SWedson Almeida Filho         Self(NotThreadSafe)
25*51158207SWedson Almeida Filho     }
26*51158207SWedson Almeida Filho 
27*51158207SWedson Almeida Filho     /// Explicitly releases the RCU read side lock.
unlock(self)28*51158207SWedson Almeida Filho     pub fn unlock(self) {}
29*51158207SWedson Almeida Filho }
30*51158207SWedson Almeida Filho 
31*51158207SWedson Almeida Filho impl Default for Guard {
default() -> Self32*51158207SWedson Almeida Filho     fn default() -> Self {
33*51158207SWedson Almeida Filho         Self::new()
34*51158207SWedson Almeida Filho     }
35*51158207SWedson Almeida Filho }
36*51158207SWedson Almeida Filho 
37*51158207SWedson Almeida Filho impl Drop for Guard {
drop(&mut self)38*51158207SWedson Almeida Filho     fn drop(&mut self) {
39*51158207SWedson Almeida Filho         // SAFETY: By the type invariants, the RCU read side is locked, so it is ok to unlock it.
40*51158207SWedson Almeida Filho         unsafe { bindings::rcu_read_unlock() };
41*51158207SWedson Almeida Filho     }
42*51158207SWedson Almeida Filho }
43*51158207SWedson Almeida Filho 
44*51158207SWedson Almeida Filho /// Acquires the RCU read side lock.
read_lock() -> Guard45*51158207SWedson Almeida Filho pub fn read_lock() -> Guard {
46*51158207SWedson Almeida Filho     Guard::new()
47*51158207SWedson Almeida Filho }
48