Lock classes aren't used without lockdep. The C side declares the key as an empty struct in that case, but let's make it an explicit ZST in Rust, implemented in a separate module. This allows us to more easily guarantee that the lockdep code will be trivially optimized out without CONFIG_LOCKDEP, including LockClassKey arguments that are passed around. Depending on whether CONFIG_LOCKDEP is enabled or not, we then import the real lockdep implementation or the dummy one. Signed-off-by: Asahi Lina <lina@xxxxxxxxxxxxx> --- rust/kernel/sync.rs | 29 ++++++++--------------------- rust/kernel/sync/lockdep.rs | 27 +++++++++++++++++++++++++++ rust/kernel/sync/no_lockdep.rs | 19 +++++++++++++++++++ 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index d219ee518eff..352472c6b77a 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -5,37 +5,24 @@ //! This module contains the kernel APIs related to synchronisation that have been ported or //! wrapped for usage by Rust code in the kernel. -use crate::types::Opaque; - mod arc; mod condvar; pub mod lock; mod locked_by; +#[cfg(CONFIG_LOCKDEP)] +mod lockdep; +#[cfg(not(CONFIG_LOCKDEP))] +mod no_lockdep; +#[cfg(not(CONFIG_LOCKDEP))] +use no_lockdep as lockdep; + pub use arc::{Arc, ArcBorrow, UniqueArc}; pub use condvar::CondVar; pub use lock::{mutex::Mutex, spinlock::SpinLock}; +pub use lockdep::LockClassKey; pub use locked_by::LockedBy; -/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. -#[repr(transparent)] -pub struct LockClassKey(Opaque<bindings::lock_class_key>); - -// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and -// provides its own synchronization. -unsafe impl Sync for LockClassKey {} - -impl LockClassKey { - /// Creates a new lock class key. - pub const fn new() -> Self { - Self(Opaque::uninit()) - } - - pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { - self.0.get() - } -} - /// Defines a new static lock class and returns a pointer to it. #[doc(hidden)] #[macro_export] diff --git a/rust/kernel/sync/lockdep.rs b/rust/kernel/sync/lockdep.rs new file mode 100644 index 000000000000..cb68b18dc0ad --- /dev/null +++ b/rust/kernel/sync/lockdep.rs @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Lockdep utilities. +//! +//! This module abstracts the parts of the kernel lockdep API relevant to Rust +//! modules, including lock classes. + +use crate::types::Opaque; + +/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. +#[repr(transparent)] +pub struct LockClassKey(Opaque<bindings::lock_class_key>); + +impl LockClassKey { + /// Creates a new lock class key. + pub const fn new() -> Self { + Self(Opaque::uninit()) + } + + pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { + self.0.get() + } +} + +// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and +// provides its own synchronization. +unsafe impl Sync for LockClassKey {} diff --git a/rust/kernel/sync/no_lockdep.rs b/rust/kernel/sync/no_lockdep.rs new file mode 100644 index 000000000000..69d42e8d9801 --- /dev/null +++ b/rust/kernel/sync/no_lockdep.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Dummy lockdep utilities. +//! +//! Takes the place of the `lockdep` module when lockdep is disabled. + +/// A dummy, zero-sized lock class. +pub struct LockClassKey(); + +impl LockClassKey { + /// Creates a new dummy lock class key. + pub const fn new() -> Self { + Self() + } + + pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { + core::ptr::null_mut() + } +} -- 2.40.1