From a192923f99e1f0c929b385fefd235453b44a3924 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 27 Jan 2023 09:50:43 -0800 Subject: [PATCH] freedreno/drm: Restart import on zombie race If we hit the race condition of looking up an already imported BO that is in the process of being destroyed, the handle will be GEM_CLOSE'd, meaning that the handle that we just got from the kernel is probably not valid. So in this case we should retry. Signed-off-by: Rob Clark Part-of: --- src/freedreno/drm/freedreno_bo.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index a875ba4a48e..0e78ad94410 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -41,6 +41,8 @@ set_name(struct fd_bo *bo, uint32_t name) _mesa_hash_table_insert(bo->dev->name_table, &bo->name, bo); } +static struct fd_bo zombie; + /* lookup a buffer, call w/ table_lock held: */ static struct fd_bo * lookup_bo(struct hash_table *tbl, uint32_t key) @@ -62,8 +64,7 @@ lookup_bo(struct hash_table *tbl, uint32_t key) * checking for refcnt==0. */ if (bo->refcnt == 0) { - bo->handle = 0; - return NULL; + return &zombie; } /* found, incr refcnt and return: */ @@ -211,6 +212,12 @@ fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size) out_unlock: simple_mtx_unlock(&table_lock); + /* We've raced with the handle being closed, so the handle is no longer + * valid. Friends don't let friends share handles. + */ + if (bo == &zombie) + return NULL; + return bo; } @@ -221,6 +228,7 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd) uint32_t handle; struct fd_bo *bo; +restart: simple_mtx_lock(&table_lock); ret = drmPrimeFDToHandle(dev->fd, fd, &handle); if (ret) { @@ -243,6 +251,9 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd) out_unlock: simple_mtx_unlock(&table_lock); + if (bo == &zombie) + goto restart; + return bo; } @@ -261,6 +272,7 @@ fd_bo_from_name(struct fd_device *dev, uint32_t name) if (bo) goto out_unlock; +restart: if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { ERROR_MSG("gem-open failed: %s", strerror(errno)); goto out_unlock; @@ -279,6 +291,9 @@ fd_bo_from_name(struct fd_device *dev, uint32_t name) out_unlock: simple_mtx_unlock(&table_lock); + if (bo == &zombie) + goto restart; + return bo; }