[Mesa-dev] [PATCH 3/3] r600g, radeonsi: attempt to fix racy multi-context apps calling BufferData

Marek Olšák maraeo at gmail.com
Sat Mar 8 17:24:53 PST 2014


From: Marek Olšák <marek.olsak at amd.com>

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75061
---
 src/gallium/drivers/r600/r600_state_common.c    |  5 +----
 src/gallium/drivers/radeon/r600_buffer_common.c | 20 +++++++++++++++-----
 src/gallium/drivers/radeonsi/si_descriptors.c   |  5 +----
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 96c1880..7dbb0b7 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -2292,10 +2292,7 @@ static void r600_invalidate_buffer(struct pipe_context *ctx, struct pipe_resourc
 	struct r600_resource *rbuffer = r600_resource(buf);
 	unsigned i, shader, mask, alignment = rbuffer->buf->alignment;
 
-	/* Discard the buffer. */
-	pb_reference(&rbuffer->buf, NULL);
-
-	/* Create a new one in the same pipe_resource. */
+	/* Reallocate the buffer in the same pipe_resource. */
 	r600_init_resource(&rctx->screen->b, rbuffer, rbuffer->b.b.width0,
 			   alignment, TRUE);
 
diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c
index d56a644..f9423ae 100644
--- a/src/gallium/drivers/radeon/r600_buffer_common.c
+++ b/src/gallium/drivers/radeon/r600_buffer_common.c
@@ -106,6 +106,7 @@ bool r600_init_resource(struct r600_common_screen *rscreen,
 			bool use_reusable_pool)
 {
 	struct r600_texture *rtex = (struct r600_texture*)res;
+	struct pb_buffer *old_buf, *new_buf;
 
 	switch (res->b.b.usage) {
 	case PIPE_USAGE_STAGING:
@@ -136,15 +137,23 @@ bool r600_init_resource(struct r600_common_screen *rscreen,
 		res->domains = RADEON_DOMAIN_VRAM;
 	}
 
-	/* Allocate the resource. */
-	res->buf = rscreen->ws->buffer_create(rscreen->ws, size, alignment,
-                                              use_reusable_pool,
-                                              res->domains);
-	if (!res->buf) {
+	/* Allocate a new resource. */
+	new_buf = rscreen->ws->buffer_create(rscreen->ws, size, alignment,
+					     use_reusable_pool,
+					     res->domains);
+	if (!new_buf) {
 		return false;
 	}
 
+	/* Replace the pointer such that if res->buf wasn't NULL, it won't be
+	 * NULL. This should prevent crashes with multiple contexts using
+	 * the same buffer where one of the contexts invalidates it while
+	 * the others are using it. */
+	old_buf = res->buf;
+	res->buf = new_buf; /* this should be atomic */
 	res->cs_buf = rscreen->ws->buffer_get_cs_handle(res->buf);
+	pb_reference(&old_buf, NULL);
+
 	util_range_set_empty(&res->valid_buffer_range);
 
 	if (rscreen->debug_flags & DBG_VM && res->b.b.target == PIPE_BUFFER) {
@@ -363,6 +372,7 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
 	pipe_reference_init(&rbuffer->b.b.reference, 1);
 	rbuffer->b.b.screen = screen;
 	rbuffer->b.vtbl = &r600_buffer_vtbl;
+	rbuffer->buf = NULL;
 	util_range_init(&rbuffer->valid_buffer_range);
 
 	if (!r600_init_resource(rscreen, rbuffer, templ->width0, alignment, TRUE)) {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 12e5b61..85d17d0 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -723,10 +723,7 @@ static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource
 	unsigned i, shader, alignment = rbuffer->buf->alignment;
 	uint64_t old_va = r600_resource_va(ctx->screen, buf);
 
-	/* Discard the buffer. */
-	pb_reference(&rbuffer->buf, NULL);
-
-	/* Create a new one in the same pipe_resource. */
+	/* Reallocate the buffer in the same pipe_resource. */
 	r600_init_resource(&sctx->screen->b, rbuffer, rbuffer->b.b.width0,
 			   alignment, TRUE);
 
-- 
1.8.3.2



More information about the mesa-dev mailing list