diff options
author | Mike Blumenkrantz <michael.blumenkrantz@gmail.com> | 2021-10-19 13:57:39 -0400 |
---|---|---|
committer | Eric Engestrom <eric@engestrom.ch> | 2021-10-20 20:40:59 +0100 |
commit | f8b5444a09a0cee9e25bd02339d081c20c70823b (patch) | |
tree | 4ef8ea90f6cf62f6ffb48aeced63152cfbde6cf9 | |
parent | f1b779361c589039f3a6196ec8b67265b5746710 (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.json | 2 | ||||
-rw-r--r-- | src/gallium/drivers/zink/zink_context.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/zink/zink_surface.c | 5 |
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); |