FILE
mutex.rs
File preview with syntax highlighting.
linux-6.19.14/rust/kernel/sync/lock/mutex.rs
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 7/// Creates a [`Mutex`] initialiser with the given name and a newly-created lock class. 8/// 9/// It uses the name if one is given, otherwise it generates one based on the file name and line 10/// number. 11#[macro_export] 12macro_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} 18pub 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 87pub 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 95pub type MutexGuard<'a, T> = super::Guard<'a, T, MutexBackend>; 96 97/// A kernel `struct mutex` lock backend. 98pub struct MutexBackend; 99 100// SAFETY: The underlying kernel `struct mutex` object ensures mutual exclusion. 101unsafe impl super::Backend for MutexBackend { 102 type State = bindings::mutex; 103 type GuardState = (); 104 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::__mutex_init(ptr, name, key) } 113 } 114 115 unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { 116 // SAFETY: The safety requirements of this function ensure that `ptr` points to valid 117 // memory, and that it has been initialised before. 118 unsafe { bindings::mutex_lock(ptr) }; 119 } 120 121 unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { 122 // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the 123 // caller is the owner of the mutex. 124 unsafe { bindings::mutex_unlock(ptr) }; 125 } 126 127 unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> { 128 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 129 let result = unsafe { bindings::mutex_trylock(ptr) }; 130 131 if result != 0 { 132 Some(()) 133 } else { 134 None 135 } 136 } 137 138 unsafe fn assert_is_held(ptr: *mut Self::State) { 139 // SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use. 140 unsafe { bindings::mutex_assert_is_held(ptr) } 141 } 142}
~/
Read-only file preview.