[Mesa-dev] [PATCH 7/8] i965/bufmgr: Don't allow busy BOs to be returned to the pool

Jason Ekstrand jason at jlekstrand.net
Wed Jun 13 20:26:59 UTC 2018


---
 src/mesa/drivers/dri/i965/brw_bufmgr.c | 51 ++++++++++++++++----------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
index cfa32ff3726..ef918315c65 100644
--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
+++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
@@ -524,6 +524,14 @@ bo_alloc_internal(struct brw_bufmgr *bufmgr,
          bo_size = page_size;
    } else {
       bo_size = bucket->size;
+
+      /* If there's nothing in the bucket, call bufmgr_collect in the hopes
+       * that maybe we can free and re-use an old BO.  It should be safe to
+       * call list_empty() without taking a lock since it's just a pointer
+       * comparison and nothing bad will happen if we get it wrong.
+       */
+      if (list_empty(&bucket->head))
+         brw_bufmgr_collect(bufmgr);
    }
 
    mtx_lock(&bufmgr->lock);
@@ -539,31 +547,29 @@ retry:
        * waiting for the GPU to finish.
        */
       bo = LIST_ENTRY(struct brw_bo, bucket->head.next, head);
-      if (!brw_bo_busy(bo)) {
-         alloc_from_cache = true;
-         list_del(&bo->head);
+      assert(!brw_bo_busy(bo));
+
+      alloc_from_cache = true;
+      list_del(&bo->head);
+
+      if (!brw_bo_madvise(bo, I915_MADV_WILLNEED)) {
+         bo_free(bo);
+         brw_bo_cache_purge_bucket(bufmgr, bucket);
+         goto retry;
       }
 
-      if (alloc_from_cache) {
-         if (!brw_bo_madvise(bo, I915_MADV_WILLNEED)) {
-            bo_free(bo);
-            brw_bo_cache_purge_bucket(bufmgr, bucket);
-            goto retry;
-         }
+      if (bo_set_tiling_internal(bo, tiling_mode, stride)) {
+         bo_free(bo);
+         goto retry;
+      }
 
-         if (bo_set_tiling_internal(bo, tiling_mode, stride)) {
+      if (zeroed) {
+         void *map = brw_bo_map(NULL, bo, MAP_WRITE | MAP_RAW);
+         if (!map) {
             bo_free(bo);
             goto retry;
          }
-
-         if (zeroed) {
-            void *map = brw_bo_map(NULL, bo, MAP_WRITE | MAP_RAW);
-            if (!map) {
-               bo_free(bo);
-               goto retry;
-            }
-            memset(map, 0, bo_size);
-         }
+         memset(map, 0, bo_size);
       }
    }
 
@@ -871,6 +877,13 @@ bo_unreference_final(struct brw_bo *bo, time_t time)
 
    DBG("bo_unreference final: %d (%s)\n", bo->gem_handle, bo->name);
 
+   /* The only way an internal BO can be busy is if it's in use by one of our
+    * (this screen's) batch buffers.  Since we always wait for the batch to be
+    * idle before we unref the BOs it references, we can never get here with a
+    * busy internal BO.
+    */
+   assert(bo->external || !brw_bo_busy(bo));
+
    bucket = bucket_for_size(bufmgr, bo->size);
    /* Put the buffer into our internal cache for reuse if we can. */
    if (bufmgr->bo_reuse && bo->reusable && bucket != NULL &&
-- 
2.17.1



More information about the mesa-dev mailing list