From fd571565d2c71c47a6894e31db84f2150b5f3e86 Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Tue, 15 Jun 2021 10:38:49 -0700 Subject: [PATCH] freedreno: Fix batch reference handling in flush_resource(). We take references under the lock, but then accessed the lock-requiring batch_cache structure without holding the lock. The batches wouldn't get freed and removed from their slots until the last ref goes away so it was safe (other than the assert at the end), but writing the simple code is shorter and requires fewer assumptions. Part-of: --- .../drivers/freedreno/freedreno_resource.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 74b0b10cf5b..d3981c15fd9 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -672,7 +672,7 @@ flush_resource(struct fd_context *ctx, struct fd_resource *rsc, if (usage & PIPE_MAP_WRITE) { struct fd_batch *batch, *batches[32] = {}; - uint32_t batch_mask; + uint32_t batch_count = 0; /* This is a bit awkward, probably a fd_batch_flush_locked() * would make things simpler.. but we need to hold the lock @@ -680,18 +680,14 @@ flush_resource(struct fd_context *ctx, struct fd_resource *rsc, * we must first grab references under a lock, then flush. */ fd_screen_lock(ctx->screen); - batch_mask = rsc->track->batch_mask; - foreach_batch (batch, &ctx->screen->batch_cache, batch_mask) - fd_batch_reference_locked(&batches[batch->idx], batch); + foreach_batch (batch, &ctx->screen->batch_cache, rsc->track->batch_mask) + fd_batch_reference_locked(&batches[batch_count++], batch); fd_screen_unlock(ctx->screen); - foreach_batch (batch, &ctx->screen->batch_cache, batch_mask) - fd_batch_flush(batch); - - foreach_batch (batch, &ctx->screen->batch_cache, batch_mask) { - fd_batch_reference(&batches[batch->idx], NULL); + for (int i = 0; i < batch_count; i++) { + fd_batch_flush(batches[i]); + fd_batch_reference(&batches[i], NULL); } - assert(rsc->track->batch_mask == 0); } else if (write_batch) { fd_batch_flush(write_batch); }