[Mesa-dev] [PATCH 04/21] glsl: protect glsl_type with a mutex
Chia-I Wu
olvaffe at gmail.com
Tue Apr 22 01:58:19 PDT 2014
glsl_type has several static hash tables and a static ralloc context. They
need to be protected by a mutex as they are not thread-safe.
Signed-off-by: Chia-I Wu <olv at lunarg.com>
---
src/glsl/glsl_types.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++------
src/glsl/glsl_types.h | 15 +++++++++----
2 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 849a79a..562cf00 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -31,6 +31,7 @@ extern "C" {
#include "program/hash_table.h"
}
+mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
hash_table *glsl_type::array_types = NULL;
hash_table *glsl_type::record_types = NULL;
hash_table *glsl_type::interface_types = NULL;
@@ -55,9 +56,14 @@ glsl_type::glsl_type(GLenum gl_type,
vector_elements(vector_elements), matrix_columns(matrix_columns),
length(0)
{
+ mtx_lock(&glsl_type::mutex);
+
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
+
+ mtx_unlock(&glsl_type::mutex);
+
/* Neither dimension is zero or both dimensions are zero.
*/
assert((vector_elements == 0) == (matrix_columns == 0));
@@ -73,9 +79,14 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
sampler_array(array), sampler_type(type), interface_packing(0),
length(0)
{
+ mtx_lock(&glsl_type::mutex);
+
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
+
+ mtx_unlock(&glsl_type::mutex);
+
memset(& fields, 0, sizeof(fields));
if (base_type == GLSL_TYPE_SAMPLER) {
@@ -97,11 +108,14 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
{
unsigned int i;
+ mtx_lock(&glsl_type::mutex);
+
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
this->fields.structure = ralloc_array(this->mem_ctx,
glsl_struct_field, length);
+
for (i = 0; i < length; i++) {
this->fields.structure[i].type = fields[i].type;
this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
@@ -112,6 +126,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].sample = fields[i].sample;
this->fields.structure[i].row_major = fields[i].row_major;
}
+
+ mtx_unlock(&glsl_type::mutex);
}
glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
@@ -125,6 +141,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
{
unsigned int i;
+ mtx_lock(&glsl_type::mutex);
+
init_ralloc_type_ctx();
assert(name != NULL);
this->name = ralloc_strdup(this->mem_ctx, name);
@@ -140,6 +158,8 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].sample = fields[i].sample;
this->fields.structure[i].row_major = fields[i].row_major;
}
+
+ mtx_unlock(&glsl_type::mutex);
}
@@ -287,6 +307,8 @@ const glsl_type *glsl_type::get_scalar_type() const
void
_mesa_glsl_release_types(void)
{
+ mtx_lock(&glsl_type::mutex);
+
if (glsl_type::array_types != NULL) {
hash_table_dtor(glsl_type::array_types);
glsl_type::array_types = NULL;
@@ -296,6 +318,8 @@ _mesa_glsl_release_types(void)
hash_table_dtor(glsl_type::record_types);
glsl_type::record_types = NULL;
}
+
+ mtx_unlock(&glsl_type::mutex);
}
@@ -318,7 +342,10 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) :
* NUL.
*/
const unsigned name_length = strlen(array->name) + 10 + 3;
+
+ mtx_lock(&glsl_type::mutex);
char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
+ mtx_unlock(&glsl_type::mutex);
if (length == 0)
snprintf(n, name_length, "%s[]", array->name);
@@ -454,12 +481,6 @@ glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
const glsl_type *
glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
{
-
- if (array_types == NULL) {
- array_types = hash_table_ctor(64, hash_table_string_hash,
- hash_table_string_compare);
- }
-
/* Generate a name using the base type pointer in the key. This is
* done because the name of the base type may not be unique across
* shaders. For example, two shaders may have different record types
@@ -468,9 +489,19 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
char key[128];
snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
+ mtx_lock(&glsl_type::mutex);
+
+ if (array_types == NULL) {
+ array_types = hash_table_ctor(64, hash_table_string_hash,
+ hash_table_string_compare);
+ }
+
const glsl_type *t = (glsl_type *) hash_table_find(array_types, key);
+
if (t == NULL) {
+ mtx_unlock(&glsl_type::mutex);
t = new glsl_type(base, array_size);
+ mtx_lock(&glsl_type::mutex);
hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key));
}
@@ -479,6 +510,8 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
assert(t->length == array_size);
assert(t->fields.array == base);
+ mtx_unlock(&glsl_type::mutex);
+
return t;
}
@@ -563,13 +596,17 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
{
const glsl_type key(fields, num_fields, name);
+ mtx_lock(&glsl_type::mutex);
+
if (record_types == NULL) {
record_types = hash_table_ctor(64, record_key_hash, record_key_compare);
}
const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key);
if (t == NULL) {
+ mtx_unlock(&glsl_type::mutex);
t = new glsl_type(fields, num_fields, name);
+ mtx_lock(&glsl_type::mutex);
hash_table_insert(record_types, (void *) t, t);
}
@@ -578,6 +615,8 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
assert(t->length == num_fields);
assert(strcmp(t->name, name) == 0);
+ mtx_unlock(&glsl_type::mutex);
+
return t;
}
@@ -590,13 +629,17 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
{
const glsl_type key(fields, num_fields, packing, block_name);
+ mtx_lock(&glsl_type::mutex);
+
if (interface_types == NULL) {
interface_types = hash_table_ctor(64, record_key_hash, record_key_compare);
}
const glsl_type *t = (glsl_type *) hash_table_find(interface_types, & key);
if (t == NULL) {
+ mtx_unlock(&glsl_type::mutex);
t = new glsl_type(fields, num_fields, packing, block_name);
+ mtx_lock(&glsl_type::mutex);
hash_table_insert(interface_types, (void *) t, t);
}
@@ -605,6 +648,8 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
assert(t->length == num_fields);
assert(strcmp(t->name, block_name) == 0);
+ mtx_unlock(&glsl_type::mutex);
+
return t;
}
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index ae3829f..7fcb291 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -101,16 +101,18 @@ struct glsl_type {
* easier to just ralloc_free 'mem_ctx' (or any of its ancestors). */
static void* operator new(size_t size)
{
- if (glsl_type::mem_ctx == NULL) {
- glsl_type::mem_ctx = ralloc_context(NULL);
- assert(glsl_type::mem_ctx != NULL);
- }
+ mtx_lock(&glsl_type::mutex);
+
+ /* mem_ctx should have been created by the static members */
+ assert(glsl_type::mem_ctx != NULL);
void *type;
type = ralloc_size(glsl_type::mem_ctx, size);
assert(type != NULL);
+ mtx_unlock(&glsl_type::mutex);
+
return type;
}
@@ -118,7 +120,9 @@ struct glsl_type {
* ralloc_free in that case. */
static void operator delete(void *type)
{
+ mtx_lock(&glsl_type::mutex);
ralloc_free(type);
+ mtx_unlock(&glsl_type::mutex);
}
/**
@@ -567,6 +571,9 @@ struct glsl_type {
bool record_compare(const glsl_type *b) const;
private:
+
+ static mtx_t mutex;
+
/**
* ralloc context for all glsl_type allocations
*
--
1.8.5.3
More information about the mesa-dev
mailing list