1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2024 Google LLC. 4 5 //! Version of `MmWithUser` using `mmput_async`. 6 //! 7 //! This is a separate file from `mm.rs` due to the dependency on `CONFIG_MMU=y`. 8 #![cfg(CONFIG_MMU)] 9 10 use crate::{ 11 bindings, 12 mm::MmWithUser, 13 types::{ARef, AlwaysRefCounted}, 14 }; 15 use core::{ops::Deref, ptr::NonNull}; 16 17 /// A wrapper for the kernel's `struct mm_struct`. 18 /// 19 /// This type is identical to `MmWithUser` except that it uses `mmput_async` when dropping a 20 /// refcount. This means that the destructor of `ARef<MmWithUserAsync>` is safe to call in atomic 21 /// context. 22 /// 23 /// # Invariants 24 /// 25 /// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero. 26 #[repr(transparent)] 27 pub struct MmWithUserAsync { 28 mm: MmWithUser, 29 } 30 31 // SAFETY: It is safe to call `mmput_async` on another thread than where `mmget` was called. 32 unsafe impl Send for MmWithUserAsync {} 33 // SAFETY: All methods on `MmWithUserAsync` can be called in parallel from several threads. 34 unsafe impl Sync for MmWithUserAsync {} 35 36 // SAFETY: By the type invariants, this type is always refcounted. 37 unsafe impl AlwaysRefCounted for MmWithUserAsync { 38 #[inline] inc_ref(&self)39 fn inc_ref(&self) { 40 // SAFETY: The pointer is valid since self is a reference. 41 unsafe { bindings::mmget(self.as_raw()) }; 42 } 43 44 #[inline] dec_ref(obj: NonNull<Self>)45 unsafe fn dec_ref(obj: NonNull<Self>) { 46 // SAFETY: The caller is giving up their refcount. 47 unsafe { bindings::mmput_async(obj.cast().as_ptr()) }; 48 } 49 } 50 51 // Make all `MmWithUser` methods available on `MmWithUserAsync`. 52 impl Deref for MmWithUserAsync { 53 type Target = MmWithUser; 54 55 #[inline] deref(&self) -> &MmWithUser56 fn deref(&self) -> &MmWithUser { 57 &self.mm 58 } 59 } 60 61 impl MmWithUser { 62 /// Use `mmput_async` when dropping this refcount. 63 #[inline] into_mmput_async(me: ARef<MmWithUser>) -> ARef<MmWithUserAsync>64 pub fn into_mmput_async(me: ARef<MmWithUser>) -> ARef<MmWithUserAsync> { 65 // SAFETY: The layouts and invariants are compatible. 66 unsafe { ARef::from_raw(ARef::into_raw(me).cast()) } 67 } 68 } 69