Skip to content

Commit 38cb08c

Browse files
LyudeDanilo Krummrich
authored andcommitted
rust: drm: gem: Implement AlwaysRefCounted for all gem objects automatically
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 <[email protected]> Reviewed-by: Daniel Almeida <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent b36ff40 commit 38cb08c

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

rust/kernel/drm/gem/mod.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
drm::driver::{AllocImpl, AllocOps},
1111
error::{to_result, Result},
1212
prelude::*,
13-
types::{ARef, Opaque},
13+
types::{ARef, AlwaysRefCounted, Opaque},
1414
};
1515
use core::{mem, ops::Deref, ptr::NonNull};
1616

@@ -36,7 +36,7 @@ pub trait BaseDriverObject<T: BaseObject>: Sync + Send + Sized {
3636
}
3737

3838
/// Trait that represents a GEM object subtype
39-
pub trait IntoGEMObject: Sized + super::private::Sealed {
39+
pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted {
4040
/// Owning driver for this type
4141
type Driver: drm::Driver;
4242

@@ -54,6 +54,26 @@ pub trait IntoGEMObject: Sized + super::private::Sealed {
5454
unsafe fn as_ref<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self;
5555
}
5656

57+
// SAFETY: All gem objects are refcounted.
58+
unsafe impl<T: IntoGEMObject> AlwaysRefCounted for T {
59+
fn inc_ref(&self) {
60+
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
61+
unsafe { bindings::drm_gem_object_get(self.as_raw()) };
62+
}
63+
64+
unsafe fn dec_ref(obj: NonNull<Self>) {
65+
// SAFETY: We either hold the only refcount on `obj`, or one of many - meaning that no one
66+
// else could possibly hold a mutable reference to `obj` and thus this immutable reference
67+
// is safe.
68+
let obj = unsafe { obj.as_ref() }.as_raw();
69+
70+
// SAFETY:
71+
// - The safety requirements guarantee that the refcount is non-zero.
72+
// - We hold no references to `obj` now, making it safe for us to potentially deallocate it.
73+
unsafe { bindings::drm_gem_object_put(obj) };
74+
}
75+
}
76+
5777
/// Trait which must be implemented by drivers using base GEM objects.
5878
pub trait DriverObject: BaseDriverObject<Object<Self>> {
5979
/// Parent `Driver` for this object.
@@ -112,10 +132,7 @@ impl<T: DriverObject> IntoGEMObject for Object<T> {
112132
}
113133

114134
/// Base operations shared by all GEM object classes
115-
pub trait BaseObject
116-
where
117-
Self: crate::types::AlwaysRefCounted + IntoGEMObject,
118-
{
135+
pub trait BaseObject: IntoGEMObject {
119136
/// Returns the size of the object in bytes.
120137
fn size(&self) -> usize {
121138
// SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
@@ -172,7 +189,7 @@ where
172189
}
173190
}
174191

175-
impl<T> BaseObject for T where Self: crate::types::AlwaysRefCounted + IntoGEMObject {}
192+
impl<T: IntoGEMObject> BaseObject for T {}
176193

177194
/// A base GEM object.
178195
///
@@ -266,22 +283,6 @@ impl<T: DriverObject> Object<T> {
266283
}
267284
}
268285

269-
// SAFETY: Instances of `Object<T>` are always reference-counted.
270-
unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> {
271-
fn inc_ref(&self) {
272-
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
273-
unsafe { bindings::drm_gem_object_get(self.as_raw()) };
274-
}
275-
276-
unsafe fn dec_ref(obj: NonNull<Self>) {
277-
// SAFETY: `obj` is a valid pointer to an `Object<T>`.
278-
let obj = unsafe { obj.as_ref() };
279-
280-
// SAFETY: The safety requirements guarantee that the refcount is non-zero.
281-
unsafe { bindings::drm_gem_object_put(obj.as_raw()) }
282-
}
283-
}
284-
285286
impl<T: DriverObject> super::private::Sealed for Object<T> {}
286287

287288
impl<T: DriverObject> Deref for Object<T> {

0 commit comments

Comments
 (0)