[Mesa-dev] [PATCH 13/14] radeonsi: prevent race conditions when doing scratch patching
Marek Olšák
maraeo at gmail.com
Fri Apr 28 21:42:50 UTC 2017
From: Marek Olšák <marek.olsak at amd.com>
---
src/gallium/drivers/radeonsi/si_state_shaders.c | 32 +++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 16fb522..a3ff511 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -2570,60 +2570,88 @@ static bool si_update_gs_ring_buffers(struct si_context *sctx)
}
if (sctx->gsvs_ring) {
si_set_ring_buffer(&sctx->b.b, SI_RING_GSVS,
sctx->gsvs_ring, 0, sctx->gsvs_ring->width0,
false, false, 0, 0, 0);
}
return true;
}
+static void si_shader_lock(struct si_shader *shader)
+{
+ mtx_lock(&shader->selector->mutex);
+ if (shader->previous_stage_sel) {
+ assert(shader->previous_stage_sel != shader->selector);
+ mtx_lock(&shader->previous_stage_sel->mutex);
+ }
+}
+
+static void si_shader_unlock(struct si_shader *shader)
+{
+ if (shader->previous_stage_sel)
+ mtx_unlock(&shader->previous_stage_sel->mutex);
+ mtx_unlock(&shader->selector->mutex);
+}
+
/**
* @returns 1 if \p sel has been updated to use a new scratch buffer
* 0 if not
* < 0 if there was a failure
*/
static int si_update_scratch_buffer(struct si_context *sctx,
struct si_shader *shader)
{
uint64_t scratch_va = sctx->scratch_buffer->gpu_address;
int r;
if (!shader)
return 0;
/* This shader doesn't need a scratch buffer */
if (shader->config.scratch_bytes_per_wave == 0)
return 0;
+ /* Prevent race conditions when updating:
+ * - si_shader::scratch_bo
+ * - si_shader::binary::code
+ * - si_shader::previous_stage::binary::code.
+ */
+ si_shader_lock(shader);
+
/* This shader is already configured to use the current
* scratch buffer. */
- if (shader->scratch_bo == sctx->scratch_buffer)
+ if (shader->scratch_bo == sctx->scratch_buffer) {
+ si_shader_unlock(shader);
return 0;
+ }
assert(sctx->scratch_buffer);
if (shader->previous_stage)
si_shader_apply_scratch_relocs(shader->previous_stage, scratch_va);
si_shader_apply_scratch_relocs(shader, scratch_va);
/* Replace the shader bo with a new bo that has the relocs applied. */
r = si_shader_binary_upload(sctx->screen, shader);
- if (r)
+ if (r) {
+ si_shader_unlock(shader);
return r;
+ }
/* Update the shader state to use the new shader bo. */
si_shader_init_pm4_state(sctx->screen, shader);
r600_resource_reference(&shader->scratch_bo, sctx->scratch_buffer);
+ si_shader_unlock(shader);
return 1;
}
static unsigned si_get_current_scratch_buffer_size(struct si_context *sctx)
{
return sctx->scratch_buffer ? sctx->scratch_buffer->b.b.width0 : 0;
}
static unsigned si_get_scratch_buffer_bytes_per_wave(struct si_shader *shader)
{
--
2.7.4
More information about the mesa-dev
mailing list