18eea62ffSAlice Ryhl // SPDX-License-Identifier: GPL-2.0 28eea62ffSAlice Ryhl 38eea62ffSAlice Ryhl // Copyright (C) 2024 Google LLC. 48eea62ffSAlice Ryhl 58eea62ffSAlice Ryhl //! Support for defining statics containing locks. 68eea62ffSAlice Ryhl 78eea62ffSAlice Ryhl use crate::{ 88eea62ffSAlice Ryhl str::CStr, 98eea62ffSAlice Ryhl sync::lock::{Backend, Guard, Lock}, 108eea62ffSAlice Ryhl sync::{LockClassKey, LockedBy}, 118eea62ffSAlice Ryhl types::Opaque, 128eea62ffSAlice Ryhl }; 138eea62ffSAlice Ryhl use core::{ 148eea62ffSAlice Ryhl cell::UnsafeCell, 158eea62ffSAlice Ryhl marker::{PhantomData, PhantomPinned}, 16*f73ca66fSMitchell Levy pin::Pin, 178eea62ffSAlice Ryhl }; 188eea62ffSAlice Ryhl 198eea62ffSAlice Ryhl /// Trait implemented for marker types for global locks. 208eea62ffSAlice Ryhl /// 218eea62ffSAlice Ryhl /// See [`global_lock!`] for examples. 228eea62ffSAlice Ryhl pub trait GlobalLockBackend { 238eea62ffSAlice Ryhl /// The name for this global lock. 248eea62ffSAlice Ryhl const NAME: &'static CStr; 258eea62ffSAlice Ryhl /// Item type stored in this global lock. 268eea62ffSAlice Ryhl type Item: 'static; 278eea62ffSAlice Ryhl /// The backend used for this global lock. 288eea62ffSAlice Ryhl type Backend: Backend + 'static; 298eea62ffSAlice Ryhl /// The class for this global lock. get_lock_class() -> Pin<&'static LockClassKey>30*f73ca66fSMitchell Levy fn get_lock_class() -> Pin<&'static LockClassKey>; 318eea62ffSAlice Ryhl } 328eea62ffSAlice Ryhl 338eea62ffSAlice Ryhl /// Type used for global locks. 348eea62ffSAlice Ryhl /// 358eea62ffSAlice Ryhl /// See [`global_lock!`] for examples. 368eea62ffSAlice Ryhl pub struct GlobalLock<B: GlobalLockBackend> { 378eea62ffSAlice Ryhl inner: Lock<B::Item, B::Backend>, 388eea62ffSAlice Ryhl } 398eea62ffSAlice Ryhl 408eea62ffSAlice Ryhl impl<B: GlobalLockBackend> GlobalLock<B> { 418eea62ffSAlice Ryhl /// Creates a global lock. 428eea62ffSAlice Ryhl /// 438eea62ffSAlice Ryhl /// # Safety 448eea62ffSAlice Ryhl /// 458eea62ffSAlice Ryhl /// * Before any other method on this lock is called, [`Self::init`] must be called. 468eea62ffSAlice Ryhl /// * The type `B` must not be used with any other lock. new(data: B::Item) -> Self478eea62ffSAlice Ryhl pub const unsafe fn new(data: B::Item) -> Self { 488eea62ffSAlice Ryhl Self { 498eea62ffSAlice Ryhl inner: Lock { 508eea62ffSAlice Ryhl state: Opaque::uninit(), 518eea62ffSAlice Ryhl data: UnsafeCell::new(data), 528eea62ffSAlice Ryhl _pin: PhantomPinned, 538eea62ffSAlice Ryhl }, 548eea62ffSAlice Ryhl } 558eea62ffSAlice Ryhl } 568eea62ffSAlice Ryhl 578eea62ffSAlice Ryhl /// Initializes a global lock. 588eea62ffSAlice Ryhl /// 598eea62ffSAlice Ryhl /// # Safety 608eea62ffSAlice Ryhl /// 618eea62ffSAlice Ryhl /// Must not be called more than once on a given lock. init(&'static self)628eea62ffSAlice Ryhl pub unsafe fn init(&'static self) { 638eea62ffSAlice Ryhl // SAFETY: The pointer to `state` is valid for the duration of this call, and both `name` 648eea62ffSAlice Ryhl // and `key` are valid indefinitely. The `state` is pinned since we have a `'static` 658eea62ffSAlice Ryhl // reference to `self`. 668eea62ffSAlice Ryhl // 678eea62ffSAlice Ryhl // We have exclusive access to the `state` since the caller of `new` promised to call 688eea62ffSAlice Ryhl // `init` before using any other methods. As `init` can only be called once, all other 698eea62ffSAlice Ryhl // uses of this lock must happen after this call. 708eea62ffSAlice Ryhl unsafe { 718eea62ffSAlice Ryhl B::Backend::init( 728eea62ffSAlice Ryhl self.inner.state.get(), 738eea62ffSAlice Ryhl B::NAME.as_char_ptr(), 748eea62ffSAlice Ryhl B::get_lock_class().as_ptr(), 758eea62ffSAlice Ryhl ) 768eea62ffSAlice Ryhl } 778eea62ffSAlice Ryhl } 788eea62ffSAlice Ryhl 798eea62ffSAlice Ryhl /// Lock this global lock. lock(&'static self) -> GlobalGuard<B>808eea62ffSAlice Ryhl pub fn lock(&'static self) -> GlobalGuard<B> { 818eea62ffSAlice Ryhl GlobalGuard { 828eea62ffSAlice Ryhl inner: self.inner.lock(), 838eea62ffSAlice Ryhl } 848eea62ffSAlice Ryhl } 858eea62ffSAlice Ryhl 868eea62ffSAlice Ryhl /// Try to lock this global lock. try_lock(&'static self) -> Option<GlobalGuard<B>>878eea62ffSAlice Ryhl pub fn try_lock(&'static self) -> Option<GlobalGuard<B>> { 888eea62ffSAlice Ryhl Some(GlobalGuard { 898eea62ffSAlice Ryhl inner: self.inner.try_lock()?, 908eea62ffSAlice Ryhl }) 918eea62ffSAlice Ryhl } 928eea62ffSAlice Ryhl } 938eea62ffSAlice Ryhl 948eea62ffSAlice Ryhl /// A guard for a [`GlobalLock`]. 958eea62ffSAlice Ryhl /// 968eea62ffSAlice Ryhl /// See [`global_lock!`] for examples. 978eea62ffSAlice Ryhl pub struct GlobalGuard<B: GlobalLockBackend> { 988eea62ffSAlice Ryhl inner: Guard<'static, B::Item, B::Backend>, 998eea62ffSAlice Ryhl } 1008eea62ffSAlice Ryhl 1018eea62ffSAlice Ryhl impl<B: GlobalLockBackend> core::ops::Deref for GlobalGuard<B> { 1028eea62ffSAlice Ryhl type Target = B::Item; 1038eea62ffSAlice Ryhl deref(&self) -> &Self::Target1048eea62ffSAlice Ryhl fn deref(&self) -> &Self::Target { 1058eea62ffSAlice Ryhl &self.inner 1068eea62ffSAlice Ryhl } 1078eea62ffSAlice Ryhl } 1088eea62ffSAlice Ryhl 1098eea62ffSAlice Ryhl impl<B: GlobalLockBackend> core::ops::DerefMut for GlobalGuard<B> { deref_mut(&mut self) -> &mut Self::Target1108eea62ffSAlice Ryhl fn deref_mut(&mut self) -> &mut Self::Target { 1118eea62ffSAlice Ryhl &mut self.inner 1128eea62ffSAlice Ryhl } 1138eea62ffSAlice Ryhl } 1148eea62ffSAlice Ryhl 1158eea62ffSAlice Ryhl /// A version of [`LockedBy`] for a [`GlobalLock`]. 1168eea62ffSAlice Ryhl /// 1178eea62ffSAlice Ryhl /// See [`global_lock!`] for examples. 1188eea62ffSAlice Ryhl pub struct GlobalLockedBy<T: ?Sized, B: GlobalLockBackend> { 1198eea62ffSAlice Ryhl _backend: PhantomData<B>, 1208eea62ffSAlice Ryhl value: UnsafeCell<T>, 1218eea62ffSAlice Ryhl } 1228eea62ffSAlice Ryhl 1238eea62ffSAlice Ryhl // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLockedBy`. 1248eea62ffSAlice Ryhl unsafe impl<T, B> Send for GlobalLockedBy<T, B> 1258eea62ffSAlice Ryhl where 1268eea62ffSAlice Ryhl T: ?Sized, 1278eea62ffSAlice Ryhl B: GlobalLockBackend, 1288eea62ffSAlice Ryhl LockedBy<T, B::Item>: Send, 1298eea62ffSAlice Ryhl { 1308eea62ffSAlice Ryhl } 1318eea62ffSAlice Ryhl 1328eea62ffSAlice Ryhl // SAFETY: The same thread-safety rules as `LockedBy` apply to `GlobalLockedBy`. 1338eea62ffSAlice Ryhl unsafe impl<T, B> Sync for GlobalLockedBy<T, B> 1348eea62ffSAlice Ryhl where 1358eea62ffSAlice Ryhl T: ?Sized, 1368eea62ffSAlice Ryhl B: GlobalLockBackend, 1378eea62ffSAlice Ryhl LockedBy<T, B::Item>: Sync, 1388eea62ffSAlice Ryhl { 1398eea62ffSAlice Ryhl } 1408eea62ffSAlice Ryhl 1418eea62ffSAlice Ryhl impl<T, B: GlobalLockBackend> GlobalLockedBy<T, B> { 1428eea62ffSAlice Ryhl /// Create a new [`GlobalLockedBy`]. 1438eea62ffSAlice Ryhl /// 1448eea62ffSAlice Ryhl /// The provided value will be protected by the global lock indicated by `B`. new(val: T) -> Self1458eea62ffSAlice Ryhl pub fn new(val: T) -> Self { 1468eea62ffSAlice Ryhl Self { 1478eea62ffSAlice Ryhl value: UnsafeCell::new(val), 1488eea62ffSAlice Ryhl _backend: PhantomData, 1498eea62ffSAlice Ryhl } 1508eea62ffSAlice Ryhl } 1518eea62ffSAlice Ryhl } 1528eea62ffSAlice Ryhl 1538eea62ffSAlice Ryhl impl<T: ?Sized, B: GlobalLockBackend> GlobalLockedBy<T, B> { 1548eea62ffSAlice Ryhl /// Access the value immutably. 1558eea62ffSAlice Ryhl /// 1568eea62ffSAlice Ryhl /// The caller must prove shared access to the lock. as_ref<'a>(&'a self, _guard: &'a GlobalGuard<B>) -> &'a T1578eea62ffSAlice Ryhl pub fn as_ref<'a>(&'a self, _guard: &'a GlobalGuard<B>) -> &'a T { 1588eea62ffSAlice Ryhl // SAFETY: The lock is globally unique, so there can only be one guard. 1598eea62ffSAlice Ryhl unsafe { &*self.value.get() } 1608eea62ffSAlice Ryhl } 1618eea62ffSAlice Ryhl 1628eea62ffSAlice Ryhl /// Access the value mutably. 1638eea62ffSAlice Ryhl /// 1648eea62ffSAlice Ryhl /// The caller must prove shared exclusive to the lock. as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<B>) -> &'a mut T1658eea62ffSAlice Ryhl pub fn as_mut<'a>(&'a self, _guard: &'a mut GlobalGuard<B>) -> &'a mut T { 1668eea62ffSAlice Ryhl // SAFETY: The lock is globally unique, so there can only be one guard. 1678eea62ffSAlice Ryhl unsafe { &mut *self.value.get() } 1688eea62ffSAlice Ryhl } 1698eea62ffSAlice Ryhl 1708eea62ffSAlice Ryhl /// Access the value mutably directly. 1718eea62ffSAlice Ryhl /// 1728eea62ffSAlice Ryhl /// The caller has exclusive access to this `GlobalLockedBy`, so they do not need to hold the 1738eea62ffSAlice Ryhl /// lock. get_mut(&mut self) -> &mut T1748eea62ffSAlice Ryhl pub fn get_mut(&mut self) -> &mut T { 1758eea62ffSAlice Ryhl self.value.get_mut() 1768eea62ffSAlice Ryhl } 1778eea62ffSAlice Ryhl } 1788eea62ffSAlice Ryhl 1798eea62ffSAlice Ryhl /// Defines a global lock. 1808eea62ffSAlice Ryhl /// 1818eea62ffSAlice Ryhl /// The global mutex must be initialized before first use. Usually this is done by calling 1828eea62ffSAlice Ryhl /// [`GlobalLock::init`] in the module initializer. 1838eea62ffSAlice Ryhl /// 1848eea62ffSAlice Ryhl /// # Examples 1858eea62ffSAlice Ryhl /// 1868eea62ffSAlice Ryhl /// A global counter: 1878eea62ffSAlice Ryhl /// 1888eea62ffSAlice Ryhl /// ``` 1898eea62ffSAlice Ryhl /// # mod ex { 1908eea62ffSAlice Ryhl /// # use kernel::prelude::*; 1918eea62ffSAlice Ryhl /// kernel::sync::global_lock! { 1928eea62ffSAlice Ryhl /// // SAFETY: Initialized in module initializer before first use. 1938eea62ffSAlice Ryhl /// unsafe(uninit) static MY_COUNTER: Mutex<u32> = 0; 1948eea62ffSAlice Ryhl /// } 1958eea62ffSAlice Ryhl /// 1968eea62ffSAlice Ryhl /// fn increment_counter() -> u32 { 1978eea62ffSAlice Ryhl /// let mut guard = MY_COUNTER.lock(); 1988eea62ffSAlice Ryhl /// *guard += 1; 1998eea62ffSAlice Ryhl /// *guard 2008eea62ffSAlice Ryhl /// } 2018eea62ffSAlice Ryhl /// 2028eea62ffSAlice Ryhl /// impl kernel::Module for MyModule { 2038eea62ffSAlice Ryhl /// fn init(_module: &'static ThisModule) -> Result<Self> { 2048eea62ffSAlice Ryhl /// // SAFETY: Called exactly once. 2058eea62ffSAlice Ryhl /// unsafe { MY_COUNTER.init() }; 2068eea62ffSAlice Ryhl /// 2078eea62ffSAlice Ryhl /// Ok(MyModule {}) 2088eea62ffSAlice Ryhl /// } 2098eea62ffSAlice Ryhl /// } 2108eea62ffSAlice Ryhl /// # struct MyModule {} 2118eea62ffSAlice Ryhl /// # } 2128eea62ffSAlice Ryhl /// ``` 2138eea62ffSAlice Ryhl /// 2148eea62ffSAlice Ryhl /// A global mutex used to protect all instances of a given struct: 2158eea62ffSAlice Ryhl /// 2168eea62ffSAlice Ryhl /// ``` 2178eea62ffSAlice Ryhl /// # mod ex { 2188eea62ffSAlice Ryhl /// # use kernel::prelude::*; 2198eea62ffSAlice Ryhl /// use kernel::sync::{GlobalGuard, GlobalLockedBy}; 2208eea62ffSAlice Ryhl /// 2218eea62ffSAlice Ryhl /// kernel::sync::global_lock! { 2228eea62ffSAlice Ryhl /// // SAFETY: Initialized in module initializer before first use. 2238eea62ffSAlice Ryhl /// unsafe(uninit) static MY_MUTEX: Mutex<()> = (); 2248eea62ffSAlice Ryhl /// } 2258eea62ffSAlice Ryhl /// 2268eea62ffSAlice Ryhl /// /// All instances of this struct are protected by `MY_MUTEX`. 2278eea62ffSAlice Ryhl /// struct MyStruct { 2288eea62ffSAlice Ryhl /// my_counter: GlobalLockedBy<u32, MY_MUTEX>, 2298eea62ffSAlice Ryhl /// } 2308eea62ffSAlice Ryhl /// 2318eea62ffSAlice Ryhl /// impl MyStruct { 2328eea62ffSAlice Ryhl /// /// Increment the counter in this instance. 2338eea62ffSAlice Ryhl /// /// 2348eea62ffSAlice Ryhl /// /// The caller must hold the `MY_MUTEX` mutex. 2358eea62ffSAlice Ryhl /// fn increment(&self, guard: &mut GlobalGuard<MY_MUTEX>) -> u32 { 2368eea62ffSAlice Ryhl /// let my_counter = self.my_counter.as_mut(guard); 2378eea62ffSAlice Ryhl /// *my_counter += 1; 2388eea62ffSAlice Ryhl /// *my_counter 2398eea62ffSAlice Ryhl /// } 2408eea62ffSAlice Ryhl /// } 2418eea62ffSAlice Ryhl /// 2428eea62ffSAlice Ryhl /// impl kernel::Module for MyModule { 2438eea62ffSAlice Ryhl /// fn init(_module: &'static ThisModule) -> Result<Self> { 2448eea62ffSAlice Ryhl /// // SAFETY: Called exactly once. 2458eea62ffSAlice Ryhl /// unsafe { MY_MUTEX.init() }; 2468eea62ffSAlice Ryhl /// 2478eea62ffSAlice Ryhl /// Ok(MyModule {}) 2488eea62ffSAlice Ryhl /// } 2498eea62ffSAlice Ryhl /// } 2508eea62ffSAlice Ryhl /// # struct MyModule {} 2518eea62ffSAlice Ryhl /// # } 2528eea62ffSAlice Ryhl /// ``` 2538eea62ffSAlice Ryhl #[macro_export] 2548eea62ffSAlice Ryhl macro_rules! global_lock { 2558eea62ffSAlice Ryhl { 2568eea62ffSAlice Ryhl $(#[$meta:meta])* $pub:vis 2578eea62ffSAlice Ryhl unsafe(uninit) static $name:ident: $kind:ident<$valuety:ty> = $value:expr; 2588eea62ffSAlice Ryhl } => { 2598eea62ffSAlice Ryhl #[doc = ::core::concat!( 2608eea62ffSAlice Ryhl "Backend type used by [`", 2618eea62ffSAlice Ryhl ::core::stringify!($name), 2628eea62ffSAlice Ryhl "`](static@", 2638eea62ffSAlice Ryhl ::core::stringify!($name), 2648eea62ffSAlice Ryhl ")." 2658eea62ffSAlice Ryhl )] 2668eea62ffSAlice Ryhl #[allow(non_camel_case_types, unreachable_pub)] 2678eea62ffSAlice Ryhl $pub enum $name {} 2688eea62ffSAlice Ryhl 2698eea62ffSAlice Ryhl impl $crate::sync::lock::GlobalLockBackend for $name { 2708eea62ffSAlice Ryhl const NAME: &'static $crate::str::CStr = $crate::c_str!(::core::stringify!($name)); 2718eea62ffSAlice Ryhl type Item = $valuety; 2728eea62ffSAlice Ryhl type Backend = $crate::global_lock_inner!(backend $kind); 2738eea62ffSAlice Ryhl 274*f73ca66fSMitchell Levy fn get_lock_class() -> Pin<&'static $crate::sync::LockClassKey> { 2758eea62ffSAlice Ryhl $crate::static_lock_class!() 2768eea62ffSAlice Ryhl } 2778eea62ffSAlice Ryhl } 2788eea62ffSAlice Ryhl 2798eea62ffSAlice Ryhl $(#[$meta])* 2808eea62ffSAlice Ryhl $pub static $name: $crate::sync::lock::GlobalLock<$name> = { 2818eea62ffSAlice Ryhl // Defined here to be outside the unsafe scope. 2828eea62ffSAlice Ryhl let init: $valuety = $value; 2838eea62ffSAlice Ryhl 2848eea62ffSAlice Ryhl // SAFETY: 2858eea62ffSAlice Ryhl // * The user of this macro promises to initialize the macro before use. 2868eea62ffSAlice Ryhl // * We are only generating one static with this backend type. 2878eea62ffSAlice Ryhl unsafe { $crate::sync::lock::GlobalLock::new(init) } 2888eea62ffSAlice Ryhl }; 2898eea62ffSAlice Ryhl }; 2908eea62ffSAlice Ryhl } 2918eea62ffSAlice Ryhl pub use global_lock; 2928eea62ffSAlice Ryhl 2938eea62ffSAlice Ryhl #[doc(hidden)] 2948eea62ffSAlice Ryhl #[macro_export] 2958eea62ffSAlice Ryhl macro_rules! global_lock_inner { 2968eea62ffSAlice Ryhl (backend Mutex) => { 2978eea62ffSAlice Ryhl $crate::sync::lock::mutex::MutexBackend 2988eea62ffSAlice Ryhl }; 2998eea62ffSAlice Ryhl (backend SpinLock) => { 3008eea62ffSAlice Ryhl $crate::sync::lock::spinlock::SpinLockBackend 3018eea62ffSAlice Ryhl }; 3028eea62ffSAlice Ryhl } 303