glsl: protect glsl_type with a mutex
authorChia-I Wu <olvaffe@gmail.com>
Wed, 20 Aug 2014 06:40:29 +0000 (14:40 +0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 30 Oct 2014 09:26:19 +0000 (02:26 -0700)
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.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69200
Signed-off-by: Chia-I Wu <olv@lunarg.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/glsl_types.cpp
src/glsl/glsl_types.h

index c11d86482be4843e9a015042e9ae0266e95b1acd..321df2504b302e3f2e02a8ca3b3ef414cee2d822 100644 (file)
@@ -29,6 +29,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;
@@ -53,9 +54,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));
@@ -71,9 +77,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) {
@@ -95,11 +106,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,
@@ -110,6 +124,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].matrix_layout = fields[i].matrix_layout;
    }
+
+   mtx_unlock(&glsl_type::mutex);
 }
 
 glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
@@ -123,6 +139,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);
@@ -138,6 +156,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].matrix_layout = fields[i].matrix_layout;
    }
+
+   mtx_unlock(&glsl_type::mutex);
 }
 
 
@@ -285,6 +305,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;
@@ -294,6 +316,8 @@ _mesa_glsl_release_types(void)
       hash_table_dtor(glsl_type::record_types);
       glsl_type::record_types = NULL;
    }
+
+   mtx_unlock(&glsl_type::mutex);
 }
 
 
@@ -316,7 +340,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);
@@ -452,12 +479,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
@@ -466,9 +487,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));
    }
@@ -477,6 +508,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;
 }
 
@@ -575,13 +608,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);
    }
@@ -590,6 +627,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;
 }
 
@@ -602,13 +641,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);
    }
@@ -617,6 +660,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;
 }
 
index eeb14c2740230e54503d1d4af71f4408b36684a8..654304144e4feb3a3810fc84f22a17d3d4a9056b 100644 (file)
@@ -122,16 +122,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;
    }
 
@@ -139,7 +141,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);
    }
 
    /**
@@ -618,6 +622,9 @@ struct glsl_type {
    bool record_compare(const glsl_type *b) const;
 
 private:
+
+   static mtx_t mutex;
+
    /**
     * ralloc context for all glsl_type allocations
     *