diff options
author | Lucas Stach <[email protected]> | 2019-08-09 15:34:31 +0200 |
---|---|---|
committer | Lucas Stach <[email protected]> | 2019-10-18 17:03:25 +0000 |
commit | 9e672e4d20fb77e1b39aee29f9e8e76a5c2af68e (patch) | |
tree | 5c24325d2771197d93fb1f10c419b615365885ee /src/gallium/drivers/etnaviv | |
parent | 90e223646bf9541c4b751bcbd04cd81e27fb42e1 (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]>
Diffstat (limited to 'src/gallium/drivers/etnaviv')
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_context.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_resource.c | 18 |
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); } |