summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>2021-10-19 13:57:39 -0400
committerEric Engestrom <eric@engestrom.ch>2021-10-20 20:40:59 +0100
commitf8b5444a09a0cee9e25bd02339d081c20c70823b (patch)
tree4ef8ea90f6cf62f6ffb48aeced63152cfbde6cf9
parentf1b779361c589039f3a6196ec8b67265b5746710 (diff)
zink: rescue surfaces/bufferviews for cache hits during deletion
this is a wild race condition, but it's possible for these to get their final unref, enter their destructor, and then get a cache hit while waiting on the lock to remove themselves from the cache in such a scenario, a second, normal check of the refcount will suffice, as the increment is atomic, and the value will otherwise be zero fixes crashes in basemark cc: mesa-stable Reviewed-by: Hoe Hao Cheng <haochengho12907@gmail.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13442> (cherry picked from commit 86b3d8c66ce17ddcaefa5bdea68882cc03a57f15)
-rw-r--r--.pick_status.json2
-rw-r--r--src/gallium/drivers/zink/zink_context.c5
-rw-r--r--src/gallium/drivers/zink/zink_surface.c5
3 files changed, 11 insertions, 1 deletions
diff --git a/.pick_status.json b/.pick_status.json
index 00a551de6ec..2505134e7b0 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -4,7 +4,7 @@
"description": "zink: rescue surfaces/bufferviews for cache hits during deletion",
"nominated": true,
"nomination_type": 0,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": null
},
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 58fbc220624..56211a4d0ee 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -777,6 +777,11 @@ zink_destroy_buffer_view(struct zink_screen *screen, struct zink_buffer_view *bu
{
struct zink_resource *res = zink_resource(buffer_view->pres);
simple_mtx_lock(&res->bufferview_mtx);
+ if (buffer_view->reference.count) {
+ /* got a cache hit during deletion */
+ simple_mtx_unlock(&res->bufferview_mtx);
+ return;
+ }
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&res->bufferview_cache, buffer_view->hash, &buffer_view->bvci);
assert(he);
_mesa_hash_table_remove(&res->bufferview_cache, he);
diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c
index 08dc0057ffa..e7af9963529 100644
--- a/src/gallium/drivers/zink/zink_surface.c
+++ b/src/gallium/drivers/zink/zink_surface.c
@@ -281,6 +281,11 @@ zink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface)
struct zink_resource *res = zink_resource(psurface->texture);
if (!psurface->nr_samples) {
simple_mtx_lock(&res->surface_mtx);
+ if (psurface->reference.count) {
+ /* got a cache hit during deletion */
+ simple_mtx_unlock(&res->surface_mtx);
+ return;
+ }
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&res->surface_cache, surface->hash, &surface->ivci);
assert(he);
assert(he->data == surface);