[PATCH v12 0/6] rust: add ww_mutex support
From: Onur Özkan
Date: Mon Oct 12 2026 - 06:58:47 EST
This series adds Rust abstractions for ww_mutex, including Class, Mutex,
AcquireCtx and MutexGuard. LockSet handles deadlock recovery for callers
that need to acquire multiple locks.
Changes in v12 (sashiko fixes):
- Give Rust-defined classes separate _acquire and _mutex lockdep names
to match the C initializer.
- Correct the Class Sync safety comment and add an invariant comment
when constructing MutexGuard.
- Add #[inline] to Class::from_raw(), Mutex::is_locked(),
AcquireCtx::done(), MutexGuard::drop() and RawGuard::drop().
Built x86_64 kernels with and without PREEMPT_RT. rustfmtcheck, Clippy and
rustdoc passed. All 14 ww_mutex/LockSet KUnit tests passed on both builds
with CONFIG_PROVE_LOCKING and CONFIG_DEBUG_WW_MUTEX_SLOWPATH enabled.
Previous version:
https://lore.kernel.org/all/cover.1791743500.git.work@xxxxxxxxxxxxx/
Onur Özkan (6):
rust: add C wrappers for ww_mutex inline functions
ww_mutex: add ww_class field unconditionally
rust: implement Class for ww_class support
rust: ww_mutex: add Mutex, AcquireCtx and MutexGuard
rust: ww_mutex: implement LockSet
MAINTAINERS: add Onur Özkan as WW MUTEX maintainer
MAINTAINERS | 2 +
include/linux/ww_mutex.h | 8 +-
rust/helpers/helpers.c | 1 +
rust/helpers/ww_mutex.c | 33 ++
rust/kernel/sync/lock.rs | 1 +
rust/kernel/sync/lock/ww_mutex.rs | 447 +++++++++++++++++
rust/kernel/sync/lock/ww_mutex/acquire_ctx.rs | 149 ++++++
rust/kernel/sync/lock/ww_mutex/class.rs | 151 ++++++
rust/kernel/sync/lock/ww_mutex/lock_set.rs | 449 ++++++++++++++++++
9 files changed, 1235 insertions(+), 6 deletions(-)
create mode 100644 rust/helpers/ww_mutex.c
create mode 100644 rust/kernel/sync/lock/ww_mutex.rs
create mode 100644 rust/kernel/sync/lock/ww_mutex/acquire_ctx.rs
create mode 100644 rust/kernel/sync/lock/ww_mutex/class.rs
create mode 100644 rust/kernel/sync/lock/ww_mutex/lock_set.rs
Range-diff against v11:
1: 4942155a8873e = 1: 4942155a8873e rust: add C wrappers for ww_mutex inline functions
2: 168394bb52a6c = 2: 168394bb52a6c ww_mutex: add ww_class field unconditionally
3: 003bc88697dc8 ! 3: ba8ea8e2e2b50 rust: implement Class for ww_class support
@@ rust/kernel/sync/lock/ww_mutex/class.rs (new)
+ // SAFETY: This is `static`, so address is fixed and won't move.
+ unsafe {
+ $crate::sync::lock::ww_mutex::Class::new_unpinned(
-+ $crate::c_str!(::core::stringify!($name)),
++ $crate::c_str!(::core::concat!(::core::stringify!($name), "_acquire")),
++ $crate::c_str!(::core::concat!(::core::stringify!($name), "_mutex")),
+ false,
+ )
+ };
@@ rust/kernel/sync/lock/ww_mutex/class.rs (new)
+ // SAFETY: This is `static`, so address is fixed and won't move.
+ unsafe {
+ $crate::sync::lock::ww_mutex::Class::new_unpinned(
-+ $crate::c_str!(::core::stringify!($name)),
++ $crate::c_str!(::core::concat!(::core::stringify!($name), "_acquire")),
++ $crate::c_str!(::core::concat!(::core::stringify!($name), "_mutex")),
+ true,
+ )
+ };
@@ rust/kernel/sync/lock/ww_mutex/class.rs (new)
+ ///
+ /// Caller must guarantee that the returned value must be pinned before
+ /// its first use.
-+ pub const unsafe fn new_unpinned(name: &'static CStr, is_wait_die: bool) -> Self {
++ pub const unsafe fn new_unpinned(
++ acquire_name: &'static CStr,
++ mutex_name: &'static CStr,
++ is_wait_die: bool,
++ ) -> Self {
+ Class {
+ inner: Opaque::new(bindings::ww_class {
+ stamp: bindings::atomic_long_t { counter: 0 },
-+ acquire_name: crate::str::as_char_ptr_in_const_context(name),
-+ mutex_name: crate::str::as_char_ptr_in_const_context(name),
++ acquire_name: crate::str::as_char_ptr_in_const_context(acquire_name),
++ mutex_name: crate::str::as_char_ptr_in_const_context(mutex_name),
+ is_wait_die: is_wait_die as u32,
+ // TODO: Replace with `bindings::lock_class_key::default()` once
+ // stabilized for `const`.
@@ rust/kernel/sync/lock/ww_mutex/class.rs (new)
+ ///
+ /// The caller must ensure that `ptr` points to the `inner` field of
+ /// [`Class`] and that it remains valid for the lifetime `'a`.
++ #[inline]
+ pub const unsafe fn from_raw<'a>(ptr: *mut bindings::ww_class) -> &'a Self {
+ // SAFETY: By the safety contract, `ptr` is valid to construct `Class`.
+ unsafe { &*ptr.cast() }
+ }
+}
+
-+// SAFETY: [`Class`] is set up once and never modified. It's fine to share it across threads.
++// SAFETY: [`Class`] is immutable except for its atomic stamp. It's fine to share it across threads.
+unsafe impl Sync for Class {}
+// SAFETY: Doesn't hold anything thread-specific. It's safe to send to other threads.
+unsafe impl Send for Class {}
4: 293fbbc0bcc0f ! 4: 36bddd73ca296 rust: ww_mutex: add Mutex, AcquireCtx and MutexGuard
@@ rust/kernel/sync/lock/ww_mutex.rs
+ ///
+ /// The returned value is racy as another thread can acquire
+ /// or release the lock immediately after this call returns.
++ #[inline]
+ pub fn is_locked(&self) -> bool {
+ // SAFETY: It's safe to call `ww_mutex_is_locked` on
+ // a valid mutex.
@@ rust/kernel/sync/lock/ww_mutex.rs
+ fn new(mutex: &'a Mutex<'a, T>) -> Self {
+ assert!(mutex.is_locked());
+
++ // INVARIANT: `lock_common` and `from_raw` ensure that the current task holds the mutex
++ // and transfer sole responsibility for unlocking it to this guard.
+ Self {
+ mutex,
+ _not_send: NotThreadSafe,
@@ rust/kernel/sync/lock/ww_mutex.rs
+}
+
+impl<T: ?Sized> Drop for MutexGuard<'_, T> {
++ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: self.mutex is locked and are about to release it.
+ unsafe { bindings::ww_mutex_unlock(self.mutex.inner.get()) };
@@ rust/kernel/sync/lock/ww_mutex/acquire_ctx.rs (new)
+ ///
+ /// After calling this function, no more mutexes can be acquired with
+ /// this context.
++ #[inline]
+ pub fn done(&self) {
+ // SAFETY: `self.inner` contains a valid, initialized acquire context.
+ unsafe { bindings::ww_acquire_done(self.inner.get()) };
5: d085c15ba9da4 ! 5: 8a3e94391fcee rust: ww_mutex: implement LockSet
@@ rust/kernel/sync/lock/ww_mutex/lock_set.rs (new)
+}
+
+impl Drop for RawGuard {
++ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: `mutex_ptr` originates from a locked `Mutex` and remains
+ // valid for the lifetime of this guard, so unlocking here is sound.
6: 8f0e93bd1781e = 6: 2b7b779f72f77 MAINTAINERS: add Onur Özkan as WW MUTEX maintainer
base-commit: 47324d3a5b3abd781295044d01d92d09f184e872
--
2.51.2