[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