mesa: Replace uses of Shared->Mutex with hash-table mutexes

We were locking the Shared->Mutex and then using calling functions like
_mesa_HashInsert that do additional per-hash-table locking internally.

Instead just lock each hash-table's mutex and use functions like
_mesa_HashInsertLocked and the new _mesa_HashRemoveLocked.

In order to do this, we need to remove the locking from
_mesa_HashFindFreeKeyBlock since it will always be called with the
per-hash-table lock taken.

Reviewed-by: Timothy Arceri <t_arceri@yahoo.com.au>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Matt Turner 2015-07-30 14:31:04 -07:00
parent aded1160e5
commit 015f2207cf
9 changed files with 78 additions and 50 deletions

View file

@ -200,13 +200,18 @@ _mesa_GenProgramsARB(GLsizei n, GLuint *ids)
if (!ids) if (!ids)
return; return;
_mesa_HashLockMutex(ctx->Shared->Programs);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
/* Insert pointer to dummy program as placeholder */ /* Insert pointer to dummy program as placeholder */
for (i = 0; i < (GLuint) n; i++) { for (i = 0; i < (GLuint) n; i++) {
_mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); _mesa_HashInsertLocked(ctx->Shared->Programs, first + i,
&_mesa_DummyProgram);
} }
_mesa_HashUnlockMutex(ctx->Shared->Programs);
/* Return the program names */ /* Return the program names */
for (i = 0; i < (GLuint) n; i++) { for (i = 0; i < (GLuint) n; i++) {
ids[i] = first + i; ids[i] = first + i;

View file

@ -201,11 +201,15 @@ _mesa_GenFragmentShadersATI(GLuint range)
return 0; return 0;
} }
_mesa_HashLockMutex(ctx->Shared->ATIShaders);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
for (i = 0; i < range; i++) { for (i = 0; i < range; i++) {
_mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader); _mesa_HashInsertLocked(ctx->Shared->ATIShaders, first + i, &DummyShader);
} }
_mesa_HashUnlockMutex(ctx->Shared->ATIShaders);
return first; return first;
} }

View file

@ -1097,8 +1097,11 @@ _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
struct gl_buffer_object * struct gl_buffer_object *
_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer) _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer)
{ {
return (struct gl_buffer_object *) if (buffer == 0)
_mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer); return NULL;
else
return (struct gl_buffer_object *)
_mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer);
} }
/** /**
@ -1283,10 +1286,11 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
return; return;
} }
mtx_lock(&ctx->Shared->Mutex); _mesa_HashLockMutex(ctx->Shared->BufferObjects);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); struct gl_buffer_object *bufObj =
_mesa_lookup_bufferobj_locked(ctx, ids[i]);
if (bufObj) { if (bufObj) {
struct gl_vertex_array_object *vao = ctx->Array.VAO; struct gl_vertex_array_object *vao = ctx->Array.VAO;
GLuint j; GLuint j;
@ -1395,7 +1399,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
} }
/* The ID is immediately freed for re-use */ /* The ID is immediately freed for re-use */
_mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]); _mesa_HashRemoveLocked(ctx->Shared->BufferObjects, ids[i]);
/* Make sure we do not run into the classic ABA problem on bind. /* Make sure we do not run into the classic ABA problem on bind.
* We don't want to allow re-binding a buffer object that's been * We don't want to allow re-binding a buffer object that's been
* "deleted" by glDeleteBuffers(). * "deleted" by glDeleteBuffers().
@ -1411,7 +1415,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
} }
} }
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
} }
@ -1445,7 +1449,7 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
/* /*
* This must be atomic (generation and allocation of buffer object IDs) * This must be atomic (generation and allocation of buffer object IDs)
*/ */
mtx_lock(&ctx->Shared->Mutex); _mesa_HashLockMutex(ctx->Shared->BufferObjects);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
@ -1460,17 +1464,17 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
buf = ctx->Driver.NewBufferObject(ctx, buffers[i]); buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
if (!buf) { if (!buf) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
return; return;
} }
} }
else else
buf = &DummyBufferObject; buf = &DummyBufferObject;
_mesa_HashInsert(ctx->Shared->BufferObjects, buffers[i], buf); _mesa_HashInsertLocked(ctx->Shared->BufferObjects, buffers[i], buf);
} }
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
} }
/** /**
@ -1512,9 +1516,7 @@ _mesa_IsBuffer(GLuint id)
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
mtx_lock(&ctx->Shared->Mutex);
bufObj = _mesa_lookup_bufferobj(ctx, id); bufObj = _mesa_lookup_bufferobj(ctx, id);
mtx_unlock(&ctx->Shared->Mutex);
return bufObj && bufObj != &DummyBufferObject; return bufObj && bufObj != &DummyBufferObject;
} }

View file

@ -9228,15 +9228,15 @@ _mesa_GenLists(GLsizei range)
/* /*
* Make this an atomic operation * Make this an atomic operation
*/ */
mtx_lock(&ctx->Shared->Mutex); _mesa_HashLockMutex(ctx->Shared->DisplayList);
base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range); base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range);
if (base) { if (base) {
/* reserve the list IDs by with empty/dummy lists */ /* reserve the list IDs by with empty/dummy lists */
GLint i; GLint i;
for (i = 0; i < range; i++) { for (i = 0; i < range; i++) {
_mesa_HashInsert(ctx->Shared->DisplayList, base + i, _mesa_HashInsertLocked(ctx->Shared->DisplayList, base + i,
make_list(base + i, 1)); make_list(base + i, 1));
} }
} }
@ -9258,7 +9258,7 @@ _mesa_GenLists(GLsizei range)
} }
} }
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->DisplayList);
return base; return base;
} }

