Mesa (gallium-0.1): gallium: Make handle_table reentrant.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Mon Nov 17 03:36:34 UTC 2008


Module: Mesa
Branch: gallium-0.1
Commit: c13cf0d69094bd586df16bb5cf1aa306f8923307
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c13cf0d69094bd586df16bb5cf1aa306f8923307

Author: José Fonseca <jrfonseca at tungstengraphics.com>
Date:   Tue Nov 11 23:27:27 2008 +0900

gallium: Make handle_table reentrant.

Ensure that the object has consistent state also when calling the destroy
callback. Namely, ensure the object passed to the callback is removed from
the table prior to calling the destroy callback to avoid a infinite loop or
double free.

---

 src/gallium/auxiliary/util/u_handle_table.c |   34 ++++++++++++++++++++------
 1 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c
index 2c40011..2d15932 100644
--- a/src/gallium/auxiliary/util/u_handle_table.c
+++ b/src/gallium/auxiliary/util/u_handle_table.c
@@ -124,6 +124,28 @@ handle_table_resize(struct handle_table *ht,
 }
 
 
+static INLINE void
+handle_table_clear(struct handle_table *ht, 
+                   unsigned index)
+{
+   void *object;
+   
+   /* The order here is important so that the object being destroyed is not
+    * present in the table when seen by the destroy callback, because the 
+    * destroy callback may directly or indirectly call the other functions in 
+    * this module.
+    */
+
+   object = ht->objects[index];
+   if(object) {
+      ht->objects[index] = NULL;
+      
+      if(ht->destroy)
+         ht->destroy(object);
+   }   
+}
+
+
 unsigned
 handle_table_add(struct handle_table *ht, 
                  void *object)
@@ -184,9 +206,8 @@ handle_table_set(struct handle_table *ht,
    if(!handle_table_resize(ht, index))
       return 0;
 
-   if(ht->objects[index] && ht->destroy)
-      ht->destroy(ht->objects[index]);
-      
+   handle_table_clear(ht, index);
+
    ht->objects[index] = object;
    
    return handle;
@@ -227,10 +248,8 @@ handle_table_remove(struct handle_table *ht,
    if(!object)
       return;
    
-   if(ht->destroy)
-      ht->destroy(object);
+   handle_table_clear(ht, index);
 
-   ht->objects[index] = NULL;
    if(index < ht->filled)
       ht->filled = index;
 }
@@ -266,8 +285,7 @@ handle_table_destroy(struct handle_table *ht)
 
    if(ht->destroy)
       for(index = 0; index < ht->size; ++index)
-	 if(ht->objects[index])
-	    ht->destroy(ht->objects[index]);
+         handle_table_clear(ht, index);
    
    FREE(ht->objects);
    FREE(ht);




More information about the mesa-commit mailing list