freedreno/drm: Detect zombie BOs

When importing from a GEM name or dmabuf fd, we can race with the final
unref of the same BO, in which case we can get a hit in the handle
table for an fd_bo that another thread is about to free().  Detect and
handle this case.

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:57:28 -08:00 committed by Marge Bot
parent 547f50c244
commit 160137ccae

View file

@ -46,10 +46,28 @@ static struct fd_bo *
lookup_bo(struct hash_table *tbl, uint32_t key)
{
struct fd_bo *bo = NULL;
struct hash_entry *entry = _mesa_hash_table_search(tbl, &key);
struct hash_entry *entry;
simple_mtx_assert_locked(&table_lock);
entry = _mesa_hash_table_search(tbl, &key);
if (entry) {
bo = entry->data;
/* We could be racing with final unref in another thread, and won
* the table_lock preventing the other thread from being able to
* remove an object it is about to free. Fortunately since table
* lookup and removal are protected by the same lock (and table
* removal happens before obj free) we can easily detect this by
* checking for refcnt==0.
*/
if (bo->refcnt == 0) {
bo->handle = 0;
return NULL;
}
/* found, incr refcnt and return: */
bo = fd_bo_ref(entry->data);
fd_bo_ref(bo);
if (!list_is_empty(&bo->node)) {
mesa_logw("bo was in cache, size=%u, alloc_flags=0x%x\n",