]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Add HashTable_FreeUnsafe to allow freeing of an atomic hash table
authorVMware, Inc <>
Mon, 26 Jul 2010 18:23:18 +0000 (11:23 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 26 Jul 2010 18:23:18 +0000 (11:23 -0700)
The MXUser read-write lock wants to free its hash table when the lcok
is destroyed, but HashTable_Free has an ASSERT that it cannot be
atomic.  Let's add another function HashTable_FreeUnsafe to allow
freeing of an atomic hash table, but the caller has to ensure that no
other thread may be accessing the hash table when it is being freed.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/hashTable.h
open-vm-tools/lib/lock/ulRW.c
open-vm-tools/lib/misc/hashTable.c

index 321499f4ab605c14f681c973e16233a683f8a61a..93022fa10bdcc53ebe036ca2f15d55becc45e8c9 100644 (file)
@@ -66,6 +66,9 @@ HashTable_AllocOnce(Atomic_Ptr          *var,
 void
 HashTable_Free(HashTable *hashTable);
 
+void
+HashTable_FreeUnsafe(HashTable *hashTable);
+
 Bool
 HashTable_Insert(HashTable  *hashTable,
                  const void *keyStr,
index 679b426ef3c0ff615f9e14e6c7745fbfd55c958b..8f468f39015a3486d96a908dd9ae1c209a292543 100644 (file)
@@ -520,7 +520,7 @@ MXUser_DestroyRWLock(MXUserRWLock *lock)  // IN:
       MXUserHistoTearDown(Atomic_ReadPtr(&lock->heldHisto));
 #endif
 
-      HashTable_Free(lock->holderTable);
+      HashTable_FreeUnsafe(lock->holderTable);
       lock->header.signature = 0;  // just in case...
       free((void *) lock->header.name);  // avoid const warnings
       lock->header.name = NULL;
index 740b861343078b1208051d3d9b2e336b676ea3d5..4b80ec40f70a326c1de9612af448dd8daccc08f3 100644 (file)
@@ -311,8 +311,7 @@ HashTable_AllocOnce(Atomic_Ptr *var,          // IN/OUT: the atomic var
       if (ht == NULL) {
          ht = new;
       } else {
-         new->atomic = FALSE;
-         HashTable_Free(new);
+         HashTable_FreeUnsafe(new);
       }
    }
    ASSERT(ht == Atomic_ReadPtr(var));
@@ -321,6 +320,56 @@ HashTable_AllocOnce(Atomic_Ptr *var,          // IN/OUT: the atomic var
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * HashTable_Clear --
+ *
+ *      Clear all entries a hashtable by freeing them.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+HashTableClearInternal(HashTable *ht)  // IN/OUT:
+{
+   int i;
+
+   ht->numElements = 0;
+
+   for (i = 0; i < ht->numEntries; i++) {
+      HashTableEntry *entry;
+
+      while ((entry = ENTRY(ht->buckets[i])) != NULL) {
+         SETENTRY(ht->buckets[i], ENTRY(entry->next));
+         if (ht->copyKey) {
+            free((void *) entry->keyStr);
+         }
+         if (ht->freeEntryFn) {
+            ht->freeEntryFn(Atomic_ReadPtr(&entry->clientData));
+         }
+         free(entry);
+      }
+   }
+}
+
+
+void
+HashTable_Clear(HashTable *ht)  // IN/OUT:
+{
+   ASSERT(ht);
+   ASSERT(!ht->atomic);
+
+   HashTableClearInternal(ht);
+}
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -343,7 +392,7 @@ HashTable_Free(HashTable *ht)  // IN/OUT:
    ASSERT(ht);
    ASSERT(!ht->atomic);
 
-   HashTable_Clear(ht);
+   HashTableClearInternal(ht);
 
    free(ht->buckets);
    free(ht);
@@ -353,9 +402,11 @@ HashTable_Free(HashTable *ht)  // IN/OUT:
 /*
  *----------------------------------------------------------------------
  *
- * HashTable_Clear --
+ * HashTable_FreeUnsafe --
  *
- *      Clear all entries a hashtable by freeing them.
+ *      HashTable_Free for atomic hash tables.  Non-atomic hash tables
+ *      should always use HashTable_Free.  The caller should make sure
+ *      no other thread may access the hash table when this is called.
  *
  * Results:
  *      None.
@@ -367,29 +418,14 @@ HashTable_Free(HashTable *ht)  // IN/OUT:
  */
 
 void
-HashTable_Clear(HashTable *ht)  // IN/OUT:
+HashTable_FreeUnsafe(HashTable *ht)  // IN/OUT:
 {
-   int i;
-
    ASSERT(ht);
-   ASSERT(!ht->atomic);
 
-   ht->numElements = 0;
+   HashTableClearInternal(ht);
 
-   for (i = 0; i < ht->numEntries; i++) {
-      HashTableEntry *entry;
-
-      while ((entry = ENTRY(ht->buckets[i])) != NULL) {
-         SETENTRY(ht->buckets[i], ENTRY(entry->next));
-         if (ht->copyKey) {
-            free((void *) entry->keyStr);
-         }
-         if (ht->freeEntryFn) {
-            ht->freeEntryFn(Atomic_ReadPtr(&entry->clientData));
-         }
-         free(entry);
-      }
-   }
+   free(ht->buckets);
+   free(ht);
 }