Hi Lyude, > On 1 May 2025, at 15:33, Lyude Paul <ly...@redhat.com> wrote: > > Currently we are requiring AlwaysRefCounted in most trait bounds for gem > objects, and implementing it by hand for our only current type of gem > object. However, all gem objects use the same functions for reference > counting - and all gem objects support reference counting. > > We're planning on adding support for shmem gem objects, let's move this > around a bit by instead making IntoGEMObject require AlwaysRefCounted as a > trait bound, and then provide a blanket AlwaysRefCounted implementation for > any object that implements IntoGEMObject so all gem object types can use > the same AlwaysRefCounted implementation. This also makes things less > verbose by making the AlwaysRefCounted trait bound implicit for any > IntoGEMObject bound. > > Signed-off-by: Lyude Paul <ly...@redhat.com> > --- > rust/kernel/drm/gem/mod.rs | 47 +++++++++++++++++++------------------- > 1 file changed, 24 insertions(+), 23 deletions(-) > > diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs > index 55b2f1d056c39..929f6c9718362 100644 > --- a/rust/kernel/drm/gem/mod.rs > +++ b/rust/kernel/drm/gem/mod.rs > @@ -10,7 +10,7 @@ > drm::driver::{AllocImpl, AllocOps}, > error::{to_result, Result}, > prelude::*, > - types::{ARef, Opaque}, > + types::{ARef, AlwaysRefCounted, Opaque}, > }; > use core::{mem, ops::Deref, ptr, ptr::NonNull}; > > @@ -36,7 +36,7 @@ fn close( > } > > /// Trait that represents a GEM object subtype > -pub trait IntoGEMObject: Sized + super::private::Sealed { > +pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted { > /// Owning driver for this type > type Driver: drm::Driver; > > @@ -52,6 +52,26 @@ pub trait IntoGEMObject: Sized + super::private::Sealed { > unsafe fn as_ref<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self; > } > > +// SAFETY: All gem objects are refcounted. > +unsafe impl<T: IntoGEMObject> AlwaysRefCounted for T { > + fn inc_ref(&self) { > + // SAFETY: The existence of a shared reference guarantees that the > refcount is non-zero. > + unsafe { bindings::drm_gem_object_get(self.as_gem_obj()) }; > + } > + > + unsafe fn dec_ref(obj: NonNull<Self>) { > + // SAFETY: We either hold the only refcount on `obj`, or one of many > - meaning that no one > + // else could possibly hold a mutable reference to `obj` and thus > this immutable reference > + // is safe. > + let obj = unsafe { obj.as_ref() }.as_gem_obj(); > + > + // SAFETY: > + // - The safety requirements guarantee that the refcount is non-zero. > + // - We hold no references to `obj` now, making it safe for us to > potentially deallocate it. > + unsafe { bindings::drm_gem_object_put(obj) }; > + } > +} > + > /// Trait which must be implemented by drivers using base GEM objects. > pub trait DriverObject: BaseDriverObject<Object<Self>> { > /// Parent `Driver` for this object. > @@ -110,10 +130,7 @@ unsafe fn as_ref<'a>(self_ptr: *mut > bindings::drm_gem_object) -> &'a Self { > } > > /// Base operations shared by all GEM object classes > -pub trait BaseObject > -where > - Self: crate::types::AlwaysRefCounted + IntoGEMObject, > -{ > +pub trait BaseObject: IntoGEMObject { > /// Returns the size of the object in bytes. > fn size(&self) -> usize { > // SAFETY: `self.into_gem_obj()` is guaranteed to be a pointer to a > valid `struct > @@ -175,7 +192,7 @@ fn create_mmap_offset(&self) -> Result<u64> { > } > } > > -impl<T> BaseObject for T where Self: crate::types::AlwaysRefCounted + > IntoGEMObject {} > +impl<T: IntoGEMObject> BaseObject for T {} > > /// A base GEM object. > /// > @@ -269,22 +286,6 @@ extern "C" fn free_callback(obj: *mut > bindings::drm_gem_object) { > } > } > > -// SAFETY: Instances of `Object<T>` are always reference-counted. > -unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> { > - fn inc_ref(&self) { > - // SAFETY: The existence of a shared reference guarantees that the > refcount is non-zero. > - unsafe { bindings::drm_gem_object_get(self.as_raw()) }; > - } > - > - unsafe fn dec_ref(obj: NonNull<Self>) { > - // SAFETY: `obj` is a valid pointer to an `Object<T>`. > - let obj = unsafe { obj.as_ref() }; > - > - // SAFETY: The safety requirements guarantee that the refcount is > non-zero. > - unsafe { bindings::drm_gem_object_put(obj.as_raw()) } > - } > -} > - > impl<T: DriverObject> super::private::Sealed for Object<T> {} > > impl<T: DriverObject> Deref for Object<T> { > -- > 2.48.1 > >
Reviewed-by: Daniel Almeida <daniel.alme...@collabora.com>