mesa/shaderobj: Fix races on refcounts
authorChad Versace <chadversary@chromium.org>
Tue, 27 Dec 2016 22:26:24 +0000 (14:26 -0800)
committerChad Versace <chadversary@chromium.org>
Wed, 28 Dec 2016 19:10:43 +0000 (11:10 -0800)
Use atomic ops when updating gl_shader::RefCount.

Fixes intermittent failures and crashes in
'dEQP-EGL.functional.sharing.gles2.multithread.*'.
All tests in that group now pass except
'dEQP-EGL.functional.sharing.gles2.multithread.simple_egl_server_sync.textures.copyteximage2d_texsubimage2d_render'.

Tested with:
  mesa: branch 'master' at d6545f2
  deqp: branch 'nougat-cts-dev' at 4acf725 with additional local fixes
  DEQP_TARGET: x11_egl
  hw: Intel Broadwell 0x1616

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99085
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
Cc: mesa-stable@lists.freedesktop.org
Cc: Mark Janes <mark.a.janes@intel.com>
Cc: Haixia Shi <hshi@chromium.org>
src/mesa/main/shaderobj.c

index 6fcdf44282893ed9532501cfe3ac96da59041849..2071ffff45d652e0bde78ddc158c69ee0cc4eea3 100644 (file)
@@ -65,14 +65,11 @@ _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
    }
    if (*ptr) {
       /* Unreference the old shader */
-      GLboolean deleteFlag = GL_FALSE;
       struct gl_shader *old = *ptr;
 
       assert(old->RefCount > 0);
-      old->RefCount--;
-      deleteFlag = (old->RefCount == 0);
 
-      if (deleteFlag) {
+      if (p_atomic_dec_zero(&old->RefCount)) {
         if (old->Name != 0)
            _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
          _mesa_delete_shader(ctx, old);
@@ -84,7 +81,7 @@ _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
 
    if (sh) {
       /* reference new */
-      sh->RefCount++;
+      p_atomic_inc(&sh->RefCount);
       *ptr = sh;
    }
 }
@@ -257,14 +254,11 @@ _mesa_reference_shader_program_(struct gl_context *ctx,
    }
    if (*ptr) {
       /* Unreference the old shader program */
-      GLboolean deleteFlag = GL_FALSE;
       struct gl_shader_program *old = *ptr;
 
       assert(old->RefCount > 0);
-      old->RefCount--;
-      deleteFlag = (old->RefCount == 0);
 
-      if (deleteFlag) {
+      if (p_atomic_dec_zero(&old->RefCount)) {
         if (old->Name != 0)
            _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
          _mesa_delete_shader_program(ctx, old);
@@ -275,7 +269,7 @@ _mesa_reference_shader_program_(struct gl_context *ctx,
    assert(!*ptr);
 
    if (shProg) {
-      shProg->RefCount++;
+      p_atomic_inc(&shProg->RefCount);
       *ptr = shProg;
    }
 }