View file

@ -1287,8 +1287,8 @@ _mesa_IsRenderbuffer(GLuint renderbuffer)
static struct gl_renderbuffer * static struct gl_renderbuffer *
allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer, allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
const char *func) const char *func)
{ {
struct gl_renderbuffer *newRb; struct gl_renderbuffer *newRb;
@ -1299,10 +1299,8 @@ allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer,
return NULL; return NULL;
} }
assert(newRb->AllocStorage); assert(newRb->AllocStorage);
mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
_mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
newRb->RefCount = 1; /* referenced by hash table */ newRb->RefCount = 1; /* referenced by hash table */
mtx_unlock(&ctx->Shared->Mutex);
return newRb; return newRb;
} }
@ -1336,7 +1334,10 @@ bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
} }
if (!newRb) { if (!newRb) {
newRb = allocate_renderbuffer(ctx, renderbuffer, "glBindRenderbufferEXT"); _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
"glBindRenderbufferEXT");
_mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
} }
} }
else { else {
@ -1643,6 +1644,8 @@ create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
if (!renderbuffers) if (!renderbuffers)
return; return;
_mesa_HashLockMutex(ctx->Shared->RenderBuffers);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@ -1650,14 +1653,15 @@ create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
renderbuffers[i] = name; renderbuffers[i] = name;
if (dsa) { if (dsa) {
allocate_renderbuffer(ctx, name, func); allocate_renderbuffer_locked(ctx, name, func);
} else { } else {
/* insert a dummy renderbuffer into the hash table */ /* insert a dummy renderbuffer into the hash table */
mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, name,
_mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); &DummyRenderbuffer);
mtx_unlock(&ctx->Shared->Mutex);
} }
} }
_mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
} }
@ -2684,6 +2688,8 @@ create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
if (!framebuffers) if (!framebuffers)
return; return;
_mesa_HashLockMutex(ctx->Shared->FrameBuffers);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@ -2700,10 +2706,10 @@ create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
else else
fb = &DummyFramebuffer; fb = &DummyFramebuffer;
mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
_mesa_HashInsert(ctx->Shared->FrameBuffers, name, fb);
mtx_unlock(&ctx->Shared->Mutex);
} }
_mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
} }

View file

@ -468,10 +468,8 @@ GLuint
_mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys)
{ {
const GLuint maxKey = ~((GLuint) 0) - 1; const GLuint maxKey = ~((GLuint) 0) - 1;
mtx_lock(&table->Mutex);
if (maxKey - numKeys > table->MaxKey) { if (maxKey - numKeys > table->MaxKey) {
/* the quick solution */ /* the quick solution */
mtx_unlock(&table->Mutex);
return table->MaxKey + 1; return table->MaxKey + 1;
} }
else { else {
@ -489,13 +487,11 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys)
/* this key not in use, check if we've found enough */ /* this key not in use, check if we've found enough */
freeCount++; freeCount++;
if (freeCount == numKeys) { if (freeCount == numKeys) {
mtx_unlock(&table->Mutex);
return freeStart; return freeStart;
} }
} }
} }
/* cannot allocate a block of numKeys consecutive keys */ /* cannot allocate a block of numKeys consecutive keys */
mtx_unlock(&table->Mutex);
return 0; return 0;
} }
} }

View file

