From: Marek Olšák <[email protected]>

---
 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

_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to