16d20d629SWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 26d20d629SWedson Almeida Filho 36d20d629SWedson Almeida Filho //! A kernel mutex. 46d20d629SWedson Almeida Filho //! 56d20d629SWedson Almeida Filho //! This module allows Rust code to use the kernel's `struct mutex`. 66d20d629SWedson Almeida Filho 76d20d629SWedson Almeida Filho /// Creates a [`Mutex`] initialiser with the given name and a newly-created lock class. 86d20d629SWedson Almeida Filho /// 96d20d629SWedson Almeida Filho /// It uses the name if one is given, otherwise it generates one based on the file name and line 106d20d629SWedson Almeida Filho /// number. 116d20d629SWedson Almeida Filho #[macro_export] 126d20d629SWedson Almeida Filho macro_rules! new_mutex { 136d20d629SWedson Almeida Filho ($inner:expr $(, $name:literal)? $(,)?) => { 146d20d629SWedson Almeida Filho $crate::sync::Mutex::new( 156d20d629SWedson Almeida Filho $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!()) 166d20d629SWedson Almeida Filho }; 176d20d629SWedson Almeida Filho } 18e283ee23SAlice Ryhl pub use new_mutex; 196d20d629SWedson Almeida Filho 206d20d629SWedson Almeida Filho /// A mutual exclusion primitive. 216d20d629SWedson Almeida Filho /// 226d20d629SWedson Almeida Filho /// Exposes the kernel's [`struct mutex`]. When multiple threads attempt to lock the same mutex, 236d20d629SWedson Almeida Filho /// only one at a time is allowed to progress, the others will block (sleep) until the mutex is 246d20d629SWedson Almeida Filho /// unlocked, at which point another thread will be allowed to wake up and make progress. 256d20d629SWedson Almeida Filho /// 266d20d629SWedson Almeida Filho /// Since it may block, [`Mutex`] needs to be used with care in atomic contexts. 276d20d629SWedson Almeida Filho /// 286d20d629SWedson Almeida Filho /// Instances of [`Mutex`] need a lock class and to be pinned. The recommended way to create such 296d20d629SWedson Almeida Filho /// instances is with the [`pin_init`](crate::pin_init) and [`new_mutex`] macros. 306d20d629SWedson Almeida Filho /// 316d20d629SWedson Almeida Filho /// # Examples 326d20d629SWedson Almeida Filho /// 336d20d629SWedson Almeida Filho /// The following example shows how to declare, allocate and initialise a struct (`Example`) that 346d20d629SWedson Almeida Filho /// contains an inner struct (`Inner`) that is protected by a mutex. 356d20d629SWedson Almeida Filho /// 366d20d629SWedson Almeida Filho /// ``` 37e283ee23SAlice Ryhl /// use kernel::sync::{new_mutex, Mutex}; 386d20d629SWedson Almeida Filho /// 396d20d629SWedson Almeida Filho /// struct Inner { 406d20d629SWedson Almeida Filho /// a: u32, 416d20d629SWedson Almeida Filho /// b: u32, 426d20d629SWedson Almeida Filho /// } 436d20d629SWedson Almeida Filho /// 446d20d629SWedson Almeida Filho /// #[pin_data] 456d20d629SWedson Almeida Filho /// struct Example { 466d20d629SWedson Almeida Filho /// c: u32, 476d20d629SWedson Almeida Filho /// #[pin] 486d20d629SWedson Almeida Filho /// d: Mutex<Inner>, 496d20d629SWedson Almeida Filho /// } 506d20d629SWedson Almeida Filho /// 516d20d629SWedson Almeida Filho /// impl Example { 526d20d629SWedson Almeida Filho /// fn new() -> impl PinInit<Self> { 536d20d629SWedson Almeida Filho /// pin_init!(Self { 546d20d629SWedson Almeida Filho /// c: 10, 556d20d629SWedson Almeida Filho /// d <- new_mutex!(Inner { a: 20, b: 30 }), 566d20d629SWedson Almeida Filho /// }) 576d20d629SWedson Almeida Filho /// } 586d20d629SWedson Almeida Filho /// } 596d20d629SWedson Almeida Filho /// 606d20d629SWedson Almeida Filho /// // Allocate a boxed `Example`. 61*c34aa00dSWedson Almeida Filho /// let e = Box::pin_init(Example::new(), GFP_KERNEL)?; 626d20d629SWedson Almeida Filho /// assert_eq!(e.c, 10); 636d20d629SWedson Almeida Filho /// assert_eq!(e.d.lock().a, 20); 646d20d629SWedson Almeida Filho /// assert_eq!(e.d.lock().b, 30); 65bfa7dff0SMiguel Ojeda /// # Ok::<(), Error>(()) 666d20d629SWedson Almeida Filho /// ``` 676d20d629SWedson Almeida Filho /// 686d20d629SWedson Almeida Filho /// The following example shows how to use interior mutability to modify the contents of a struct 696d20d629SWedson Almeida Filho /// protected by a mutex despite only having a shared reference: 706d20d629SWedson Almeida Filho /// 716d20d629SWedson Almeida Filho /// ``` 726d20d629SWedson Almeida Filho /// use kernel::sync::Mutex; 736d20d629SWedson Almeida Filho /// 746d20d629SWedson Almeida Filho /// struct Example { 756d20d629SWedson Almeida Filho /// a: u32, 766d20d629SWedson Almeida Filho /// b: u32, 776d20d629SWedson Almeida Filho /// } 786d20d629SWedson Almeida Filho /// 796d20d629SWedson Almeida Filho /// fn example(m: &Mutex<Example>) { 806d20d629SWedson Almeida Filho /// let mut guard = m.lock(); 816d20d629SWedson Almeida Filho /// guard.a += 10; 826d20d629SWedson Almeida Filho /// guard.b += 20; 836d20d629SWedson Almeida Filho /// } 846d20d629SWedson Almeida Filho /// ``` 856d20d629SWedson Almeida Filho /// 86bc2e7d5cSMiguel Ojeda /// [`struct mutex`]: srctree/include/linux/mutex.h 876d20d629SWedson Almeida Filho pub type Mutex<T> = super::Lock<T, MutexBackend>; 886d20d629SWedson Almeida Filho 896d20d629SWedson Almeida Filho /// A kernel `struct mutex` lock backend. 906d20d629SWedson Almeida Filho pub struct MutexBackend; 916d20d629SWedson Almeida Filho 926d20d629SWedson Almeida Filho // SAFETY: The underlying kernel `struct mutex` object ensures mutual exclusion. 936d20d629SWedson Almeida Filho unsafe impl super::Backend for MutexBackend { 946d20d629SWedson Almeida Filho type State = bindings::mutex; 956d20d629SWedson Almeida Filho type GuardState = (); 966d20d629SWedson Almeida Filho init( ptr: *mut Self::State, name: *const core::ffi::c_char, key: *mut bindings::lock_class_key, )976d20d629SWedson Almeida Filho unsafe fn init( 986d20d629SWedson Almeida Filho ptr: *mut Self::State, 996d20d629SWedson Almeida Filho name: *const core::ffi::c_char, 1006d20d629SWedson Almeida Filho key: *mut bindings::lock_class_key, 1016d20d629SWedson Almeida Filho ) { 1026d20d629SWedson Almeida Filho // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and 1036d20d629SWedson Almeida Filho // `key` are valid for read indefinitely. 1046d20d629SWedson Almeida Filho unsafe { bindings::__mutex_init(ptr, name, key) } 1056d20d629SWedson Almeida Filho } 1066d20d629SWedson Almeida Filho lock(ptr: *mut Self::State) -> Self::GuardState1076d20d629SWedson Almeida Filho unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { 1086d20d629SWedson Almeida Filho // SAFETY: The safety requirements of this function ensure that `ptr` points to valid 1096d20d629SWedson Almeida Filho // memory, and that it has been initialised before. 1106d20d629SWedson Almeida Filho unsafe { bindings::mutex_lock(ptr) }; 1116d20d629SWedson Almeida Filho } 1126d20d629SWedson Almeida Filho unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState)1136d20d629SWedson Almeida Filho unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { 1146d20d629SWedson Almeida Filho // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the 1156d20d629SWedson Almeida Filho // caller is the owner of the mutex. 1166d20d629SWedson Almeida Filho unsafe { bindings::mutex_unlock(ptr) }; 1176d20d629SWedson Almeida Filho } 1186d20d629SWedson Almeida Filho } 119