1 // SPDX-License-Identifier: GPL-2.0 2 3 //! A kernel spinlock. 4 //! 5 //! This module allows Rust code to use the kernel's `spinlock_t`. 6 use super::*; 7 use crate::prelude::*; 8 9 /// Creates a [`SpinLock`] initialiser with the given name and a newly-created lock class. 10 /// 11 /// It uses the name if one is given, otherwise it generates one based on the file name and line 12 /// number. 13 #[macro_export] 14 macro_rules! new_spinlock { 15 ($inner:expr $(, $name:literal)? $(,)?) => { 16 $crate::sync::SpinLock::new( 17 $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!()) 18 }; 19 } 20 pub use new_spinlock; 21 22 /// A spinlock. 23 /// 24 /// Exposes the kernel's [`spinlock_t`]. When multiple CPUs attempt to lock the same spinlock, only 25 /// one at a time is allowed to progress, the others will block (spinning) until the spinlock is 26 /// unlocked, at which point another CPU will be allowed to make progress. 27 /// 28 /// Instances of [`SpinLock`] need a lock class and to be pinned. The recommended way to create such 29 /// instances is with the [`pin_init`](pin_init::pin_init) and [`new_spinlock`] macros. 30 /// 31 /// # Examples 32 /// 33 /// The following example shows how to declare, allocate and initialise a struct (`Example`) that 34 /// contains an inner struct (`Inner`) that is protected by a spinlock. 35 /// 36 /// ``` 37 /// use kernel::sync::{new_spinlock, SpinLock}; 38 /// 39 /// struct Inner { 40 /// a: u32, 41 /// b: u32, 42 /// } 43 /// 44 /// #[pin_data] 45 /// struct Example { 46 /// c: u32, 47 /// #[pin] 48 /// d: SpinLock<Inner>, 49 /// } 50 /// 51 /// impl Example { 52 /// fn new() -> impl PinInit<Self> { 53 /// pin_init!(Self { 54 /// c: 10, 55 /// d <- new_spinlock!(Inner { a: 20, b: 30 }), 56 /// }) 57 /// } 58 /// } 59 /// 60 /// // Allocate a boxed `Example`. 61 /// let e = KBox::pin_init(Example::new(), GFP_KERNEL)?; 62 /// assert_eq!(e.c, 10); 63 /// assert_eq!(e.d.lock().a, 20); 64 /// assert_eq!(e.d.lock().b, 30); 65 /// # Ok::<(), Error>(()) 66 /// ``` 67 /// 68 /// The following example shows how to use interior mutability to modify the contents of a struct 69 /// protected by a spinlock despite only having a shared reference: 70 /// 71 /// ``` 72 /// use kernel::sync::SpinLock; 73 /// 74 /// struct Example { 75 /// a: u32, 76 /// b: u32, 77 /// } 78 /// 79 /// fn example(m: &SpinLock<Example>) { 80 /// let mut guard = m.lock(); 81 /// guard.a += 10; 82 /// guard.b += 20; 83 /// } 84 /// ``` 85 /// 86 /// [`spinlock_t`]: srctree/include/linux/spinlock.h 87 pub type SpinLock<T> = Lock<T, SpinLockBackend>; 88 89 /// A kernel `spinlock_t` lock backend. 90 pub struct SpinLockBackend; 91 92 /// A [`Guard`] acquired from locking a [`SpinLock`]. 93 /// 94 /// This is simply a type alias for a [`Guard`] returned from locking a [`SpinLock`]. It will unlock 95 /// the [`SpinLock`] upon being dropped. 96 pub type SpinLockGuard<'a, T> = Guard<'a, T, SpinLockBackend>; 97 98 // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. `relock` uses the 99 // default implementation that always calls the same locking method. 100 unsafe impl Backend for SpinLockBackend { 101 type State = bindings::spinlock_t; 102 type GuardState = (); 103 104 #[inline] 105 unsafe fn init( 106 ptr: *mut Self::State, 107 name: *const crate::ffi::c_char, 108 key: *mut bindings::lock_class_key, 109 ) { 110 // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and 111 // `key` are valid for read indefinitely. 112 unsafe { bindings::__spin_lock_init(ptr, name, key) } 113 } 114 115 #[inline] 116 unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { 117 // SAFETY: The safety requirements of this function ensure that `ptr` points to valid 118 // memory, and that it has been initialised before. 119 unsafe { bindings::spin_lock(ptr) } 120 } 121 122 #[inline] 123 unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { 124 // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the 125 // caller is the owner of the spinlock. 126 unsafe { bindings::spin_unlock(ptr) } 127 } 128 129 #[inline] 130 unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> { 131 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 132 let result = unsafe { bindings::spin_trylock(ptr) }; 133 134 if result != 0 { 135 Some(()) 136 } else { 137 None 138 } 139 } 140 141 #[inline] 142 unsafe fn assert_is_held(ptr: *mut Self::State) { 143 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 144 unsafe { bindings::spin_assert_is_held(ptr) } 145 } 146 } 147 148 /// Creates a [`SpinLockIrq`] initialiser with the given name and a newly-created lock class. 149 /// 150 /// It uses the name if one is given, otherwise it generates one based on the file name and line 151 /// number. 152 #[macro_export] 153 macro_rules! new_spinlock_irq { 154 ($inner:expr $(, $name:literal)? $(,)?) => { 155 $crate::sync::SpinLockIrq::new( 156 $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!()) 157 }; 158 } 159 pub use new_spinlock_irq; 160 161 /// A variant of `SpinLock` that ensures interrupts are disabled in the critical section. 162 /// 163 /// For more info on spinlocks, see [`SpinLock`]. For more information on interrupts, 164 /// [see the interrupt module](kernel::interrupt). 165 /// 166 /// # Examples 167 /// 168 /// The following example shows how to declare, allocate initialise and access a struct (`Example`) 169 /// that contains an inner struct (`Inner`) that is protected by a spinlock that requires local 170 /// processor interrupts to be disabled. 171 /// 172 /// ``` 173 /// use kernel::sync::{new_spinlock_irq, SpinLockIrq}; 174 /// 175 /// struct Inner { 176 /// a: u32, 177 /// b: u32, 178 /// } 179 /// 180 /// #[pin_data] 181 /// struct Example { 182 /// #[pin] 183 /// c: SpinLockIrq<Inner>, 184 /// #[pin] 185 /// d: SpinLockIrq<Inner>, 186 /// } 187 /// 188 /// impl Example { 189 /// fn new() -> impl PinInit<Self> { 190 /// pin_init!(Self { 191 /// c <- new_spinlock_irq!(Inner { a: 0, b: 10 }), 192 /// d <- new_spinlock_irq!(Inner { a: 20, b: 30 }), 193 /// }) 194 /// } 195 /// } 196 /// 197 /// // Allocate a boxed `Example` 198 /// let e = KBox::pin_init(Example::new(), GFP_KERNEL)?; 199 /// 200 /// // Accessing an `Example` from a context where interrupts may not be disabled already. 201 /// let c_guard = e.c.lock(); // interrupts are disabled now, +1 interrupt disable refcount 202 /// let d_guard = e.d.lock(); // no interrupt state change, +1 interrupt disable refcount 203 /// 204 /// assert_eq!(c_guard.a, 0); 205 /// assert_eq!(c_guard.b, 10); 206 /// assert_eq!(d_guard.a, 20); 207 /// assert_eq!(d_guard.b, 30); 208 /// 209 /// drop(c_guard); // Dropping c_guard will not re-enable interrupts just yet, since d_guard is 210 /// // still in scope. 211 /// drop(d_guard); // Last interrupt disable reference dropped here, so interrupts are re-enabled 212 /// // now 213 /// # Ok::<(), Error>(()) 214 /// ``` 215 /// 216 /// [`lock()`]: SpinLockIrq::lock 217 pub type SpinLockIrq<T> = super::Lock<T, SpinLockIrqBackend>; 218 219 /// A kernel `spinlock_t` lock backend that can only be acquired in interrupt disabled contexts. 220 pub struct SpinLockIrqBackend; 221 222 /// A [`Guard`] acquired from locking a [`SpinLockIrq`] using [`lock()`]. 223 /// 224 /// This is simply a type alias for a [`Guard`] returned from locking a [`SpinLockIrq`] using 225 /// [`lock()`]. It will unlock the [`SpinLockIrq`] and decrement the local processor's interrupt 226 /// disablement refcount upon being dropped. 227 /// 228 /// [`lock()`]: SpinLockIrq::lock 229 pub type SpinLockIrqGuard<'a, T> = Guard<'a, T, SpinLockIrqBackend>; 230 231 // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. `relock` uses the 232 // default implementation that always calls the same locking method. 233 unsafe impl Backend for SpinLockIrqBackend { 234 type State = bindings::spinlock_t; 235 type GuardState = (); 236 237 #[inline] 238 unsafe fn init( 239 ptr: *mut Self::State, 240 name: *const crate::ffi::c_char, 241 key: *mut bindings::lock_class_key, 242 ) { 243 // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and 244 // `key` are valid for read indefinitely. 245 unsafe { bindings::__spin_lock_init(ptr, name, key) } 246 } 247 248 #[inline] 249 unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { 250 // SAFETY: The safety requirements of this function ensure that `ptr` points to valid 251 // memory, and that it has been initialised before. 252 unsafe { bindings::spin_lock_irq_disable(ptr) } 253 } 254 255 #[inline] 256 unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { 257 // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the 258 // caller is the owner of the spinlock. 259 unsafe { bindings::spin_unlock_irq_enable(ptr) } 260 } 261 262 #[inline] 263 unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> { 264 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 265 let result = unsafe { bindings::spin_trylock_irq_disable(ptr) }; 266 267 if result != 0 { 268 Some(()) 269 } else { 270 None 271 } 272 } 273 274 #[inline] 275 unsafe fn assert_is_held(ptr: *mut Self::State) { 276 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 277 unsafe { bindings::spin_assert_is_held(ptr) } 278 } 279 } 280 281 #[kunit_tests(rust_spinlock_irq_condvar)] 282 mod tests { 283 use super::*; 284 use crate::{ 285 sync::*, 286 workqueue::{ 287 self, 288 impl_has_work, 289 new_work, 290 Work, 291 WorkItem, // 292 }, 293 }; 294 295 struct TestState { 296 value: u32, 297 waiter_ready: bool, 298 } 299 300 #[pin_data] 301 struct Test { 302 #[pin] 303 state: SpinLockIrq<TestState>, 304 305 #[pin] 306 state_changed: CondVar, 307 308 #[pin] 309 waiter_state_changed: CondVar, 310 311 #[pin] 312 wait_work: Work<Self>, 313 } 314 315 impl_has_work! { 316 impl HasWork<Self> for Test { self.wait_work } 317 } 318 319 impl Test { 320 pub(crate) fn new() -> Result<Arc<Self>> { 321 Arc::try_pin_init( 322 try_pin_init!( 323 Self { 324 state <- new_spinlock_irq!(TestState { 325 value: 1, 326 waiter_ready: false 327 }), 328 state_changed <- new_condvar!(), 329 waiter_state_changed <- new_condvar!(), 330 wait_work <- new_work!("IrqCondvarTest::wait_work") 331 } 332 ), 333 GFP_KERNEL, 334 ) 335 } 336 } 337 338 impl WorkItem for Test { 339 type Pointer = Arc<Self>; 340 341 fn run(this: Arc<Self>) { 342 // Wait for the test to be ready to wait for us 343 let mut state = this.state.lock(); 344 345 // Make sure the interrupts actually turned off 346 // SAFETY: It's always safe to call `lockdep_assert_irqs_disabled()` 347 unsafe { bindings::lockdep_assert_irqs_disabled() }; 348 349 while !state.waiter_ready { 350 this.waiter_state_changed.wait(&mut state); 351 } 352 353 // Deliver the exciting value update our test has been waiting for 354 state.value += 1; 355 this.state_changed.notify_sync(); 356 } 357 } 358 359 #[test] 360 fn spinlock_irq_condvar() -> Result { 361 let testdata = Test::new()?; 362 363 let _ = workqueue::system().enqueue(testdata.clone()); 364 365 // Let the updater know when we're ready to wait 366 let mut state = testdata.state.lock(); 367 state.waiter_ready = true; 368 testdata.waiter_state_changed.notify_sync(); 369 370 // Wait for the exciting value update 371 testdata.state_changed.wait(&mut state); 372 assert_eq!(state.value, 2); 373 Ok(()) 374 } 375 } 376