xref: /linux/rust/kernel/sync/lockdep.rs (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Utilities related to lockdep.
4 //!
5 //! C headers: [`include/linux/lockdep.h`](srctree/include/linux/lockdep.h)
6 
7 use crate::{
8     prelude::*,
9     types::Opaque, //
10 };
11 
12 /// Represents a lockdep class.
13 ///
14 /// Wraps the kernel's `struct lock_class_key`.
15 #[repr(transparent)]
16 #[pin_data(PinnedDrop)]
17 pub struct LockClassKey {
18     #[pin]
19     inner: Opaque<bindings::lock_class_key>,
20 }
21 
22 // SAFETY: Unregistering a lock class key from a different thread than where it was registered is
23 // allowed.
24 unsafe impl Send for LockClassKey {}
25 
26 // SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and
27 // provides its own synchronization.
28 unsafe impl Sync for LockClassKey {}
29 
30 impl LockClassKey {
31     /// Initializes a statically allocated lock class key.
32     ///
33     /// This is usually used indirectly through the [`static_lock_class!`] macro. See its
34     /// documentation for more information.
35     ///
36     /// # Safety
37     ///
38     /// * Before using the returned value, it must be pinned in a static memory location.
39     /// * The destructor must never run on the returned `LockClassKey`.
40     pub const unsafe fn new_static() -> Self {
41         LockClassKey {
42             inner: Opaque::uninit(),
43         }
44     }
45 
46     /// Initializes a dynamically allocated lock class key.
47     ///
48     /// In the common case of using a statically allocated lock class key, the
49     /// [`static_lock_class!`] macro should be used instead.
50     ///
51     /// # Examples
52     ///
53     /// ```
54     /// use kernel::alloc::KBox;
55     /// use kernel::types::ForeignOwnable;
56     /// use kernel::sync::{LockClassKey, SpinLock};
57     /// use pin_init::stack_pin_init;
58     ///
59     /// let key = KBox::pin_init(LockClassKey::new_dynamic(), GFP_KERNEL)?;
60     /// let key_ptr = key.into_foreign();
61     ///
62     /// {
63     ///     stack_pin_init!(let num: SpinLock<u32> = SpinLock::new(
64     ///         0,
65     ///         c"my_spinlock",
66     ///         // SAFETY: `key_ptr` is returned by the above `into_foreign()`, whose
67     ///         // `from_foreign()` has not yet been called.
68     ///         unsafe { <Pin<KBox<LockClassKey>> as ForeignOwnable>::borrow(key_ptr) }
69     ///     ));
70     /// }
71     ///
72     /// // SAFETY: We dropped `num`, the only use of the key, so the result of the previous
73     /// // `borrow` has also been dropped. Thus, it's safe to use from_foreign.
74     /// unsafe { drop(<Pin<KBox<LockClassKey>> as ForeignOwnable>::from_foreign(key_ptr)) };
75     /// # Ok::<(), Error>(())
76     /// ```
77     pub fn new_dynamic() -> impl PinInit<Self> {
78         pin_init!(Self {
79             // SAFETY: lockdep_register_key expects an uninitialized block of memory
80             inner <- Opaque::ffi_init(|slot| unsafe { bindings::lockdep_register_key(slot) })
81         })
82     }
83 
84     /// Returns a raw pointer to the inner C struct.
85     ///
86     /// It is up to the caller to use the raw pointer correctly.
87     pub fn as_ptr(&self) -> *mut bindings::lock_class_key {
88         self.inner.get()
89     }
90 }
91 
92 #[pinned_drop]
93 impl PinnedDrop for LockClassKey {
94     fn drop(self: Pin<&mut Self>) {
95         // SAFETY: `self.as_ptr()` was registered with lockdep and `self` is pinned, so the address
96         // hasn't changed. Thus, it's safe to pass it to unregister.
97         unsafe { bindings::lockdep_unregister_key(self.as_ptr()) }
98     }
99 }
100 
101 /// Defines a new static lock class and returns a pointer to it.
102 ///
103 /// # Examples
104 ///
105 /// ```
106 /// use kernel::sync::{static_lock_class, Arc, SpinLock};
107 ///
108 /// fn new_locked_int() -> Result<Arc<SpinLock<u32>>> {
109 ///     Arc::pin_init(SpinLock::new(
110 ///         42,
111 ///         c"new_locked_int",
112 ///         static_lock_class!(),
113 ///     ), GFP_KERNEL)
114 /// }
115 /// ```
116 #[macro_export]
117 macro_rules! static_lock_class {
118     () => {{
119         static CLASS: $crate::sync::LockClassKey =
120             // SAFETY: The returned `LockClassKey` is stored in static memory and we pin it. Drop
121             // never runs on a static global.
122             unsafe { $crate::sync::LockClassKey::new_static() };
123         $crate::prelude::Pin::static_ref(&CLASS)
124     }};
125 }
126 pub use static_lock_class;
127 
128 /// Returns the given string, if one is provided, otherwise generates one based on the source code
129 /// location.
130 #[doc(hidden)]
131 #[macro_export]
132 macro_rules! optional_name {
133     () => {
134         $crate::c_str!(::core::concat!(::core::file!(), ":", ::core::line!()))
135     };
136     ($name:literal) => {
137         $crate::c_str!($name)
138     };
139 }
140 
141 /// Not checked, catch all.
142 pub const LD_WAIT_INV: u8 = bindings::lockdep_wait_type_LD_WAIT_INV as u8;
143 /// Spin loops, `raw_spinlock_t` etc
144 pub const LD_WAIT_SPIN: u8 = bindings::lockdep_wait_type_LD_WAIT_SPIN as u8;
145 
146 /// Helper for declaring a raw `struct lockdep_map` for locks in statics.
147 ///
148 /// It's up to the caller to use the returned `struct lockdep_map` correctly.
149 #[cfg(CONFIG_DEBUG_LOCK_ALLOC)]
150 pub(crate) const fn raw_lockdep_map(
151     name: &'static CStr,
152     wait_type_inner: u8,
153     wait_type_outer: u8,
154 ) -> bindings::lockdep_map {
155     // SAFETY: All zeros is valid for this type.
156     let mut map: bindings::lockdep_map = unsafe { core::mem::zeroed() };
157     map.name = kernel::str::as_char_ptr_in_const_context(name);
158     map.wait_type_inner = wait_type_inner;
159     map.wait_type_outer = wait_type_outer;
160     map
161 }
162