xref: /linux/rust/kernel/sync/lock/global.rs (revision 60675d4ca1ef0857e44eba5849b74a3a998d0c0f)
1*8eea62ffSAlice Ryhl // SPDX-License-Identifier: GPL-2.0
2*8eea62ffSAlice Ryhl 
3*8eea62ffSAlice Ryhl // Copyright (C) 2024 Google LLC.
4*8eea62ffSAlice Ryhl 
5*8eea62ffSAlice Ryhl //! Support for defining statics containing locks.
6*8eea62ffSAlice Ryhl 
7*8eea62ffSAlice Ryhl use crate::{
8*8eea62ffSAlice Ryhl     str::CStr,
9*8eea62ffSAlice Ryhl     sync::lock::{Backend, Guard, Lock},
10*8eea62ffSAlice Ryhl     sync::{LockClassKey, LockedBy},
11*8eea62ffSAlice Ryhl     types::Opaque,
12*8eea62ffSAlice Ryhl };
13*8eea62ffSAlice Ryhl use core::{
14*8eea62ffSAlice Ryhl     cell::UnsafeCell,
15*8eea62ffSAlice Ryhl     marker::{PhantomData, PhantomPinned},
16*8eea62ffSAlice Ryhl };
17*8eea62ffSAlice Ryhl 
18*8eea62ffSAlice Ryhl /// Trait implemented for marker types for global locks.
19*8eea62ffSAlice Ryhl ///
20*8eea62ffSAlice Ryhl /// See [`global_lock!`] for examples.
21*8eea62ffSAlice Ryhl pub trait GlobalLockBackend {
22*8eea62ffSAlice Ryhl     /// The name for this global lock.
23*8eea62ffSAlice Ryhl     const NAME: &'static CStr;
24*8eea62ffSAlice Ryhl     /// Item type stored in this global lock.
25*8eea62ffSAlice Ryhl     type Item: 'static;
26*8eea62ffSAlice Ryhl     /// The backend used for this global lock.
27*8eea62ffSAlice Ryhl     type Backend: Backend + 'static;
28*8eea62ffSAlice Ryhl     /// The class for this global lock.
29*8eea62ffSAlice Ryhl     fn get_lock_class() -> &'static LockClassKey;
30*8eea62ffSAlice Ryhl }
31*8eea62ffSAlice Ryhl 
32*8eea62ffSAlice Ryhl /// Type used for global locks.
33*8eea62ffSAlice Ryhl ///
34*8eea62ffSAlice Ryhl /// See [`global_lock!`] for examples.
35*8eea62ffSAlice Ryhl pub struct GlobalLock<B: GlobalLockBackend> {
36*8eea62ffSAlice Ryhl     inner: Lock<B::Item, B::Backend>,
37*8eea62ffSAlice Ryhl }
38*8eea62ffSAlice Ryhl 
39*8eea62ffSAlice Ryhl impl<B: GlobalLockBackend> GlobalLock<B> {
40*8eea62ffSAlice Ryhl     /// Creates a global lock.
41*8eea62ffSAlice Ryhl     ///
42*8eea62ffSAlice Ryhl     /// # Safety
43*8eea62ffSAlice Ryhl     ///
44*8eea62ffSAlice Ryhl     /// * Before any other method on this lock is called, [`Self::init`] must be called.
45*8eea62ffSAlice Ryhl     /// * The type `B` must not be used with any other lock.
46*8eea62ffSAlice Ryhl     pub const unsafe fn new(data: B::Item) -> Self {
47*8eea62ffSAlice Ryhl         Self {
48*8eea62ffSAlice Ryhl             inner: Lock {
49*8eea62ffSAlice Ryhl                 state: Opaque::uninit(),
50*8eea62ffSAlice Ryhl                 data: UnsafeCell::new(data),
51*8eea62ffSAlice Ryhl                 _pin: PhantomPinned,
52*8eea62ffSAlice Ryhl             },
53*8eea62ffSAlice Ryhl         }
54*8eea62ffSAlice Ryhl     }
55*8eea62ffSAlice Ryhl 
56*8eea62ffSAlice Ryhl     /// Initializes a global lock.
57*8eea62ffSAlice Ryhl     ///
58*8eea62ffSAlice Ryhl     /// # Safety
59*8eea62ffSAlice Ryhl     ///
60*8eea62ffSAlice Ryhl     /// Must not be called more than once on a given lock.
61*8eea62ffSAlice Ryhl     pub unsafe fn init(&'static self) {
62*8eea62ffSAlice Ryhl         // SAFETY: The pointer to `state` is valid for the duration of this call, and both `name`
63*8eea62ffSAlice Ryhl         // and `key` are valid indefinitely. The `state` is pinned since we have a `'static`
64*8eea62ffSAlice Ryhl         // reference to `self`.
65*8eea62ffSAlice Ryhl         //
66*8eea62ffSAlice Ryhl         // We have exclusive access to the `state` since the caller of `new` promised to call
67*8eea62ffSAlice Ryhl         // `init` before using any other methods. As `init` can only be called once, all other
68*8eea62ffSAlice Ryhl         // uses of this lock must happen after this call.
69*8eea62ffSAlice Ryhl         unsafe {
70*8eea62ffSAlice Ryhl             B::Backend::init(
71*8eea62ffSAlice Ryhl                 self.inner.state.get(),
72*8eea62ffSAlice Ryhl                 B::NAME.as_char_ptr(),
73*8eea62ffSAlice Ryhl                 B::get_lock_class().as_ptr(),
74*8eea62ffSAlice Ryhl             )
75*8eea62ffSAlice Ryhl         }
76*8eea62ffSAlice Ryhl     }
77*8eea62ffSAlice Ryhl 
78*8eea62ffSAlice Ryhl     /// Lock this global lock.
79*8eea62ffSAlice Ryhl     pub fn lock(&'static self) -> GlobalGuard<B> {
80*8eea62ffSAlice Ryhl         GlobalGuard {
81*8eea62ffSAlice Ryhl             inner: self.inner.lock(),
82*8eea62ffSAlice Ryhl         }
83*8eea62ffSAlice Ryhl     }
84*8eea62ffSAlice Ryhl 
85*8eea62ffSAlice Ryhl     /// Try to lock this global lock.
86*8eea62ffSAlice Ryhl     pub fn try_lock(&'static self) -> Option<GlobalGuard<B>> {
87*8eea62ffSAlice Ryhl         Some(GlobalGuard {
88*8eea62ffSAlice Ryhl             inner: self.inner.try_lock()?,
89*8eea62ffSAlice Ryhl         })
90*8eea62ffSAlice Ryhl     }
91*8eea62ffSAlice Ryhl }
92*8eea62ffSAlice Ryhl 
93*8eea62ffSAlice Ryhl /// A guard for a [`GlobalLock`].
94*8eea62ffSAlice Ryhl ///
95*8eea62ffSAlice Ryhl /// See [`global_lock!`] for examples.
96*8eea62ffSAlice Ryhl pub struct GlobalGuard<B: GlobalLockBackend> {
97*8eea62ffSAlice Ryhl     inner: Guard<'static, B::Item, B::Backend>,
98*8eea62ffSAlice Ryhl }
99*8eea62ffSAlice Ryhl 
100*8eea62ffSAlice Ryhl impl<B: GlobalLockBackend> core::ops::Deref for GlobalGuard<B> {
101*8eea62ffSAlice Ryhl     type Target = B::Item;
102*8eea62ffSAlice Ryhl 
103*8eea62ffSAlice Ryhl     fn deref(&self) -> &Self::Target {
104*8eea62ffSAlice Ryhl         &self.inner
105*8eea62ffSAlice Ryhl     }
106*8eea62ffSAlice Ryhl }
107*8eea62ffSAlice Ryhl 
108*8eea62ffSAlice Ryhl impl<B: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<B> {
109*8eea62ffSAlice Ryhl     fn deref_mut(&mut self) -> &mut Self::Target {
110*8eea62ffSAlice Ryhl         &mut self.inner
111*8eea62ffSAlice Ryhl     }
112*8eea62ffSAlice Ryhl }
113*8eea62ffSAlice Ryhl 
114*8eea62ffSAlice Ryhl /// A version of [`LockedBy`] for a [`GlobalLock`].
115*8eea62ffSAlice Ryhl ///
116*8eea62ffSAlice Ryhl /// See [`global_lock!`] for examples.
117*8eea62ffSAlice Ryhl pub struct GlobalLockedBy<T: ?Sized, B: GlobalLockBackend> {
118*8eea62ffSAlice Ryhl     _backend: PhantomData<B>,
119*8eea62ffSAlice Ryhl     value: UnsafeCell<T>,
120*8eea62ffSAlice Ryhl }
121*8eea62ffSAlice Ryhl 
122*8eea62ffSAlice Ryhl // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLockedBy`.
123*8eea62ffSAlice Ryhl unsafe impl<T, B> Send for GlobalLockedBy<T, B>
124*8eea62ffSAlice Ryhl where
125*8eea62ffSAlice Ryhl     T: ?Sized,
126*8eea62ffSAlice Ryhl     B: GlobalLockBackend,
127*8eea62ffSAlice Ryhl     LockedBy<T, B::Item>: Send,
128*8eea62ffSAlice Ryhl {
129*8eea62ffSAlice Ryhl }
130*8eea62ffSAlice Ryhl 
131*8eea62ffSAlice Ryhl // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLockedBy`.
132*8eea62ffSAlice Ryhl unsafe impl<T, B> Sync for GlobalLockedBy<T, B>
133*8eea62ffSAlice Ryhl where
134*8eea62ffSAlice Ryhl     T: ?Sized,
135*8eea62ffSAlice Ryhl     B: GlobalLockBackend,
136*8eea62ffSAlice Ryhl     LockedBy<T, B::Item>: Sync,
137*8eea62ffSAlice Ryhl {
138*8eea62ffSAlice Ryhl }
139*8eea62ffSAlice Ryhl 
140*8eea62ffSAlice Ryhl impl<T, B: GlobalLockBackend> GlobalLockedBy<T, B> {
141*8eea62ffSAlice Ryhl     /// Create a new [`GlobalLockedBy`].
142*8eea62ffSAlice Ryhl     ///
143*8eea62ffSAlice Ryhl     /// The provided value will be protected by the global lock indicated by `B`.
144*8eea62ffSAlice Ryhl     pub fn new(val: T) -> Self {
145*8eea62ffSAlice Ryhl         Self {
146*8eea62ffSAlice Ryhl             value: UnsafeCell::new(val),
147*8eea62ffSAlice Ryhl             _backend: PhantomData,
148*8eea62ffSAlice Ryhl         }
149*8eea62ffSAlice Ryhl     }
150*8eea62ffSAlice Ryhl }
151*8eea62ffSAlice Ryhl 
152*8eea62ffSAlice Ryhl impl<T: ?Sized, B: GlobalLockBackend> GlobalLockedBy<T, B> {
153*8eea62ffSAlice Ryhl     /// Access the value immutably.
154*8eea62ffSAlice Ryhl     ///
155*8eea62ffSAlice Ryhl     /// The caller must prove shared access to the lock.
156*8eea62ffSAlice Ryhl     pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<B>) -> &'a T {
157*8eea62ffSAlice Ryhl         // SAFETY: The lock is globally unique, so there can only be one guard.
158*8eea62ffSAlice Ryhl         unsafe { &*self.value.get() }
159*8eea62ffSAlice Ryhl     }
160*8eea62ffSAlice Ryhl 
161*8eea62ffSAlice Ryhl     /// Access the value mutably.
162*8eea62ffSAlice Ryhl     ///
163*8eea62ffSAlice Ryhl     /// The caller must prove shared exclusive to the lock.
164*8eea62ffSAlice Ryhl     pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<B>) -> &'a mut T {
165*8eea62ffSAlice Ryhl         // SAFETY: The lock is globally unique, so there can only be one guard.
166*8eea62ffSAlice Ryhl         unsafe { &mut *self.value.get() }
167*8eea62ffSAlice Ryhl     }
168*8eea62ffSAlice Ryhl 
169*8eea62ffSAlice Ryhl     /// Access the value mutably directly.
170*8eea62ffSAlice Ryhl     ///
171*8eea62ffSAlice Ryhl     /// The caller has exclusive access to this `GlobalLockedBy`, so they do not need to hold the
172*8eea62ffSAlice Ryhl     /// lock.
173*8eea62ffSAlice Ryhl     pub fn get_mut(&mut self) -> &mut T {
174*8eea62ffSAlice Ryhl         self.value.get_mut()
175*8eea62ffSAlice Ryhl     }
176*8eea62ffSAlice Ryhl }
177*8eea62ffSAlice Ryhl 
178*8eea62ffSAlice Ryhl /// Defines a global lock.
179*8eea62ffSAlice Ryhl ///
180*8eea62ffSAlice Ryhl /// The global mutex must be initialized before first use. Usually this is done by calling
181*8eea62ffSAlice Ryhl /// [`GlobalLock::init`] in the module initializer.
182*8eea62ffSAlice Ryhl ///
183*8eea62ffSAlice Ryhl /// # Examples
184*8eea62ffSAlice Ryhl ///
185*8eea62ffSAlice Ryhl /// A global counter:
186*8eea62ffSAlice Ryhl ///
187*8eea62ffSAlice Ryhl /// ```
188*8eea62ffSAlice Ryhl /// # mod ex {
189*8eea62ffSAlice Ryhl /// # use kernel::prelude::*;
190*8eea62ffSAlice Ryhl /// kernel::sync::global_lock! {
191*8eea62ffSAlice Ryhl ///     // SAFETY: Initialized in module initializer before first use.
192*8eea62ffSAlice Ryhl ///     unsafe(uninit) static MY_COUNTER: Mutex<u32> = 0;
193*8eea62ffSAlice Ryhl /// }
194*8eea62ffSAlice Ryhl ///
195*8eea62ffSAlice Ryhl /// fn increment_counter() -> u32 {
196*8eea62ffSAlice Ryhl ///     let mut guard = MY_COUNTER.lock();
197*8eea62ffSAlice Ryhl ///     *guard += 1;
198*8eea62ffSAlice Ryhl ///     *guard
199*8eea62ffSAlice Ryhl /// }
200*8eea62ffSAlice Ryhl ///
201*8eea62ffSAlice Ryhl /// impl kernel::Module for MyModule {
202*8eea62ffSAlice Ryhl ///     fn init(_module: &'static ThisModule) -> Result<Self> {
203*8eea62ffSAlice Ryhl ///         // SAFETY: Called exactly once.
204*8eea62ffSAlice Ryhl ///         unsafe { MY_COUNTER.init() };
205*8eea62ffSAlice Ryhl ///
206*8eea62ffSAlice Ryhl ///         Ok(MyModule {})
207*8eea62ffSAlice Ryhl ///     }
208*8eea62ffSAlice Ryhl /// }
209*8eea62ffSAlice Ryhl /// # struct MyModule {}
210*8eea62ffSAlice Ryhl /// # }
211*8eea62ffSAlice Ryhl /// ```
212*8eea62ffSAlice Ryhl ///
213*8eea62ffSAlice Ryhl /// A global mutex used to protect all instances of a given struct:
214*8eea62ffSAlice Ryhl ///
215*8eea62ffSAlice Ryhl /// ```
216*8eea62ffSAlice Ryhl /// # mod ex {
217*8eea62ffSAlice Ryhl /// # use kernel::prelude::*;
218*8eea62ffSAlice Ryhl /// use kernel::sync::{GlobalGuard, GlobalLockedBy};
219*8eea62ffSAlice Ryhl ///
220*8eea62ffSAlice Ryhl /// kernel::sync::global_lock! {
221*8eea62ffSAlice Ryhl ///     // SAFETY: Initialized in module initializer before first use.
222*8eea62ffSAlice Ryhl ///     unsafe(uninit) static MY_MUTEX: Mutex<()> = ();
223*8eea62ffSAlice Ryhl /// }
224*8eea62ffSAlice Ryhl ///
225*8eea62ffSAlice Ryhl /// /// All instances of this struct are protected by `MY_MUTEX`.
226*8eea62ffSAlice Ryhl /// struct MyStruct {
227*8eea62ffSAlice Ryhl ///     my_counter: GlobalLockedBy<u32, MY_MUTEX>,
228*8eea62ffSAlice Ryhl /// }
229*8eea62ffSAlice Ryhl ///
230*8eea62ffSAlice Ryhl /// impl MyStruct {
231*8eea62ffSAlice Ryhl ///     /// Increment the counter in this instance.
232*8eea62ffSAlice Ryhl ///     ///
233*8eea62ffSAlice Ryhl ///     /// The caller must hold the `MY_MUTEX` mutex.
234*8eea62ffSAlice Ryhl ///     fn increment(&self, guard: &mut GlobalGuard<MY_MUTEX>) -> u32 {
235*8eea62ffSAlice Ryhl ///         let my_counter = self.my_counter.as_mut(guard);
236*8eea62ffSAlice Ryhl ///         *my_counter += 1;
237*8eea62ffSAlice Ryhl ///         *my_counter
238*8eea62ffSAlice Ryhl ///     }
239*8eea62ffSAlice Ryhl /// }
240*8eea62ffSAlice Ryhl ///
241*8eea62ffSAlice Ryhl /// impl kernel::Module for MyModule {
242*8eea62ffSAlice Ryhl ///     fn init(_module: &'static ThisModule) -> Result<Self> {
243*8eea62ffSAlice Ryhl ///         // SAFETY: Called exactly once.
244*8eea62ffSAlice Ryhl ///         unsafe { MY_MUTEX.init() };
245*8eea62ffSAlice Ryhl ///
246*8eea62ffSAlice Ryhl ///         Ok(MyModule {})
247*8eea62ffSAlice Ryhl ///     }
248*8eea62ffSAlice Ryhl /// }
249*8eea62ffSAlice Ryhl /// # struct MyModule {}
250*8eea62ffSAlice Ryhl /// # }
251*8eea62ffSAlice Ryhl /// ```
252*8eea62ffSAlice Ryhl #[macro_export]
253*8eea62ffSAlice Ryhl macro_rules! global_lock {
254*8eea62ffSAlice Ryhl     {
255*8eea62ffSAlice Ryhl         $(#[$meta:meta])* $pub:vis
256*8eea62ffSAlice Ryhl         unsafe(uninit) static $name:ident: $kind:ident<$valuety:ty> = $value:expr;
257*8eea62ffSAlice Ryhl     } => {
258*8eea62ffSAlice Ryhl         #[doc = ::core::concat!(
259*8eea62ffSAlice Ryhl             "Backend type used by [`",
260*8eea62ffSAlice Ryhl             ::core::stringify!($name),
261*8eea62ffSAlice Ryhl             "`](static@",
262*8eea62ffSAlice Ryhl             ::core::stringify!($name),
263*8eea62ffSAlice Ryhl             ")."
264*8eea62ffSAlice Ryhl         )]
265*8eea62ffSAlice Ryhl         #[allow(non_camel_case_types, unreachable_pub)]
266*8eea62ffSAlice Ryhl         $pub enum $name {}
267*8eea62ffSAlice Ryhl 
268*8eea62ffSAlice Ryhl         impl $crate::sync::lock::GlobalLockBackend for $name {
269*8eea62ffSAlice Ryhl             const NAME: &'static $crate::str::CStr = $crate::c_str!(::core::stringify!($name));
270*8eea62ffSAlice Ryhl             type Item = $valuety;
271*8eea62ffSAlice Ryhl             type Backend = $crate::global_lock_inner!(backend $kind);
272*8eea62ffSAlice Ryhl 
273*8eea62ffSAlice Ryhl             fn get_lock_class() -> &'static $crate::sync::LockClassKey {
274*8eea62ffSAlice Ryhl                 $crate::static_lock_class!()
275*8eea62ffSAlice Ryhl             }
276*8eea62ffSAlice Ryhl         }
277*8eea62ffSAlice Ryhl 
278*8eea62ffSAlice Ryhl         $(#[$meta])*
279*8eea62ffSAlice Ryhl         $pub static $name: $crate::sync::lock::GlobalLock<$name> = {
280*8eea62ffSAlice Ryhl             // Defined here to be outside the unsafe scope.
281*8eea62ffSAlice Ryhl             let init: $valuety = $value;
282*8eea62ffSAlice Ryhl 
283*8eea62ffSAlice Ryhl             // SAFETY:
284*8eea62ffSAlice Ryhl             // * The user of this macro promises to initialize the macro before use.
285*8eea62ffSAlice Ryhl             // * We are only generating one static with this backend type.
286*8eea62ffSAlice Ryhl             unsafe { $crate::sync::lock::GlobalLock::new(init) }
287*8eea62ffSAlice Ryhl         };
288*8eea62ffSAlice Ryhl     };
289*8eea62ffSAlice Ryhl }
290*8eea62ffSAlice Ryhl pub use global_lock;
291*8eea62ffSAlice Ryhl 
292*8eea62ffSAlice Ryhl #[doc(hidden)]
293*8eea62ffSAlice Ryhl #[macro_export]
294*8eea62ffSAlice Ryhl macro_rules! global_lock_inner {
295*8eea62ffSAlice Ryhl     (backend Mutex) => {
296*8eea62ffSAlice Ryhl         $crate::sync::lock::mutex::MutexBackend
297*8eea62ffSAlice Ryhl     };
298*8eea62ffSAlice Ryhl     (backend SpinLock) => {
299*8eea62ffSAlice Ryhl         $crate::sync::lock::spinlock::SpinLockBackend
300*8eea62ffSAlice Ryhl     };
301*8eea62ffSAlice Ryhl }
302