spinlock.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! A kernel spinlock.
  3. //!
  4. //! This module allows Rust code to use the kernel's `spinlock_t`.
  5. /// Creates a [`SpinLock`] initialiser with the given name and a newly-created lock class.
  6. ///
  7. /// It uses the name if one is given, otherwise it generates one based on the file name and line
  8. /// number.
  9. #[macro_export]
  10. macro_rules! new_spinlock {
  11. ($inner:expr $(, $name:literal)? $(,)?) => {
  12. $crate::sync::SpinLock::new(
  13. $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!())
  14. };
  15. }
  16. pub use new_spinlock;
  17. /// A spinlock.
  18. ///
  19. /// Exposes the kernel's [`spinlock_t`]. When multiple CPUs attempt to lock the same spinlock, only
  20. /// one at a time is allowed to progress, the others will block (spinning) until the spinlock is
  21. /// unlocked, at which point another CPU will be allowed to make progress.
  22. ///
  23. /// Instances of [`SpinLock`] need a lock class and to be pinned. The recommended way to create such
  24. /// instances is with the [`pin_init`](crate::pin_init) and [`new_spinlock`] macros.
  25. ///
  26. /// # Examples
  27. ///
  28. /// The following example shows how to declare, allocate and initialise a struct (`Example`) that
  29. /// contains an inner struct (`Inner`) that is protected by a spinlock.
  30. ///
  31. /// ```
  32. /// use kernel::sync::{new_spinlock, SpinLock};
  33. ///
  34. /// struct Inner {
  35. /// a: u32,
  36. /// b: u32,
  37. /// }
  38. ///
  39. /// #[pin_data]
  40. /// struct Example {
  41. /// c: u32,
  42. /// #[pin]
  43. /// d: SpinLock<Inner>,
  44. /// }
  45. ///
  46. /// impl Example {
  47. /// fn new() -> impl PinInit<Self> {
  48. /// pin_init!(Self {
  49. /// c: 10,
  50. /// d <- new_spinlock!(Inner { a: 20, b: 30 }),
  51. /// })
  52. /// }
  53. /// }
  54. ///
  55. /// // Allocate a boxed `Example`.
  56. /// let e = KBox::pin_init(Example::new(), GFP_KERNEL)?;
  57. /// assert_eq!(e.c, 10);
  58. /// assert_eq!(e.d.lock().a, 20);
  59. /// assert_eq!(e.d.lock().b, 30);
  60. /// # Ok::<(), Error>(())
  61. /// ```
  62. ///
  63. /// The following example shows how to use interior mutability to modify the contents of a struct
  64. /// protected by a spinlock despite only having a shared reference:
  65. ///
  66. /// ```
  67. /// use kernel::sync::SpinLock;
  68. ///
  69. /// struct Example {
  70. /// a: u32,
  71. /// b: u32,
  72. /// }
  73. ///
  74. /// fn example(m: &SpinLock<Example>) {
  75. /// let mut guard = m.lock();
  76. /// guard.a += 10;
  77. /// guard.b += 20;
  78. /// }
  79. /// ```
  80. ///
  81. /// [`spinlock_t`]: srctree/include/linux/spinlock.h
  82. pub type SpinLock<T> = super::Lock<T, SpinLockBackend>;
  83. /// A kernel `spinlock_t` lock backend.
  84. pub struct SpinLockBackend;
  85. // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. `relock` uses the
  86. // default implementation that always calls the same locking method.
  87. unsafe impl super::Backend for SpinLockBackend {
  88. type State = bindings::spinlock_t;
  89. type GuardState = ();
  90. unsafe fn init(
  91. ptr: *mut Self::State,
  92. name: *const crate::ffi::c_char,
  93. key: *mut bindings::lock_class_key,
  94. ) {
  95. // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and
  96. // `key` are valid for read indefinitely.
  97. unsafe { bindings::__spin_lock_init(ptr, name, key) }
  98. }
  99. unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState {
  100. // SAFETY: The safety requirements of this function ensure that `ptr` points to valid
  101. // memory, and that it has been initialised before.
  102. unsafe { bindings::spin_lock(ptr) }
  103. }
  104. unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) {
  105. // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the
  106. // caller is the owner of the spinlock.
  107. unsafe { bindings::spin_unlock(ptr) }
  108. }
  109. }