@ -50,6 +50,15 @@ _mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
_mesa_HashLookup(ctx->Shared->SamplerObjects, name); _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
} }
static struct gl_sampler_object *
_mesa_lookup_samplerobj_locked(struct gl_context *ctx, GLuint name)
{
if (name == 0)
return NULL;
else
return (struct gl_sampler_object *)
_mesa_HashLookupLocked(ctx->Shared->SamplerObjects, name);
}
static inline void static inline void
begin_samplerobj_lookups(struct gl_context *ctx) begin_samplerobj_lookups(struct gl_context *ctx)
@ -186,15 +195,19 @@ create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
if (!samplers) if (!samplers)
return; return;
_mesa_HashLockMutex(ctx->Shared->SamplerObjects);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
/* Insert the ID and pointer to new sampler object into hash table */ /* Insert the ID and pointer to new sampler object into hash table */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
struct gl_sampler_object *sampObj = struct gl_sampler_object *sampObj =
ctx->Driver.NewSamplerObject(ctx, first + i); ctx->Driver.NewSamplerObject(ctx, first + i);
_mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj); _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, first + i, sampObj);
samplers[i] = first + i; samplers[i] = first + i;
} }
_mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
} }
void GLAPIENTRY void GLAPIENTRY
@ -225,13 +238,13 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
return; return;
} }
mtx_lock(&ctx->Shared->Mutex); _mesa_HashLockMutex(ctx->Shared->SamplerObjects);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (samplers[i]) { if (samplers[i]) {
GLuint j; GLuint j;
struct gl_sampler_object *sampObj = struct gl_sampler_object *sampObj =
_mesa_lookup_samplerobj(ctx, samplers[i]); _mesa_lookup_samplerobj_locked(ctx, samplers[i]);
if (sampObj) { if (sampObj) {
/* If the sampler is currently bound, unbind it. */ /* If the sampler is currently bound, unbind it. */
@ -243,14 +256,14 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
} }
/* The ID is immediately freed for re-use */ /* The ID is immediately freed for re-use */
_mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]); _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]);
/* But the object exists until its reference count goes to zero */ /* But the object exists until its reference count goes to zero */
_mesa_reference_sampler_object(ctx, &sampObj, NULL); _mesa_reference_sampler_object(ctx, &sampObj, NULL);
} }
} }
} }
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects);
} }

View file

@ -305,9 +305,11 @@ create_shader(struct gl_context *ctx, GLenum type)
return 0; return 0;
} }
_mesa_HashLockMutex(ctx->Shared->ShaderObjects);
name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
sh = ctx->Driver.NewShader(ctx, name, type); sh = ctx->Driver.NewShader(ctx, name, type);
_mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh);
_mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
return name; return name;
} }
@ -319,14 +321,18 @@ create_shader_program(struct gl_context *ctx)
GLuint name; GLuint name;
struct gl_shader_program *shProg; struct gl_shader_program *shProg;
_mesa_HashLockMutex(ctx->Shared->ShaderObjects);
name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
shProg = _mesa_new_shader_program(name); shProg = _mesa_new_shader_program(name);
_mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, shProg);
assert(shProg->RefCount == 1); assert(shProg->RefCount == 1);
_mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
return name; return name;
} }

View file

@ -1219,7 +1219,7 @@ create_textures(struct gl_context *ctx, GLenum target,
/* /*
* This must be atomic (generation and allocation of texture IDs) * This must be atomic (generation and allocation of texture IDs)
*/ */
mtx_lock(&ctx->Shared->Mutex); _mesa_HashLockMutex(ctx->Shared->TexObjects);
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
@ -1229,18 +1229,18 @@ create_textures(struct gl_context *ctx, GLenum target,
GLuint name = first + i; GLuint name = first + i;
texObj = ctx->Driver.NewTextureObject(ctx, name, target); texObj = ctx->Driver.NewTextureObject(ctx, name, target);
if (!texObj) { if (!texObj) {
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sTextures", caller); _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sTextures", caller);
return; return;
} }
/* insert into hash table */ /* insert into hash table */
_mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj); _mesa_HashInsertLocked(ctx->Shared->TexObjects, texObj->Name, texObj);
textures[i] = name; textures[i] = name;
} }
mtx_unlock(&ctx->Shared->Mutex); _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
} }
/*@}*/ /*@}*/
@ -1489,9 +1489,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
/* The texture _name_ is now free for re-use. /* The texture _name_ is now free for re-use.
* Remove it from the hash table now. * Remove it from the hash table now.
*/ */
mtx_lock(&ctx->Shared->Mutex);
_mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
mtx_unlock(&ctx->Shared->Mutex);
/* Unreference the texobj. If refcount hits zero, the texture /* Unreference the texobj. If refcount hits zero, the texture
* will be deleted. * will be deleted.
@ -1723,9 +1721,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
} }
/* and insert it into hash table */ /* and insert it into hash table */
mtx_lock(&ctx->Shared->Mutex);
_mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
mtx_unlock(&ctx->Shared->Mutex);
} }
} }