void TclFinalizeAllocSubsystem(void) { unsigned int i; struct block *blockPtr, *nextPtr; Tcl_MutexLock(allocMutexPtr); for (blockPtr = blockList; blockPtr != NULL; blockPtr = nextPtr) { nextPtr = blockPtr->nextPtr; TclpSysFree(blockPtr); } blockList = NULL; for (blockPtr = bigBlocks.nextPtr; blockPtr != &bigBlocks; ) { nextPtr = blockPtr->nextPtr; TclpSysFree(blockPtr); blockPtr = nextPtr; } bigBlocks.nextPtr = &bigBlocks; bigBlocks.prevPtr = &bigBlocks; for (i=0 ; i<NBUCKETS ; i++) { nextf[i] = NULL; #ifdef MSTATS numMallocs[i] = 0; #endif } #ifdef MSTATS numMallocs[i] = 0; #endif Tcl_MutexUnlock(allocMutexPtr); }
void TclpThreadDeleteKey(void *keyPtr) { pthread_key_t *key = keyPtr; if (pthread_key_delete(*key)) { Tcl_Panic("unable to delete key!"); } TclpSysFree(keyPtr); }
void TclpThreadDeleteKey(void *keyPtr) { DWORD *key = keyPtr; if (!TlsFree(*key)) { Tcl_Panic("unable to delete key"); } TclpSysFree(keyPtr); }
void Tcl_DeleteHashTable( register Tcl_HashTable *tablePtr) /* Table to delete. */ { register Tcl_HashEntry *hPtr, *nextPtr; const Tcl_HashKeyType *typePtr; int i; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } /* * Free up all the entries in the table. */ for (i = 0; i < tablePtr->numBuckets; i++) { hPtr = tablePtr->buckets[i]; while (hPtr != NULL) { nextPtr = hPtr->nextPtr; if (typePtr->freeEntryProc) { typePtr->freeEntryProc (hPtr); } else { ckfree((char *) hPtr); } hPtr = nextPtr; } } /* * Free up the bucket array, if it was dynamically allocated. */ if (tablePtr->buckets != tablePtr->staticBuckets) { if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { TclpSysFree((char *) tablePtr->buckets); } else { ckfree((char *) tablePtr->buckets); } } /* * Arrange for panics if the table is used again without * re-initialization. */ tablePtr->findProc = BogusFind; tablePtr->createProc = BogusCreate; }
void TclFinalizeThreadStorage(void) { Tcl_HashSearch search; /* We need to hit every thread with this * search. */ Tcl_HashEntry *hPtr; /* Hash entry for current thread in master * table. */ Tcl_MutexLock(&threadStorageLock); /* * We are going to delete the hash table for every thread now. This hash * table should be empty at this point, except for one entry for the * current thread. */ for (hPtr = Tcl_FirstHashEntry(&threadStorageHashTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_HashTable *hashTablePtr = Tcl_GetHashValue(hPtr); if (hashTablePtr != NULL) { /* * Delete thread specific hash table for the thread in question * and free the struct. */ Tcl_DeleteHashTable(hashTablePtr); TclpSysFree((char *)hashTablePtr); } /* * Delete thread specific entry from master hash table. */ Tcl_SetHashValue(hPtr, NULL); } Tcl_DeleteHashTable(&threadStorageHashTable); /* * Clear out the thread storage cache as well. */ memset((void*) &threadStorageCache, 0, sizeof(ThreadStorage) * STORAGE_CACHE_SLOTS); /* * Reset this to zero, it will be set to STORAGE_FIRST_KEY if the thread * storage subsystem gets reinitialized */ nextThreadStorageKey = STORAGE_INVALID_KEY; Tcl_MutexUnlock(&threadStorageLock); }
void TclpFree( char *oldPtr) /* Pointer to memory to free. */ { register long size; register union overhead *overPtr; struct block *bigBlockPtr; if (oldPtr == NULL) { return; } Tcl_MutexLock(allocMutexPtr); overPtr = (union overhead *)((caddr_t)oldPtr - sizeof (union overhead)); ASSERT(overPtr->overMagic0 == MAGIC); /* make sure it was in use */ ASSERT(overPtr->overMagic1 == MAGIC); if (overPtr->overMagic0 != MAGIC || overPtr->overMagic1 != MAGIC) { Tcl_MutexUnlock(allocMutexPtr); return; } RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC); RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC); size = overPtr->bucketIndex; if (size == 0xff) { #ifdef MSTATS numMallocs[NBUCKETS]--; #endif bigBlockPtr = (struct block *) overPtr - 1; bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr; TclpSysFree(bigBlockPtr); Tcl_MutexUnlock(allocMutexPtr); return; } ASSERT(size < NBUCKETS); overPtr->next = nextf[size]; /* also clobbers overMagic */ nextf[size] = overPtr; #ifdef MSTATS numMallocs[size]--; #endif Tcl_MutexUnlock(allocMutexPtr); }
static void RebuildTable( register Tcl_HashTable *tablePtr) /* Table to enlarge. */ { int oldSize, count, index; Tcl_HashEntry **oldBuckets; register Tcl_HashEntry **oldChainPtr, **newChainPtr; register Tcl_HashEntry *hPtr; const Tcl_HashKeyType *typePtr; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } oldSize = tablePtr->numBuckets; oldBuckets = tablePtr->buckets; /* * Allocate and initialize the new bucket array, and set up hashing * constants for new array size. */ tablePtr->numBuckets *= 4; if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { tablePtr->buckets = (Tcl_HashEntry **) TclpSysAlloc((unsigned) (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)), 0); } else { tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned) (tablePtr->numBuckets * sizeof(Tcl_HashEntry *))); } for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets; count > 0; count--, newChainPtr++) { *newChainPtr = NULL; } tablePtr->rebuildSize *= 4; tablePtr->downShift -= 2; tablePtr->mask = (tablePtr->mask << 2) + 3; /* * Rehash all of the existing entries into the new bucket array. */ for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) { for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) { *oldChainPtr = hPtr->nextPtr; #if TCL_HASH_KEY_STORE_HASH if (typePtr->hashKeyProc == NULL || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX (tablePtr, hPtr->hash); } else { index = PTR2UINT(hPtr->hash) & tablePtr->mask; } hPtr->nextPtr = tablePtr->buckets[index]; tablePtr->buckets[index] = hPtr; #else void *key = Tcl_GetHashKey(tablePtr, hPtr); if (typePtr->hashKeyProc) { unsigned int hash; hash = typePtr->hashKeyProc(tablePtr, key); if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX (tablePtr, hash); } else { index = hash & tablePtr->mask; } } else { index = RANDOM_INDEX (tablePtr, key); } hPtr->bucketPtr = &(tablePtr->buckets[index]); hPtr->nextPtr = *hPtr->bucketPtr; *hPtr->bucketPtr = hPtr; #endif } } /* * Free up the old bucket array, if it was dynamically allocated. */ if (oldBuckets != tablePtr->staticBuckets) { if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { TclpSysFree((char *) oldBuckets); } else { ckfree((char *) oldBuckets); } } }
void TclpFinalizeThreadDataThread(void) { Tcl_ThreadId id = Tcl_GetCurrentThread(); /* Id of the thread to finalize. */ int index = PTR2UINT(id) % STORAGE_CACHE_SLOTS; Tcl_HashEntry *hPtr; /* Hash entry for current thread in master * table. */ Tcl_HashTable* hashTablePtr;/* Pointer to the hash table holding TSD * blocks for the current thread*/ Tcl_HashSearch search; /* Search object to walk the TSD blocks in the * designated thread */ Tcl_HashEntry *hPtr2; /* Hash entry for a TSD block in the * designated thread. */ Tcl_MutexLock(&threadStorageLock); hPtr = Tcl_FindHashEntry(&threadStorageHashTable, (char*)id); if (hPtr == NULL) { hashTablePtr = NULL; } else { /* * We found it, extract the hash table pointer. */ hashTablePtr = Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); /* * Make sure cache entry for this thread is NULL. */ if (threadStorageCache[index].id == id) { /* * We do not step on another thread's cache entry. This is * especially important if we are creating and exiting a lot of * threads. */ threadStorageCache[index].id = STORAGE_INVALID_THREAD; threadStorageCache[index].hashTablePtr = NULL; } } Tcl_MutexUnlock(&threadStorageLock); /* * The thread's hash table has been extracted and removed from the master * hash table. Now clean up the thread. */ if (hashTablePtr != NULL) { /* * Free all TSD */ for (hPtr2 = Tcl_FirstHashEntry(hashTablePtr, &search); hPtr2 != NULL; hPtr2 = Tcl_NextHashEntry(&search)) { void *blockPtr = Tcl_GetHashValue(hPtr2); if (blockPtr != NULL) { /* * The block itself was allocated in Tcl_GetThreadData using * ckalloc; use ckfree to dispose of it. */ ckfree(blockPtr); } } /* * Delete thread specific hash table and free the struct. */ Tcl_DeleteHashTable(hashTablePtr); TclpSysFree((char *) hashTablePtr); } }
static void FreeThreadStorageEntry( Tcl_HashEntry *hPtr) /* Hash entry to free. */ { TclpSysFree((char *) hPtr); }