From 86f4a271dc1962e389ea512d07a77626dbd8c1d8 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 11 Aug 2025 12:14:41 +0000 Subject: [PATCH] rust: sync: Refactor static_lock_class!() macro By introducing a new_static() constructor, the macro does not need to go through MaybeUninit::uninit().assume_init(), which is a pattern that is best avoided when possible. The safety comment not only requires that the value is leaked, but also that it is stored in the right portion of memory. This is so that the lockdep static_obj() check will succeed when using this constructor. One could argue that lockdep detects this scenario, so that safety requirement isn't needed. However, it simplifies matters to require that static_obj() will succeed and it's not a burdensome requirement on the caller. Suggested-by: Benno Lossin Reviewed-by: Daniel Almeida Reviewed-by: Benno Lossin Signed-off-by: Alice Ryhl Signed-off-by: Boqun Feng Link: https://patch.msgid.link/20250811-lock-class-key-cleanup-v3-1-b12967ee1ca2@google.com --- rust/kernel/sync.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 5df87e2bd212e..1dfbee8e9d003 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -45,6 +45,21 @@ pub struct LockClassKey { unsafe impl Sync for LockClassKey {} impl LockClassKey { + /// Initializes a statically allocated lock class key. + /// + /// This is usually used indirectly through the [`static_lock_class!`] macro. + /// + /// # Safety + /// + /// * Before using the returned value, it must be pinned in a static memory location. + /// * The destructor must never run on the returned `LockClassKey`. + #[doc(hidden)] + pub const unsafe fn new_static() -> Self { + LockClassKey { + inner: Opaque::uninit(), + } + } + /// Initializes a dynamically allocated lock class key. In the common case of using a /// statically allocated lock class key, the static_lock_class! macro should be used instead. /// @@ -101,12 +116,9 @@ impl PinnedDrop for LockClassKey { macro_rules! static_lock_class { () => {{ static CLASS: $crate::sync::LockClassKey = - // Lockdep expects uninitialized memory when it's handed a statically allocated `struct - // lock_class_key`. - // - // SAFETY: `LockClassKey` transparently wraps `Opaque` which permits uninitialized - // memory. - unsafe { ::core::mem::MaybeUninit::uninit().assume_init() }; + // SAFETY: The returned `LockClassKey` is stored in static memory and we pin it. Drop + // never runs on a static global. + unsafe { $crate::sync::LockClassKey::new_static() }; $crate::prelude::Pin::static_ref(&CLASS) }}; } -- 2.47.3