1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Synchronisation primitives. 4 //! 5 //! This module contains the kernel APIs related to synchronisation that have been ported or 6 //! wrapped for usage by Rust code in the kernel. 7 8 use crate::prelude::*; 9 use crate::types::Opaque; 10 use pin_init; 11 12 mod arc; 13 pub mod aref; 14 pub mod atomic; 15 pub mod barrier; 16 pub mod completion; 17 mod condvar; 18 pub mod lock; 19 mod locked_by; 20 pub mod poll; 21 pub mod rcu; 22 mod refcount; 23 mod set_once; 24 25 pub use arc::{Arc, ArcBorrow, UniqueArc}; 26 pub use completion::Completion; 27 pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult}; 28 pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy}; 29 pub use lock::mutex::{new_mutex, Mutex, MutexGuard}; 30 pub use lock::spinlock::{ 31 new_spinlock, 32 new_spinlock_irq, 33 SpinLock, 34 SpinLockGuard, 35 SpinLockIrq, 36 SpinLockIrqGuard, // 37 }; 38 pub use locked_by::LockedBy; 39 pub use refcount::Refcount; 40 pub use set_once::SetOnce; 41 42 /// Represents a lockdep class. 43 /// 44 /// Wraps the kernel's `struct lock_class_key`. 45 #[repr(transparent)] 46 #[pin_data(PinnedDrop)] 47 pub struct LockClassKey { 48 #[pin] 49 inner: Opaque<bindings::lock_class_key>, 50 } 51 52 // SAFETY: Unregistering a lock class key from a different thread than where it was registered is 53 // allowed. 54 unsafe impl Send for LockClassKey {} 55 56 // SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and 57 // provides its own synchronization. 58 unsafe impl Sync for LockClassKey {} 59 60 impl LockClassKey { 61 /// Initializes a statically allocated lock class key. 62 /// 63 /// This is usually used indirectly through the [`static_lock_class!`] macro. See its 64 /// documentation for more information. 65 /// 66 /// # Safety 67 /// 68 /// * Before using the returned value, it must be pinned in a static memory location. 69 /// * The destructor must never run on the returned `LockClassKey`. 70 pub const unsafe fn new_static() -> Self { 71 LockClassKey { 72 inner: Opaque::uninit(), 73 } 74 } 75 76 /// Initializes a dynamically allocated lock class key. 77 /// 78 /// In the common case of using a statically allocated lock class key, the 79 /// [`static_lock_class!`] macro should be used instead. 80 /// 81 /// # Examples 82 /// 83 /// ``` 84 /// use kernel::alloc::KBox; 85 /// use kernel::types::ForeignOwnable; 86 /// use kernel::sync::{LockClassKey, SpinLock}; 87 /// use pin_init::stack_pin_init; 88 /// 89 /// let key = KBox::pin_init(LockClassKey::new_dynamic(), GFP_KERNEL)?; 90 /// let key_ptr = key.into_foreign(); 91 /// 92 /// { 93 /// stack_pin_init!(let num: SpinLock<u32> = SpinLock::new( 94 /// 0, 95 /// c"my_spinlock", 96 /// // SAFETY: `key_ptr` is returned by the above `into_foreign()`, whose 97 /// // `from_foreign()` has not yet been called. 98 /// unsafe { <Pin<KBox<LockClassKey>> as ForeignOwnable>::borrow(key_ptr) } 99 /// )); 100 /// } 101 /// 102 /// // SAFETY: We dropped `num`, the only use of the key, so the result of the previous 103 /// // `borrow` has also been dropped. Thus, it's safe to use from_foreign. 104 /// unsafe { drop(<Pin<KBox<LockClassKey>> as ForeignOwnable>::from_foreign(key_ptr)) }; 105 /// # Ok::<(), Error>(()) 106 /// ``` 107 pub fn new_dynamic() -> impl PinInit<Self> { 108 pin_init!(Self { 109 // SAFETY: lockdep_register_key expects an uninitialized block of memory 110 inner <- Opaque::ffi_init(|slot| unsafe { bindings::lockdep_register_key(slot) }) 111 }) 112 } 113 114 /// Returns a raw pointer to the inner C struct. 115 /// 116 /// It is up to the caller to use the raw pointer correctly. 117 pub fn as_ptr(&self) -> *mut bindings::lock_class_key { 118 self.inner.get() 119 } 120 } 121 122 #[pinned_drop] 123 impl PinnedDrop for LockClassKey { 124 fn drop(self: Pin<&mut Self>) { 125 // SAFETY: `self.as_ptr()` was registered with lockdep and `self` is pinned, so the address 126 // hasn't changed. Thus, it's safe to pass it to unregister. 127 unsafe { bindings::lockdep_unregister_key(self.as_ptr()) } 128 } 129 } 130 131 /// Defines a new static lock class and returns a pointer to it. 132 /// 133 /// # Examples 134 /// 135 /// ``` 136 /// use kernel::sync::{static_lock_class, Arc, SpinLock}; 137 /// 138 /// fn new_locked_int() -> Result<Arc<SpinLock<u32>>> { 139 /// Arc::pin_init(SpinLock::new( 140 /// 42, 141 /// c"new_locked_int", 142 /// static_lock_class!(), 143 /// ), GFP_KERNEL) 144 /// } 145 /// ``` 146 #[macro_export] 147 macro_rules! static_lock_class { 148 () => {{ 149 static CLASS: $crate::sync::LockClassKey = 150 // SAFETY: The returned `LockClassKey` is stored in static memory and we pin it. Drop 151 // never runs on a static global. 152 unsafe { $crate::sync::LockClassKey::new_static() }; 153 $crate::prelude::Pin::static_ref(&CLASS) 154 }}; 155 } 156 pub use static_lock_class; 157 158 /// Returns the given string, if one is provided, otherwise generates one based on the source code 159 /// location. 160 #[doc(hidden)] 161 #[macro_export] 162 macro_rules! optional_name { 163 () => { 164 $crate::c_str!(::core::concat!(::core::file!(), ":", ::core::line!())) 165 }; 166 ($name:literal) => { 167 $crate::c_str!($name) 168 }; 169 } 170