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