rust: drm: Add gem::impl_aref_for_gem_obj!

In the future we're going to be introducing more GEM object types in rust
then just gem::Object<T>. Since all types of GEM objects have refcounting,
let's introduce a macro that we can use in the gem crate in order to copy
this boilerplate implementation for each type: impl_aref_for_gem_obj!().

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Janne Grunau <j@jananu.net>
Tested-by: Deborah Brouwer <deborah.brouwer@collabora.com>
Link: https://patch.msgid.link/20260316211646.650074-2-lyude@redhat.com
[ Resolve merge conflicts. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Lyude Paul
2026-03-16 17:16:09 -04:00
committed by Danilo Krummrich
parent dff8302ca1
commit e64b9cc293

View File

@@ -26,6 +26,41 @@
ptr::NonNull, //
};
/// A macro for implementing [`AlwaysRefCounted`] for any GEM object type.
///
/// Since all GEM objects use the same refcounting scheme.
#[macro_export]
macro_rules! impl_aref_for_gem_obj {
(
impl $( <$( $tparam_id:ident ),+> )? for $type:ty
$(
where
$( $bind_param:path : $bind_trait:path ),+
)?
) => {
// SAFETY: All GEM objects are refcounted.
unsafe impl $( <$( $tparam_id ),+> )? $crate::types::AlwaysRefCounted for $type
where
Self: IntoGEMObject,
$( $( $bind_param : $bind_trait ),+ )?
{
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: core::ptr::NonNull<Self>) {
// SAFETY: `obj` is a valid pointer to an `Object<T>`.
let obj = unsafe { obj.as_ref() }.as_raw();
// SAFETY: The safety requirements guarantee that the refcount is non-zero.
unsafe { bindings::drm_gem_object_put(obj) };
}
}
};
}
/// A type alias for retrieving a [`Driver`]s [`DriverFile`] implementation from its
/// [`DriverObject`] implementation.
///
@@ -263,21 +298,7 @@ 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::sync::aref::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_aref_for_gem_obj!(impl<T> for Object<T> where T: DriverObject);
impl<T: DriverObject> super::private::Sealed for Object<T> {}