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