Re: [PATCH v6 3/7] rust: implement `WwMutex`, `WwAcquireCtx` and `WwMutexGuard`

Onur Özkan
2025-10-22T10:53:07Z

On Fri, 5 Sep 2025 16:03:02 -0300
Daniel Almeida <daniel.almeida@collabora.com> wrote:

> […]
>
> >
> >> +///
> >> +/// # Examples
> >> +///
> >> +/// ## Basic Usage
> >> +///
> >> +/// ```
> >> +/// use kernel::c_str;
> >> +/// use kernel::sync::Arc;
> >> +/// use kernel::sync::lock::ww_mutex::{WwClass, WwAcquireCtx,
> >> WwMutex }; +/// use pin_init::stack_pin_init;
> >> +///
> >> +/// stack_pin_init!(let class =
> >> WwClass::new_wound_wait(c_str!("buffer_class"))); +/// let mutex =
> >> Arc::pin_init(WwMutex::new(42, &class), GFP_KERNEL)?; +///
> >> +/// let ctx = KBox::pin_init(WwAcquireCtx::new(&class),
> >> GFP_KERNEL)?; +///
> >> +/// let guard = ctx.lock(&mutex)?;
> >> +/// assert_eq!(*guard, 42);
> >> +///
> >> +/// # Ok::<(), Error>(())
> >> +/// ```
> >> +///
> >> +/// ## Multiple Locks
> >> +///
> >> +/// ```
> >> +/// use kernel::c_str;
> >> +/// use kernel::prelude::*;
> >> +/// use kernel::sync::Arc;
> >> +/// use kernel::sync::lock::ww_mutex::{WwClass, WwAcquireCtx,
> >> WwMutex}; +/// use pin_init::stack_pin_init;
> >> +///
> >> +/// stack_pin_init!(let class =
> >> WwClass::new_wait_die(c_str!("resource_class"))); +/// let mutex_a
> >> = Arc::pin_init(WwMutex::new("Resource A", &class), GFP_KERNEL)?;
> >> +/// let mutex_b = Arc::pin_init(WwMutex::new("Resource B",
> >> &class), GFP_KERNEL)?; +/// +/// let ctx =
> >> KBox::pin_init(WwAcquireCtx::new(&class), GFP_KERNEL)?; +///
> >> +/// // Try to acquire both locks.
> >> +/// let guard_a = match ctx.lock(&mutex_a) {
> >> +/// Ok(guard) => guard,
> >> +/// Err(e) if e == EDEADLK => {
> >> +/// // Deadlock detected, use slow path.
> >
> > You must release all other locks before calling this, except there
> > aren’t any taken in your example.
> >
> > You should perhaps add a release_all() function to the context.
> >
>
> By the way, if we need a context in the first place to lock, it makes
> sense to release_all() once this context is dropped.

I am going to need to implement release_all anyway since the C code [1]
requires that all locks be released before calling ww_acquire_fini
(which we already do in PinnedDrop and now in reinit (a new function)).

To make that work, we need to keep track of the locks which is what
ExecContext is currently doing. So I will probably just drop ExecContext
entirely and fold that logic into WwAcquireCtx instead (like I
mentioned a while back) for the next version in this week.

[1]:
https://github.com/torvalds/linux/blob/552c50713f27/include/linux/ww_mutex.h#L195-L196

Regards,
Onur

>
> — Daniel
>
>
>