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