From: "Onur Özkan" <work@onurozkan.dev>
To: rust-for-linux@vger.kernel.org
Cc: "Onur Özkan" <work@onurozkan.dev>,
lossin@kernel.org, lyude@redhat.com, ojeda@kernel.org,
alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net,
a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
dakr@kernel.org, peterz@infradead.org, mingo@redhat.com,
will@kernel.org, longman@redhat.com, felipe_life@live.com,
daniel@sedlak.dev, daniel.almeida@collabora.com,
thomas.hellstrom@linux.intel.com, linux-kernel@vger.kernel.org
Subject: [PATCH v12 0/6] rust: add ww_mutex support
Date: Mon, 12 Oct 2026 13:26:27 +0300 [thread overview]
Message-ID: <cover.1791799751.git.work@onurozkan.dev> (raw)
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@onurozkan.dev/
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
next reply other threads:[~2026-10-12 10:27 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 10:26 Onur Özkan [this message]
2026-10-12 10:26 ` [PATCH v12 1/6] rust: add C wrappers for ww_mutex inline functions Onur Özkan
2026-10-12 11:41 ` Gary Guo
2026-10-12 10:26 ` [PATCH v12 2/6] ww_mutex: add ww_class field unconditionally Onur Özkan
2026-10-12 11:42 ` Gary Guo
2026-10-12 10:26 ` [PATCH v12 3/6] rust: implement Class for ww_class support Onur Özkan
2026-10-12 11:03 ` Gary Guo
2026-10-12 11:26 ` Onur Özkan
2026-10-12 10:26 ` [PATCH v12 4/6] rust: ww_mutex: add Mutex, AcquireCtx and MutexGuard Onur Özkan
2026-10-12 11:40 ` Gary Guo
2026-10-12 10:26 ` [PATCH v12 5/6] rust: ww_mutex: implement LockSet Onur Özkan
2026-10-12 12:02 ` Gary Guo
2026-10-12 10:26 ` [PATCH v12 6/6] MAINTAINERS: add Onur Özkan as WW MUTEX maintainer Onur Özkan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1791799751.git.work@onurozkan.dev \
--to=work@onurozkan.dev \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=daniel@sedlak.dev \
--cc=felipe_life@live.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=thomas.hellstrom@linux.intel.com \
--cc=tmgross@umich.edu \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).