From: VMware, Inc <> Date: Mon, 26 Jul 2010 18:23:18 +0000 (-0700) Subject: Add HashTable_FreeUnsafe to allow freeing of an atomic hash table X-Git-Tag: 2010.07.25-280253~87 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ae872291e21298406ac32757da7da3c604febef8;p=thirdparty%2Fopen-vm-tools.git Add HashTable_FreeUnsafe to allow freeing of an atomic hash table 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 --- diff --git a/open-vm-tools/lib/include/hashTable.h b/open-vm-tools/lib/include/hashTable.h index 321499f4a..93022fa10 100644 --- a/open-vm-tools/lib/include/hashTable.h +++ b/open-vm-tools/lib/include/hashTable.h @@ -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, diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c index 679b426ef..8f468f390 100644 --- a/open-vm-tools/lib/lock/ulRW.c +++ b/open-vm-tools/lib/lock/ulRW.c @@ -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; diff --git a/open-vm-tools/lib/misc/hashTable.c b/open-vm-tools/lib/misc/hashTable.c index 740b86134..4b80ec40f 100644 --- a/open-vm-tools/lib/misc/hashTable.c +++ b/open-vm-tools/lib/misc/hashTable.c @@ -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); }