mesa/shaderobj: Fix races on refcounts

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>
(cherry picked from commit 464b23b1f2)
[Emil Velikov: add u_atomic.h include to resolve the build]
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
Chad Versace 2016-12-27 14:26:24 -08:00 committed by Emil Velikov
parent 9c4ebd16e9
commit 84317907b1

View file

@ -39,6 +39,7 @@
#include "main/uniforms.h"
#include "program/program.h"
#include "program/prog_parameter.h"
#include "util/u_atomic.h"
#include "util/ralloc.h"
#include "util/string_to_uint_map.h"
@ -64,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);
@ -83,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;
}
}
@ -226,14 +224,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);
@ -244,7 +239,7 @@ _mesa_reference_shader_program_(struct gl_context *ctx,
assert(!*ptr);
if (shProg) {
shProg->RefCount++;
p_atomic_inc(&shProg->RefCount);
*ptr = shProg;
}
}