freedreno/drm: Add some ref/unref debugging

Helpful to catch common refcnt issues, like resurrecting a zombie
object.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20918>
This commit is contained in:
Rob Clark 2023-01-25 11:39:06 -08:00 committed by Marge Bot
parent 870beb2159
commit 547f50c244
4 changed files with 32 additions and 9 deletions

View file

@ -273,7 +273,7 @@ fd_bo_mark_for_dump(struct fd_bo *bo)
struct fd_bo *
fd_bo_ref(struct fd_bo *bo)
{
p_atomic_inc(&bo->refcnt);
ref(&bo->refcnt);
return bo;
}
@ -302,7 +302,7 @@ bo_del_or_recycle(struct fd_bo *bo)
void
fd_bo_del(struct fd_bo *bo)
{
if (!p_atomic_dec_zero(&bo->refcnt))
if (!unref(&bo->refcnt))
return;
struct fd_device *dev = bo->dev;
@ -323,7 +323,7 @@ fd_bo_del_array(struct fd_bo **bos, unsigned count)
unsigned cnt = 0;
for (unsigned i = 0; i < count; i++) {
if (!p_atomic_dec_zero(&bos[i]->refcnt))
if (!unref(&bos[i]->refcnt))
continue;
if (cnt == ARRAY_SIZE(handles)) {
close_handles(dev, handles, cnt);

View file

@ -157,7 +157,7 @@ fd_device_open(void)
struct fd_device *
fd_device_ref(struct fd_device *dev)
{
p_atomic_inc(&dev->refcnt);
ref(&dev->refcnt);
return dev;
}
@ -171,7 +171,7 @@ fd_device_purge(struct fd_device *dev)
void
fd_device_del(struct fd_device *dev)
{
if (!p_atomic_dec_zero(&dev->refcnt))
if (!unref(&dev->refcnt))
return;
assert(list_is_empty(&dev->deferred_submits));

View file

@ -42,7 +42,7 @@ fd_submit_new(struct fd_pipe *pipe)
void
fd_submit_del(struct fd_submit *submit)
{
if (!p_atomic_dec_zero(&submit->refcnt))
if (!unref(&submit->refcnt))
return;
if (submit->primary)
@ -56,7 +56,7 @@ fd_submit_del(struct fd_submit *submit)
struct fd_submit *
fd_submit_ref(struct fd_submit *submit)
{
p_atomic_inc(&submit->refcnt);
ref(&submit->refcnt);
return submit;
}

View file

@ -139,10 +139,33 @@ struct fd_ringbuffer {
struct fd_ringbuffer *fd_ringbuffer_new_object(struct fd_pipe *pipe,
uint32_t size);
/*
* Helpers for ref/unref with some extra debugging.. unref() returns true if
* the object is still live
*/
static inline void
ref(int32_t *ref)
{
ASSERTED int32_t count = p_atomic_inc_return(ref);
/* We should never see a refcnt transition 0->1, this is a sign of a
* zombie coming back from the dead!
*/
assert(count != 1);
}
static inline bool
unref(int32_t *ref)
{
int32_t count = p_atomic_dec_return(ref);
assert(count != -1);
return count == 0;
}
static inline void
fd_ringbuffer_del(struct fd_ringbuffer *ring)
{
if (!p_atomic_dec_zero(&ring->refcnt))
if (!unref(&ring->refcnt))
return;
ring->funcs->destroy(ring);
@ -151,7 +174,7 @@ fd_ringbuffer_del(struct fd_ringbuffer *ring)
static inline struct fd_ringbuffer *
fd_ringbuffer_ref(struct fd_ringbuffer *ring)
{
p_atomic_inc(&ring->refcnt);
ref(&ring->refcnt);
return ring;
}