All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: onur-ozkan <work@onurozkan.dev>
Cc: linux-kernel@vger.kernel.org, thatslyude@gmail.com,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	rust-for-linux@vger.kernel.org,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Ingo Molnar" <mingo@kernel.org>, "Will Deacon" <will@kernel.org>,
	"Waiman Long" <longman@redhat.com>
Subject: Re: [PATCH] Add `ww_mutex` support & abstraction for Rust tree
Date: Mon, 16 Jun 2025 10:58:36 -0700	[thread overview]
Message-ID: <aFBbTMMTHrgHwVFJ@Mac.home> (raw)
In-Reply-To: <20250616162448.31641-1-work@onurozkan.dev>

Hi,

Thanks for the patch.

[Add Rust and Locking]

Could you please cc more people and lists for the next version? You
can find that information via `scripts/get_maintainer.pl` or the
"LOCKING PRIMITIVES" and "RUST" sections in MAINTAINERS file in the
kernel source.

Some comments from a quick look:

On Mon, Jun 16, 2025 at 07:24:48PM +0300, onur-ozkan wrote:
[...]
> +/// Implementation of C side `ww_class`.
> +///
> +/// Represents a group of mutexes that can participate in deadlock avoidance together.
> +/// All mutexes that might be acquired together should use the same class.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::sync::lock::ww_mutex::WwClass;
> +/// use kernel::c_str;
> +///
> +/// let _wait_die_class = unsafe { WwClass::new(c_str!("graphics_buffers"), true) };
> +/// let _wound_wait_class = unsafe { WwClass::new(c_str!("memory_pools"), false) };
> +///
> +/// # Ok::<(), Error>(())
> +/// ```
> +#[repr(transparent)]
> +pub struct WwClass(Opaque<bindings::ww_class>);
> +
> +// SAFETY: `WwClass` can be shared between threads.
> +unsafe impl Sync for WwClass {}
> +
> +impl WwClass {
> +    /// Creates `WwClass` that wraps C side `ww_class`.
> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must ensure that the returned `WwClass` is not moved or freed

You can make WwClass #[pin_data] & !Unpin as well.

> +    /// while any `WwMutex` instances using this class exist.
> +    pub unsafe fn new(name: &'static CStr, is_wait_die: bool) -> Self {
> +        Self(Opaque::new(bindings::ww_class {
> +            stamp: bindings::atomic_long_t { counter: 0 },
> +            acquire_name: name.as_char_ptr(),
> +            mutex_name: name.as_char_ptr(),
> +            is_wait_die: is_wait_die as u32,
> +
> +            // `lock_class_key` doesn't have any value
> +            acquire_key: bindings::lock_class_key {},
> +            mutex_key: bindings::lock_class_key {},
> +        }))
> +    }
> +}
> +
> +/// Implementation of C side `ww_acquire_ctx`.
> +///
> +/// An acquire context is used to group multiple mutex acquisitions together
> +/// for deadlock avoidance. It must be used when acquiring multiple mutexes
> +/// of the same class.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::sync::lock::ww_mutex::{WwClass, WwAcquireCtx, WwMutex};
> +/// use kernel::alloc::KBox;
> +/// use kernel::c_str;
> +///
> +/// let class = unsafe { WwClass::new(c_str!("my_class"), false) };
> +///
> +/// // Create mutexes
> +/// let mutex1 = unsafe { KBox::pin_init(WwMutex::new(1u32, &class), GFP_KERNEL).unwrap() };
> +/// let mutex2 = unsafe { KBox::pin_init(WwMutex::new(2u32, &class), GFP_KERNEL).unwrap() };
> +///
> +/// // Create acquire context for deadlock avoidance
> +/// let mut ctx = KBox::pin_init(
> +///     unsafe { WwAcquireCtx::new(&class) },
> +///     GFP_KERNEL
> +/// ).unwrap();
> +///
> +/// // Acquire multiple locks safely
> +/// let guard1 = mutex1.as_ref().lock(Some(&ctx)).unwrap();
> +/// let guard2 = mutex2.as_ref().lock(Some(&ctx)).unwrap();
> +///
> +/// // Mark acquisition phase as complete
> +/// ctx.as_mut().done();
> +///
> +/// # Ok::<(), Error>(())
> +/// ```
> +#[pin_data(PinnedDrop)]
> +pub struct WwAcquireCtx {
> +    #[pin]
> +    inner: Opaque<bindings::ww_acquire_ctx>,
> +    #[pin]
> +    _pin: PhantomPinned,
> +}
> +
> +// SAFETY: `WwAcquireCtx` is safe to send between threads when not in use.
> +unsafe impl Send for WwAcquireCtx {}
> +
> +impl WwAcquireCtx {
> +    /// Initializes `Self` with calling C side `ww_acquire_init` inside.
> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must ensure that the `ww_class` remains valid for the lifetime
> +    /// of this context.

You can make the type system check this for you by:

    pub struct WwAcquireCtx<'a> {
        #[pin]
        inner: Opaque<bindings::ww_acquire_ctx>,
        #[pin]
        _pin: PhantomPinned,
        _p: PhantomData<&'a WwClass>
    }

and

    impl<'ctx> WwAcquireCtx<'ctx> {
        pub fn new<'class: 'ctx>(ww_class: &'class WwClass) -> impl PinInit<Self> {
	    ...
	}
    }

the lifetime of the reference on WwClass should outlive the lifetime of
WwAcquireCtx.

Similar for WwMutex. BUT all the existing ww_classes are static,
alternatively, you can make Ww{AcquireCtx,Mutex}::new() take a `&'static
WwClass`.

Regards,
Boqun

> +    pub unsafe fn new(ww_class: &WwClass) -> impl PinInit<Self> {
> +        let raw_ptr = ww_class.0.get();
> +
> +        pin_init!(WwAcquireCtx {
> +            inner <- Opaque::ffi_init(|slot: *mut bindings::ww_acquire_ctx| {
> +                // SAFETY: The caller guarantees that `ww_class` remains valid.
> +                unsafe {
> +                    bindings::ww_acquire_init(slot, raw_ptr)
> +                }
> +            }),
> +            _pin: PhantomPinned,
> +        })
> +    }
> +
[...]

  reply	other threads:[~2025-06-16 17:58 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-16 16:24 [PATCH] Add `ww_mutex` support & abstraction for Rust tree onur-ozkan
2025-06-16 17:58 ` Boqun Feng [this message]
2025-06-17  7:03 ` kernel test robot

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=aFBbTMMTHrgHwVFJ@Mac.home \
    --to=boqun.feng@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=dakr@kernel.org \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=lossin@kernel.org \
    --cc=mingo@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=thatslyude@gmail.com \
    --cc=tmgross@umich.edu \
    --cc=will@kernel.org \
    --cc=work@onurozkan.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.