From: "Onur Özkan" <work@onurozkan.dev>
To: Beata Michalska <beata.michalska@arm.com>
Cc: rust-for-linux@vger.kernel.org, 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: Re: [PATCH v13 6/7] rust: ww_mutex: implement DynLockSet
Date: Thu, 12 Nov 2026 17:41:46 +0300 [thread overview]
Message-ID: <20261112144158.278467-1-work@onurozkan.dev> (raw)
In-Reply-To: <avTIMTuuFnxHhS74@arm.com>
On Wed, 11 Nov 2026 20:55:29 +0100
Beata Michalska <beata.michalska@arm.com> wrote:
> Hi Onur,
>
> On Tue, Oct 20, 2026 at 06:29:42PM +0300, Onur Özkan wrote:
> > DynLockSet is a high-level and safe API built on top of ww_mutex
> > for dynamically discovered locks. It keeps acquired locks held,
> > handles repeated objects and provides access to their data.
> >
> > When EDEADLK is hit it drops all held locks and waits for the
> > contended mutex. It then retries the given (by the user)
> > locking algorithm with that mutex held and the same acquire
> > context until it succeeds.
> >
> > Signed-off-by: Onur Özkan <work@onurozkan.dev>
> > ---
> > rust/kernel/sync/lock/ww_mutex.rs | 4 +
> > .../sync/lock/ww_mutex/acquire_ctx_backoff.rs | 138 ++++++-
> > .../kernel/sync/lock/ww_mutex/dyn_lock_set.rs | 351 ++++++++++++++++++
> > 3 files changed, 489 insertions(+), 4 deletions(-)
> > create mode 100644 rust/kernel/sync/lock/ww_mutex/dyn_lock_set.rs
> >
> > diff --git a/rust/kernel/sync/lock/ww_mutex.rs b/rust/kernel/sync/lock/ww_mutex.rs
> > index 2249214959b1c..fea2603d1bd1f 100644
> > --- a/rust/kernel/sync/lock/ww_mutex.rs
> > +++ b/rust/kernel/sync/lock/ww_mutex.rs
> > @@ -7,6 +7,8 @@
> > //! [`AcquireCtx`] to track ordering and ensure forward progress.
> > //!
> > //! [`ww_transaction`] provides automatic deadlock recovery for ordinary guards.
> > +//! Use [`DynLockSet::ww_transaction`] for dynamically discovered locks and
> > +//! separate acquisition and work callbacks.
> > //!
> > //! See srctree/Documentation/locking/ww-mutex-design.rst for more details.
> >
> > @@ -28,10 +30,12 @@
> > AcquireCtxBackoff, //
> > };
> > pub use class::Class;
> > +pub use dyn_lock_set::DynLockSet;
> >
> > mod acquire_ctx;
> > mod acquire_ctx_backoff;
> > mod class;
> > +mod dyn_lock_set;
> >
> > /// A wound-wait (ww) mutex that is powered with deadlock avoidance
[...]
> > +
> > + /// Acquires a dynamic set, retrying on deadlock then runs `work` once.
> > + ///
> > + /// Each call releases existing locks and starts a new transaction. Retries keep
> > + /// the same ticket. The set retains its allocation across retries and calls.
> > + ///
> > + /// `work` runs once after acquisition and must not acquire more locks. Its errors
> > + /// are returned without retrying. All locks and pending backoff state are released
> > + /// on return. The callbacks must not change the set's context or nest transactions
> > + /// on that context.
> > + ///
> > + /// # Panics
> > + ///
> > + /// Panics if the context holds caller-owned locks outside this set at a transaction
> > + /// boundary, including forgotten guards.
> > + ///
> > + /// # Examples
> > + ///
> > + /// ```
> > + /// use kernel::{
> > + /// define_ww_class,
> > + /// prelude::*,
> > + /// sync::lock::ww_mutex::{
> > + /// AcquireCtx,
> > + /// AcquireCtxBackoff,
> > + /// DynLockSet,
> > + /// Mutex, //
> > + /// }, //
> > + /// };
> > + /// use pin_init::stack_pin_init;
> > + ///
> > + /// define_ww_class!(CLASS);
> > + ///
> > + /// stack_pin_init!(let first = Mutex::new(1, &CLASS));
> > + /// stack_pin_init!(let second = Mutex::new(2, &CLASS));
> > + ///
> > + /// stack_pin_init!(let acquire_ctx = AcquireCtx::new(&CLASS));
> > + /// let ctx = AcquireCtxBackoff::new(acquire_ctx.as_mut());
> > + /// let mut set = DynLockSet::new(&ctx);
> > + ///
> > + /// set.ww_transaction(
> > + /// |set| {
> > + /// set.lock(&first)?;
> > + ///
> > + /// if set.with_locked(&first, |value| *value > 0)? {
> > + /// set.lock(&second)?;
> > + /// }
> > + ///
> > + /// Ok(())
> > + /// },
> > + /// |set| set.with_locked(&first, |value| *value += 1),
> > + /// )?;
> > + /// # Ok::<(), Error>(())
> > + /// ```
> > + pub fn ww_transaction<R>(
> > + &mut self,
> > + mut acquire: impl FnMut(&mut Self) -> Result,
> > + work: impl FnOnce(&mut Self) -> Result<R>,
> > + ) -> Result<R> {
> So I have been pondering a bit on that one, in a context of drm_exec and
> potentially having a Rust version of drm_gpuvm_exec_lock & co, and I'm having
> some doubts really. The `drm_exec` implementation, apart from locking and
> reserving fences, also plays with the `drm_gem_object` reference counting.
> The `drm_exec` pairs each tracked lock with a GEM reference and releases both
> during backoff or cleanup. Proposed implementation makes it rather cumbersome
> to drop the reference when unlocking the mutex on a rollback (or backoff in
> this series terminology). I assume that would require some sort of extension
> to the `DynLockSet` ? Or am I missing smth ?
>
> ---
> BR
> Beata
Current API tracks the locks but leaves ownership of the objects to the caller
and, yes, we need some sort of extension on DynLockSet probably together with
AcqureCtx and its wrapper type.
Does current API limit your GPUVM use case? Could you share an example of the
flow you need? I would be happy to extend the API if that's needed.
Thanks,
Onur
>
> > + let ctx = self.ctx;
> > + self.clear();
> > + ctx.restart();
> > +
> > + let result = retry(ctx, || {
> > + if let Some(guard) = self.ctx.take_contended_guard() {
> > + self.add_guard(guard)?;
> > + }
> > +
> > + let result = acquire(self);
> > + if result.is_err() {
> > + self.clear();
> > + }
> > +
> > + result
> > + });
> > +
> > + let result = result.and_then(|()| work(self));
> > +
> > + self.clear();
> > + ctx.clear_backoff();
> > + ctx.assert_no_locks_held();
> > +
> > + result
> > + }
> > +
[...]
> > +
> > + assert_eq!(set.with_locked(&mutex, |v| *v), Err(EINVAL));
> > +
> > + Ok(())
> > + }
> > +
> > + #[test]
> > + fn test_class_mismatch() -> Result {
> > + stack_pin_init!(let mutex = Mutex::new(5, &TEST_WOUND_WAIT_CLASS));
> > + stack_pin_init!(let acquire_ctx = AcquireCtx::new(&TEST_WAIT_DIE_CLASS));
> > + let ctx = AcquireCtxBackoff::new(acquire_ctx.as_mut());
> > + let mut set = DynLockSet::new(&ctx);
> > +
> > + assert_eq!(set.lock(&mutex), Err(EINVAL));
> > + assert!(!mutex.is_locked());
> > +
> > + Ok(())
> > + }
> > +}
> > --
> > 2.51.2
> >
> >
next prev parent reply other threads:[~2026-11-12 14:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 15:29 [PATCH v13 0/7] rust: add ww_mutex support Onur Özkan
2026-10-20 15:29 ` [PATCH v13 1/7] rust: add C wrappers for ww_mutex inline functions Onur Özkan
2026-10-20 15:29 ` [PATCH v13 2/7] ww_mutex: add ww_class field unconditionally Onur Özkan
2026-10-20 15:29 ` [PATCH v13 3/7] rust: implement Class for ww_class support Onur Özkan
2026-10-20 15:29 ` [PATCH v13 4/7] rust: ww_mutex: add Mutex, AcquireCtx and MutexGuard Onur Özkan
2026-10-20 15:29 ` [PATCH v13 5/7] rust: ww_mutex: add AcquireCtxBackoff Onur Özkan
2026-10-20 15:29 ` [PATCH v13 6/7] rust: ww_mutex: implement DynLockSet Onur Özkan
2026-11-11 19:55 ` Beata Michalska
2026-11-12 14:41 ` Onur Özkan [this message]
2026-10-20 15:29 ` [PATCH v13 7/7] 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=20261112144158.278467-1-work@onurozkan.dev \
--to=work@onurozkan.dev \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=beata.michalska@arm.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
all inboxes | Powered by JetHome®