Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3//! A kernel mutex.
  4//!
  5//! This module allows Rust code to use the kernel's `struct mutex`.
  6
  7use crate::bindings;
  8
  9/// Creates a [`Mutex`] 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]
 14macro_rules! new_mutex {
 15    ($inner:expr $(, $name:literal)? $(,)?) => {
 16        $crate::sync::Mutex::new(
 17            $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!())
 18    };
 19}
 20
 21/// A mutual exclusion primitive.
 22///
 23/// Exposes the kernel's [`struct mutex`]. When multiple threads attempt to lock the same mutex,
 24/// only one at a time is allowed to progress, the others will block (sleep) until the mutex is
 25/// unlocked, at which point another thread will be allowed to wake up and make progress.
 26///
 27/// Since it may block, [`Mutex`] needs to be used with care in atomic contexts.
 28///
 29/// Instances of [`Mutex`] need a lock class and to be pinned. The recommended way to create such
 30/// instances is with the [`pin_init`](crate::pin_init) and [`new_mutex`] macros.
 31///
 32/// # Examples
 33///
 34/// The following example shows how to declare, allocate and initialise a struct (`Example`) that
 35/// contains an inner struct (`Inner`) that is protected by a mutex.
 36///
 37/// ```
 38/// use kernel::{init::InPlaceInit, init::PinInit, new_mutex, pin_init, sync::Mutex};
 39///
 40/// struct Inner {
 41///     a: u32,
 42///     b: u32,
 43/// }
 44///
 45/// #[pin_data]
 46/// struct Example {
 47///     c: u32,
 48///     #[pin]
 49///     d: Mutex<Inner>,
 50/// }
 51///
 52/// impl Example {
 53///     fn new() -> impl PinInit<Self> {
 54///         pin_init!(Self {
 55///             c: 10,
 56///             d <- new_mutex!(Inner { a: 20, b: 30 }),
 57///         })
 58///     }
 59/// }
 60///
 61/// // Allocate a boxed `Example`.
 62/// let e = Box::pin_init(Example::new())?;
 63/// assert_eq!(e.c, 10);
 64/// assert_eq!(e.d.lock().a, 20);
 65/// assert_eq!(e.d.lock().b, 30);
 66/// # Ok::<(), Error>(())
 67/// ```
 68///
 69/// The following example shows how to use interior mutability to modify the contents of a struct
 70/// protected by a mutex despite only having a shared reference:
 71///
 72/// ```
 73/// use kernel::sync::Mutex;
 74///
 75/// struct Example {
 76///     a: u32,
 77///     b: u32,
 78/// }
 79///
 80/// fn example(m: &Mutex<Example>) {
 81///     let mut guard = m.lock();
 82///     guard.a += 10;
 83///     guard.b += 20;
 84/// }
 85/// ```
 86///
 87/// [`struct mutex`]: srctree/include/linux/mutex.h
 88pub type Mutex<T> = super::Lock<T, MutexBackend>;
 89
 90/// A kernel `struct mutex` lock backend.
 91pub struct MutexBackend;
 92
 93// SAFETY: The underlying kernel `struct mutex` object ensures mutual exclusion.
 94unsafe impl super::Backend for MutexBackend {
 95    type State = bindings::mutex;
 96    type GuardState = ();
 97
 98    unsafe fn init(
 99        ptr: *mut Self::State,
100        name: *const core::ffi::c_char,
101        key: *mut bindings::lock_class_key,
102    ) {
103        // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and
104        // `key` are valid for read indefinitely.
105        unsafe { bindings::__mutex_init(ptr, name, key) }
106    }
107
108    unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState {
109        // SAFETY: The safety requirements of this function ensure that `ptr` points to valid
110        // memory, and that it has been initialised before.
111        unsafe { bindings::mutex_lock(ptr) };
112    }
113
114    unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) {
115        // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the
116        // caller is the owner of the mutex.
117        unsafe { bindings::mutex_unlock(ptr) };
118    }
119}