aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <[email protected]>2019-08-09 15:34:31 +0200
committerLucas Stach <[email protected]>2019-10-18 17:03:25 +0000
commit9e672e4d20fb77e1b39aee29f9e8e76a5c2af68e (patch)
tree5c24325d2771197d93fb1f10c419b615365885ee
parent90e223646bf9541c4b751bcbd04cd81e27fb42e1 (diff)
etnaviv: keep references to pending resources
As long as a resource is pending in any context we must not destroy it, otherwise we'll hit a classical use-after-free with fireworks. To avoid this take a reference when the resource is first added to the pending set and put the reference when no longer pending. Signed-off-by: Lucas Stach <[email protected]> Reviewed-by: Jonathan Marek <[email protected]>
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_context.c3
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_resource.c18
2 files changed, 10 insertions, 11 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index 219d1de45f0..d2519f11a5a 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -425,10 +425,13 @@ etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
mtx_lock(&screen->lock);
set_foreach(ctx->used_resources, entry) {
struct etna_resource *rsc = (struct etna_resource *)entry->key;
+ struct pipe_resource *referenced = &rsc->base;
rsc->status = 0;
_mesa_set_remove_key(rsc->pending_ctx, ctx);
+
+ pipe_resource_reference(&referenced, NULL);
}
_mesa_set_clear(ctx->used_resources, NULL);
mtx_unlock(&screen->lock);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index 3a58808d743..4ccf887f600 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -464,17 +464,9 @@ etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc)
static void
etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
{
- struct etna_screen *screen = etna_screen(pscreen);
struct etna_resource *rsc = etna_resource(prsc);
- mtx_lock(&screen->lock);
- set_foreach(rsc->pending_ctx, entry) {
- struct etna_context *ctx = (struct etna_context *)entry->key;
-
- _mesa_set_remove_key(rsc->pending_ctx, ctx);
- }
- _mesa_set_destroy(rsc->pending_ctx, NULL);
- mtx_unlock(&screen->lock);
+ assert(!_mesa_set_next_entry(rsc->pending_ctx, NULL));
if (rsc->bo)
etna_bo_del(rsc->bo);
@@ -618,6 +610,7 @@ etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
enum etna_resource_status status)
{
struct etna_screen *screen = ctx->screen;
+ struct pipe_resource *referenced = NULL;
struct etna_resource *rsc;
if (!prsc)
@@ -654,8 +647,11 @@ etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
rsc->status |= status;
- _mesa_set_add(ctx->used_resources, rsc);
- _mesa_set_add(rsc->pending_ctx, ctx);
+ if (!_mesa_set_search(rsc->pending_ctx, ctx)) {
+ pipe_resource_reference(&referenced, prsc);
+ _mesa_set_add(ctx->used_resources, rsc);
+ _mesa_set_add(rsc->pending_ctx, ctx);
+ }
mtx_unlock(&screen->lock);
}