Re: [PATCH v8 5/6] rust: ww_mutex: add Mutex, AcquireCtx and MutexGuard
From: Daniel Almeida
Date: Wed Dec 03 2025 - 12:23:58 EST
> On 3 Dec 2025, at 10:26, Alice Ryhl <aliceryhl@xxxxxxxxxx> wrote:
>
> On Mon, Dec 01, 2025 at 01:28:54PM +0300, Onur Özkan wrote:
>> Covers the entire low-level locking API (lock, try_lock,
>> slow path, interruptible variants) and integration with
>> kernel bindings.
>>
>> Signed-off-by: Onur Özkan <work@xxxxxxxxxxxxx>
>
>> +impl<'class> Mutex<'class, ()> {
>> + /// Creates a [`Mutex`] from a raw pointer.
>> + ///
>> + /// This function is intended for interoperability with C code.
>> + ///
>> + /// # Safety
>> + ///
>> + /// The caller must ensure that `ptr` is a valid pointer to a `ww_mutex`
>> + /// and that it remains valid for the lifetime `'a`.
>> + pub unsafe fn from_raw<'a>(ptr: *mut bindings::ww_mutex) -> &'a Self {
>
> Should also require that the class is valid for the duration of 'class.
>
>> +/// Internal helper that unifies the different locking kinds.
>> +///
>> +/// Returns [`EINVAL`] if the [`Mutex`] has a different [`Class`].
>> +fn lock_common<'a, T: ?Sized>(
>> + mutex: &'a Mutex<'a, T>,
>> + ctx: Option<&AcquireCtx<'_>>,
>> + kind: LockKind,
>> +) -> Result<MutexGuard<'a, T>> {
>> + let mutex_ptr = mutex.inner.get();
>> +
>> + let ctx_ptr = match ctx {
>> + Some(acquire_ctx) => {
>> + let ctx_ptr = acquire_ctx.inner.get();
>> +
>> + // SAFETY: `ctx_ptr` is a valid pointer for the entire
>> + // lifetime of `ctx`.
>> + let ctx_class = unsafe { (*ctx_ptr).ww_class };
>> +
>> + // SAFETY: `mutex_ptr` is a valid pointer for the entire
>> + // lifetime of `mutex`.
>> + let mutex_class = unsafe { (*mutex_ptr).ww_class };
>> +
>> + // `ctx` and `mutex` must use the same class.
>> + if ctx_class != mutex_class {
>> + return Err(EINVAL);
>> + }
>
> Hmm, this originates from the previous conversation:
>
> https://lore.kernel.org/all/20251124184928.30b8bbaf@nimda/
>>>> + /// // SAFETY: Both `lock_set` and `mutex1` uses the
>>>> same class.
>>>> + /// unsafe { lock_set.lock(&mutex1)? };
>>>> + ///
>>>> + /// // SAFETY: Both `lock_set` and `mutex2` uses the
>>>> same class.
>>>> + /// unsafe { lock_set.lock(&mutex2)? };
>>>
>>> I wonder if there's some way we can get rid of the safety contract
>>> here and verify this at compile time, it would be a shame if every
>>> single lock invocation needed to be unsafe.
>>>
>>
>> Yeah :(. We could get rid of them easily by keeping the class that was
>> passed to the constructor functions but that becomes a problem for the
>> from_raw implementations.
>>
>> I think the best solution would be to expose ww_class type from
>> ww_acquire_ctx and ww_mutex unconditionally (right now it depends on
>> DEBUG_WW_MUTEXES). That way we can just access the class and verify
>> that the mutex and acquire_ctx classes match.
>>
>> What do you think? I can submit a patch for the C-side implementation.
>> It should be straightforward and shouldn't have any runtime impact.
>
> I think there is a better solution. We can create a different type for
> every single class, like how rust/kernel/sync/lock/global.rs creates a
> different type for every single mutex. Then, you know that the classes
> are the same since the class is part of the type.
I don’t think this would work with the from_raw() functions. What class
would you assign then? I think this is precisely what sparked the current
solution.
>
> Alice