| 1 | |
| 2 |
|
| 3 | |
| 4 | |
| 5 | |
| 6 |
|
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | #[macro_export]
|
| 12 | macro_rules! new_mutex {
|
| 13 | ($inner:expr $(, $name:literal)? $(,)?) => {
|
| 14 | $crate::sync::Mutex::new(
|
| 15 | $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!())
|
| 16 | };
|
| 17 | }
|
| 18 | pub use new_mutex;
|
| 19 |
|
| 20 | /// A mutual exclusion primitive.
|
| 21 | ///
|
| 22 | /// Exposes the kernel's [`struct mutex`]. When multiple threads attempt to lock the same mutex,
|
| 23 | /// only one at a time is allowed to progress, the others will block (sleep) until the mutex is
|
| 24 | /// unlocked, at which point another thread will be allowed to wake up and make progress.
|
| 25 | ///
|
| 26 | /// Since it may block, [`Mutex`] needs to be used with care in atomic contexts.
|
| 27 | ///
|
| 28 | /// Instances of [`Mutex`] 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_mutex`] 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 mutex.
|
| 35 | ///
|
| 36 | /// ```
|
| 37 | /// use kernel::sync::{new_mutex, Mutex};
|
| 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: Mutex<Inner>,
|
| 49 | /// }
|
| 50 | ///
|
| 51 | /// impl Example {
|
| 52 | /// fn new() -> impl PinInit<Self> {
|
| 53 | /// pin_init!(Self {
|
| 54 | /// c: 10,
|
| 55 | /// d <- new_mutex!(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 mutex despite only having a shared reference:
|
| 70 | ///
|
| 71 | /// ```
|
| 72 | /// use kernel::sync::Mutex;
|
| 73 | ///
|
| 74 | /// struct Example {
|
| 75 | /// a: u32,
|
| 76 | /// b: u32,
|
| 77 | /// }
|
| 78 | ///
|
| 79 | /// fn example(m: &Mutex<Example>) {
|
| 80 | /// let mut guard = m.lock();
|
| 81 | /// guard.a += 10;
|
| 82 | /// guard.b += 20;
|
| 83 | /// }
|
| 84 | /// ```
|
| 85 | ///
|
| 86 | /// [`struct mutex`]: srctree/include/linux/mutex.h
|
| 87 | pub type Mutex<T> = super::Lock<T, MutexBackend>;
|
| 88 |
|
| 89 | /// A [`Guard`] acquired from locking a [`Mutex`].
|
| 90 | ///
|
| 91 | /// This is simply a type alias for a [`Guard`] returned from locking a [`Mutex`]. It will unlock
|
| 92 | /// the [`Mutex`] upon being dropped.
|
| 93 | ///
|
| 94 | /// [`Guard`]: super::Guard
|
| 95 | pub type MutexGuard<'a, T> = super::Guard<'a, T, MutexBackend>;
|
| 96 |
|
| 97 | /// A kernel `struct mutex` lock backend.
|
| 98 | pub struct MutexBackend;
|
| 99 |
|
| 100 | // SAFETY: The underlying kernel `struct mutex` object ensures mutual exclusion.
|
| 101 | unsafe impl super::Backend for MutexBackend {
|
| 102 | type State = bindings::mutex;
|
| 103 | type GuardState = ();
|
| 104 |
|
| 105 | #[inline]
|
| 106 | unsafe fn init(
|
| 107 | ptr: *mut Self::State,
|
| 108 | name: *const crate::ffi::c_char,
|
| 109 | key: *mut bindings::lock_class_key,
|
| 110 | ) {
|
| 111 | // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and
|
| 112 | // `key` are valid for read indefinitely.
|
| 113 | unsafe { bindings::__mutex_init(ptr, name, key) }
|
| 114 | }
|
| 115 |
|
| 116 | #[inline]
|
| 117 | unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState {
|
| 118 | // SAFETY: The safety requirements of this function ensure that `ptr` points to valid
|
| 119 | // memory, and that it has been initialised before.
|
| 120 | unsafe { bindings::mutex_lock(ptr) };
|
| 121 | }
|
| 122 |
|
| 123 | #[inline]
|
| 124 | unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) {
|
| 125 | // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the
|
| 126 | // caller is the owner of the mutex.
|
| 127 | unsafe { bindings::mutex_unlock(ptr) };
|
| 128 | }
|
| 129 |
|
| 130 | #[inline]
|
| 131 | unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> {
|
| 132 | // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
|
| 133 | let result = unsafe { bindings::mutex_trylock(ptr) };
|
| 134 |
|
| 135 | if result != 0 {
|
| 136 | Some(())
|
| 137 | } else {
|
| 138 | None
|
| 139 | }
|
| 140 | }
|
| 141 |
|
| 142 | #[inline]
|
| 143 | unsafe fn assert_is_held(ptr: *mut Self::State) {
|
| 144 | // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
|
| 145 | unsafe { bindings::mutex_assert_is_held(ptr) }
|
| 146 | }
|
| 147 | }
|