diff options
Diffstat (limited to 'generic/tclThreadAlloc.c')
| -rw-r--r-- | generic/tclThreadAlloc.c | 403 |
1 files changed, 145 insertions, 258 deletions
diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index df4d2e3..106e908 100644 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -6,14 +6,14 @@ * fixed size blocks from block caches. * * The Initial Developer of the Original Code is America Online, Inc. - * Portions created by AOL are Copyright © 1999 America Online, Inc. + * Portions created by AOL are Copyright (C) 1999 America Online, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" -#if TCL_THREADS && defined(USE_THREAD_ALLOC) +#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) /* * If range checking is enabled, an additional byte will be allocated to store @@ -35,9 +35,7 @@ */ #define NOBJALLOC 800 - -/* Actual definition moved to tclInt.h */ -#define NOBJHIGH ALLOC_NOBJHIGH +#define NOBJHIGH 1200 /* * The following union stores accounting information for each block including @@ -82,33 +80,30 @@ typedef union Block { * and statistics information. */ -typedef struct { +typedef struct Bucket { Block *firstPtr; /* First block available */ - Block *lastPtr; /* End of block list */ - size_t numFree; /* Number of blocks available */ + long numFree; /* Number of blocks available */ /* All fields below for accounting only */ - size_t numRemoves; /* Number of removes from bucket */ - size_t numInserts; /* Number of inserts into bucket */ - size_t numLocks; /* Number of locks acquired */ - size_t totalAssigned; /* Total space assigned to bucket */ + long numRemoves; /* Number of removes from bucket */ + long numInserts; /* Number of inserts into bucket */ + long numWaits; /* Number of waits to acquire a lock */ + long numLocks; /* Number of locks acquired */ + long totalAssigned; /* Total space assigned to bucket */ } Bucket; /* * The following structure defines a cache of buckets and objs, of which there - * will be (at most) one per thread. Any changes need to be reflected in the - * struct AllocCache defined in tclInt.h, possibly also in the initialisation - * code in Tcl_CreateInterp(). + * will be (at most) one per thread. */ typedef struct Cache { struct Cache *nextPtr; /* Linked list of cache entries */ Tcl_ThreadId owner; /* Which thread's cache is this? */ Tcl_Obj *firstObjPtr; /* List of free objects for thread */ - size_t numObjects; /* Number of objects for thread */ - Tcl_Obj *lastPtr; /* Last object in this cache */ - size_t totalAssigned; /* Total space assigned to thread */ + int numObjects; /* Number of objects for thread */ + int totalAssigned; /* Total space assigned to thread */ Bucket buckets[NBUCKETS]; /* The buckets for this thread */ } Cache; @@ -119,8 +114,8 @@ typedef struct Cache { static struct { size_t blockSize; /* Bucket blocksize. */ - size_t maxBlocks; /* Max blocks before move to share. */ - size_t numMove; /* Num blocks to move to share. */ + int maxBlocks; /* Max blocks before move to share. */ + int numMove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ } bucketInfo[NBUCKETS]; @@ -131,12 +126,11 @@ static struct { static Cache * GetCache(void); static void LockBucket(Cache *cachePtr, int bucket); static void UnlockBucket(Cache *cachePtr, int bucket); -static void PutBlocks(Cache *cachePtr, int bucket, size_t numMove); +static void PutBlocks(Cache *cachePtr, int bucket, int numMove); static int GetBlocks(Cache *cachePtr, int bucket); -static Block * Ptr2Block(void *ptr); -static void * Block2Ptr(Block *blockPtr, int bucket, size_t reqSize); -static void MoveObjs(Cache *fromPtr, Cache *toPtr, size_t numMove); -static void PutObjs(Cache *fromPtr, size_t numMove); +static Block * Ptr2Block(char *ptr); +static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); +static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); /* * Local variables defined in this file and initialized at startup. @@ -147,26 +141,6 @@ static Tcl_Mutex *objLockPtr; static Cache sharedCache; static Cache *sharedPtr = &sharedCache; static Cache *firstCachePtr = &sharedCache; - -#if defined(HAVE_FAST_TSD) -static __thread Cache *tcachePtr; - -# define GETCACHE(cachePtr) \ - do { \ - if (!tcachePtr) { \ - tcachePtr = GetCache(); \ - } \ - (cachePtr) = tcachePtr; \ - } while (0) -#else -# define GETCACHE(cachePtr) \ - do { \ - (cachePtr) = (Cache*)TclpGetAllocCache(); \ - if ((cachePtr) == NULL) { \ - (cachePtr) = GetCache(); \ - } \ - } while (0) -#endif /* *---------------------------------------------------------------------- @@ -195,11 +169,20 @@ GetCache(void) if (listLockPtr == NULL) { Tcl_Mutex *initLockPtr; + unsigned int i; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); if (listLockPtr == NULL) { - TclInitThreadAlloc(); + listLockPtr = TclpNewAllocMutex(); + objLockPtr = TclpNewAllocMutex(); + for (i = 0; i < NBUCKETS; ++i) { + bucketInfo[i].blockSize = MINALLOC << i; + bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i); + bucketInfo[i].numMove = i < NBUCKETS - 1 ? + 1 << (NBUCKETS - 2 - i) : 1; + bucketInfo[i].lockPtr = TclpNewAllocMutex(); + } } Tcl_MutexUnlock(initLockPtr); } @@ -208,13 +191,12 @@ GetCache(void) * Get this thread's cache, allocating if necessary. */ - cachePtr = (Cache*)TclpGetAllocCache(); + cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { - cachePtr = (Cache*)TclpSysAlloc(sizeof(Cache), 0); + cachePtr = calloc(1, sizeof(Cache)); if (cachePtr == NULL) { Tcl_Panic("alloc: could not allocate new cache"); } - memset(cachePtr, 0, sizeof(Cache)); Tcl_MutexLock(listLockPtr); cachePtr->nextPtr = firstCachePtr; firstCachePtr = cachePtr; @@ -245,9 +227,9 @@ void TclFreeAllocCache( void *arg) { - Cache *cachePtr = (Cache*)arg; + Cache *cachePtr = arg; Cache **nextPtrPtr; - unsigned int bucket; + register unsigned int bucket; /* * Flush blocks. @@ -264,7 +246,9 @@ TclFreeAllocCache( */ if (cachePtr->numObjects > 0) { - PutObjs(cachePtr, cachePtr->numObjects); + Tcl_MutexLock(objLockPtr); + MoveObjs(cachePtr, sharedPtr, cachePtr->numObjects); + Tcl_MutexUnlock(objLockPtr); } /* @@ -279,7 +263,7 @@ TclFreeAllocCache( *nextPtrPtr = cachePtr->nextPtr; cachePtr->nextPtr = NULL; Tcl_MutexUnlock(listLockPtr); - TclpSysFree(cachePtr); + free(cachePtr); } /* @@ -298,13 +282,13 @@ TclFreeAllocCache( *---------------------------------------------------------------------- */ -void * +char * TclpAlloc( unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; - int bucket; + register int bucket; size_t size; #ifndef __LP64__ @@ -320,11 +304,14 @@ TclpAlloc( } #endif - GETCACHE(cachePtr); + cachePtr = TclpGetAllocCache(); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * Increment the requested size to include room for the Block structure. - * Call TclpSysAlloc() directly if the required amount is greater than the + * Call malloc() directly if the required amount is greater than the * largest block, otherwise pop the smallest block large enough, * allocating more blocks if necessary. */ @@ -332,24 +319,24 @@ TclpAlloc( blockPtr = NULL; size = reqSize + sizeof(Block); #if RCHECK - size++; + ++size; #endif if (size > MAXALLOC) { bucket = NBUCKETS; - blockPtr = (Block *)TclpSysAlloc(size, 0); + blockPtr = malloc(size); if (blockPtr != NULL) { cachePtr->totalAssigned += reqSize; } } else { bucket = 0; while (bucketInfo[bucket].blockSize < size) { - bucket++; + ++bucket; } if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) { blockPtr = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr->nextBlock; - cachePtr->buckets[bucket].numFree--; - cachePtr->buckets[bucket].numRemoves++; + --cachePtr->buckets[bucket].numFree; + ++cachePtr->buckets[bucket].numRemoves; cachePtr->buckets[bucket].totalAssigned += reqSize; } } @@ -377,7 +364,7 @@ TclpAlloc( void TclpFree( - void *ptr) + char *ptr) { Cache *cachePtr; Block *blockPtr; @@ -387,7 +374,10 @@ TclpFree( return; } - GETCACHE(cachePtr); + cachePtr = TclpGetAllocCache(); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * Get the block back from the user pointer and call system free directly @@ -399,18 +389,15 @@ TclpFree( bucket = blockPtr->sourceBucket; if (bucket == NBUCKETS) { cachePtr->totalAssigned -= blockPtr->blockReqSize; - TclpSysFree(blockPtr); + free(blockPtr); return; } cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; - if (cachePtr->buckets[bucket].numFree == 0) { - cachePtr->buckets[bucket].lastPtr = blockPtr; - } - cachePtr->buckets[bucket].numFree++; - cachePtr->buckets[bucket].numInserts++; + ++cachePtr->buckets[bucket].numFree; + ++cachePtr->buckets[bucket].numInserts; if (cachePtr != sharedPtr && cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) { @@ -434,9 +421,9 @@ TclpFree( *---------------------------------------------------------------------- */ -void * +char * TclpRealloc( - void *ptr, + char *ptr, unsigned int reqSize) { Cache *cachePtr; @@ -462,18 +449,21 @@ TclpRealloc( } #endif - GETCACHE(cachePtr); + cachePtr = TclpGetAllocCache(); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * If the block is not a system block and fits in place, simply return the * existing pointer. Otherwise, if the block is a system block and the new - * size would also require a system block, call TclpSysRealloc() directly. + * size would also require a system block, call realloc() directly. */ blockPtr = Ptr2Block(ptr); size = reqSize + sizeof(Block); #if RCHECK - size++; + ++size; #endif bucket = blockPtr->sourceBucket; if (bucket != NBUCKETS) { @@ -490,7 +480,7 @@ TclpRealloc( } else if (size > MAXALLOC) { cachePtr->totalAssigned -= blockPtr->blockReqSize; cachePtr->totalAssigned += reqSize; - blockPtr = (Block*)TclpSysRealloc(blockPtr, size); + blockPtr = realloc(blockPtr, size); if (blockPtr == NULL) { return NULL; } @@ -526,20 +516,18 @@ TclpRealloc( * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if * list is empty. * - * Note: - * If this code is updated, the changes need to be reflected in the macro - * TclAllocObjStorageEx() defined in tclInt.h - * *---------------------------------------------------------------------- */ Tcl_Obj * TclThreadAllocObj(void) { - Cache *cachePtr; - Tcl_Obj *objPtr; + register Cache *cachePtr = TclpGetAllocCache(); + register Tcl_Obj *objPtr; - GETCACHE(cachePtr); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * Get this thread's obj list structure and move or allocate new objs if @@ -547,7 +535,7 @@ TclThreadAllocObj(void) */ if (cachePtr->numObjects == 0) { - size_t numMove; + register int numMove; Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; @@ -562,17 +550,15 @@ TclThreadAllocObj(void) Tcl_Obj *newObjsPtr; cachePtr->numObjects = numMove = NOBJALLOC; - newObjsPtr = (Tcl_Obj *)TclpSysAlloc(sizeof(Tcl_Obj) * numMove, 0); + newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove); if (newObjsPtr == NULL) { - Tcl_Panic("alloc: could not allocate %" TCL_Z_MODIFIER "u new objects", numMove); + Tcl_Panic("alloc: could not allocate %d new objects", numMove); } - cachePtr->lastPtr = newObjsPtr + numMove - 1; - objPtr = cachePtr->firstObjPtr; /* NULL */ - while (numMove-- > 0) { - newObjsPtr[numMove].internalRep.twoPtrValue.ptr1 = objPtr; - objPtr = newObjsPtr + numMove; + while (--numMove >= 0) { + objPtr = &newObjsPtr[numMove]; + objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; + cachePtr->firstObjPtr = objPtr; } - cachePtr->firstObjPtr = newObjsPtr; } } @@ -581,8 +567,8 @@ TclThreadAllocObj(void) */ objPtr = cachePtr->firstObjPtr; - cachePtr->firstObjPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1; - cachePtr->numObjects--; + cachePtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1; + --cachePtr->numObjects; return objPtr; } @@ -599,10 +585,6 @@ TclThreadAllocObj(void) * Side effects: * May move free Tcl_Obj's to shared list upon hitting high water mark. * - * Note: - * If this code is updated, the changes need to be reflected in the macro - * TclAllocObjStorageEx() defined in tclInt.h - * *---------------------------------------------------------------------- */ @@ -610,9 +592,11 @@ void TclThreadFreeObj( Tcl_Obj *objPtr) { - Cache *cachePtr; + Cache *cachePtr = TclpGetAllocCache(); - GETCACHE(cachePtr); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * Get this thread's list and push on the free Tcl_Obj. @@ -620,10 +604,7 @@ TclThreadFreeObj( objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; - if (cachePtr->numObjects == 0) { - cachePtr->lastPtr = objPtr; - } - cachePtr->numObjects++; + ++cachePtr->numObjects; /* * If the number of free objects has exceeded the high water mark, move @@ -631,7 +612,9 @@ TclThreadFreeObj( */ if (cachePtr->numObjects > NOBJHIGH) { - PutObjs(cachePtr, NOBJALLOC); + Tcl_MutexLock(objLockPtr); + MoveObjs(cachePtr, sharedPtr, NOBJALLOC); + Tcl_MutexUnlock(objLockPtr); } } @@ -666,18 +649,18 @@ Tcl_GetMemoryInfo( if (cachePtr == sharedPtr) { Tcl_DStringAppendElement(dsPtr, "shared"); } else { - snprintf(buf, sizeof(buf), "thread%p", cachePtr->owner); + sprintf(buf, "thread%p", cachePtr->owner); Tcl_DStringAppendElement(dsPtr, buf); } for (n = 0; n < NBUCKETS; ++n) { - snprintf(buf, sizeof(buf), "%" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" - TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u", - bucketInfo[n].blockSize, + sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld", + (unsigned long) bucketInfo[n].blockSize, cachePtr->buckets[n].numFree, cachePtr->buckets[n].numRemoves, cachePtr->buckets[n].numInserts, cachePtr->buckets[n].totalAssigned, - cachePtr->buckets[n].numLocks); + cachePtr->buckets[n].numLocks, + cachePtr->buckets[n].numWaits); Tcl_DStringAppendElement(dsPtr, buf); } Tcl_DStringEndSublist(dsPtr); @@ -706,9 +689,9 @@ static void MoveObjs( Cache *fromPtr, Cache *toPtr, - size_t numMove) + int numMove) { - Tcl_Obj *objPtr = fromPtr->firstObjPtr; + register Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; @@ -719,77 +702,23 @@ MoveObjs( * to be moved) as the first object in the 'from' cache. */ - while (numMove-- > 1) { - objPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1; + while (--numMove) { + objPtr = objPtr->internalRep.twoPtrValue.ptr1; } - fromPtr->firstObjPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1; + fromPtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1; /* * Move all objects as a block - they are already linked to each other, we * just have to update the first and last. */ - toPtr->lastPtr = objPtr; - objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr; /* NULL */ + objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr; toPtr->firstObjPtr = fromFirstObjPtr; } /* *---------------------------------------------------------------------- * - * PutObjs -- - * - * Move Tcl_Obj's from thread cache to shared cache. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static void -PutObjs( - Cache *fromPtr, - size_t numMove) -{ - size_t keep = fromPtr->numObjects - numMove; - Tcl_Obj *firstPtr, *lastPtr = NULL; - - fromPtr->numObjects = keep; - firstPtr = fromPtr->firstObjPtr; - if (keep == 0) { - fromPtr->firstObjPtr = NULL; - } else { - do { - lastPtr = firstPtr; - firstPtr = (Tcl_Obj *)firstPtr->internalRep.twoPtrValue.ptr1; - } while (keep-- > 1); - lastPtr->internalRep.twoPtrValue.ptr1 = NULL; - } - - /* - * Move all objects as a block - they are already linked to each other, we - * just have to update the first and last. - */ - - Tcl_MutexLock(objLockPtr); - fromPtr->lastPtr->internalRep.twoPtrValue.ptr1 = sharedPtr->firstObjPtr; - sharedPtr->firstObjPtr = firstPtr; - if (sharedPtr->numObjects == 0) { - sharedPtr->lastPtr = fromPtr->lastPtr; - } - sharedPtr->numObjects += numMove; - Tcl_MutexUnlock(objLockPtr); - - fromPtr->lastPtr = lastPtr; -} - -/* - *---------------------------------------------------------------------- - * * Block2Ptr, Ptr2Block -- * * Convert between internal blocks and user pointers. @@ -803,13 +732,13 @@ PutObjs( *---------------------------------------------------------------------- */ -static void * +static char * Block2Ptr( Block *blockPtr, int bucket, - size_t reqSize) + unsigned int reqSize) { - void *ptr; + register void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; @@ -818,14 +747,14 @@ Block2Ptr( #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; #endif - return ptr; + return (char *) ptr; } static Block * Ptr2Block( - void *ptr) + char *ptr) { - Block *blockPtr; + register Block *blockPtr; blockPtr = (((Block *) ptr) - 1); if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { @@ -864,14 +793,22 @@ LockBucket( Cache *cachePtr, int bucket) { +#if 0 + if (Tcl_MutexTryLock(bucketInfo[bucket].lockPtr) != TCL_OK) { + Tcl_MutexLock(bucketInfo[bucket].lockPtr); + ++cachePtr->buckets[bucket].numWaits; + ++sharedPtr->buckets[bucket].numWaits; + } +#else Tcl_MutexLock(bucketInfo[bucket].lockPtr); - cachePtr->buckets[bucket].numLocks++; - sharedPtr->buckets[bucket].numLocks++; +#endif + ++cachePtr->buckets[bucket].numLocks; + ++sharedPtr->buckets[bucket].numLocks; } static void UnlockBucket( - TCL_UNUSED(Cache *), + Cache *cachePtr, int bucket) { Tcl_MutexUnlock(bucketInfo[bucket].lockPtr); @@ -897,27 +834,22 @@ static void PutBlocks( Cache *cachePtr, int bucket, - size_t numMove) + int numMove) { + register Block *lastPtr, *firstPtr; + register int n = numMove; + /* - * We have numFree. Want to shed numMove. So compute how many - * Blocks to keep. + * Before acquiring the lock, walk the block list to find the last block + * to be moved. */ - size_t keep = cachePtr->buckets[bucket].numFree - numMove; - Block *lastPtr = NULL, *firstPtr; - - cachePtr->buckets[bucket].numFree = keep; - firstPtr = cachePtr->buckets[bucket].firstPtr; - if (keep == 0) { - cachePtr->buckets[bucket].firstPtr = NULL; - } else { - do { - lastPtr = firstPtr; - firstPtr = firstPtr->nextBlock; - } while (keep-- > 1); - lastPtr->nextBlock = NULL; + firstPtr = lastPtr = cachePtr->buckets[bucket].firstPtr; + while (--n > 0) { + lastPtr = lastPtr->nextBlock; } + cachePtr->buckets[bucket].firstPtr = lastPtr->nextBlock; + cachePtr->buckets[bucket].numFree -= numMove; /* * Aquire the lock and place the list of blocks at the front of the shared @@ -925,17 +857,10 @@ PutBlocks( */ LockBucket(cachePtr, bucket); - cachePtr->buckets[bucket].lastPtr->nextBlock - = sharedPtr->buckets[bucket].firstPtr; + lastPtr->nextBlock = sharedPtr->buckets[bucket].firstPtr; sharedPtr->buckets[bucket].firstPtr = firstPtr; - if (sharedPtr->buckets[bucket].numFree == 0) { - sharedPtr->buckets[bucket].lastPtr - = cachePtr->buckets[bucket].lastPtr; - } sharedPtr->buckets[bucket].numFree += numMove; UnlockBucket(cachePtr, bucket); - - cachePtr->buckets[bucket].lastPtr = lastPtr; } /* @@ -959,11 +884,11 @@ GetBlocks( Cache *cachePtr, int bucket) { - Block *blockPtr; - size_t n; + register Block *blockPtr; + register int n; /* - * First, attempt to move blocks from the shared cache. Note the + * First, atttempt to move blocks from the shared cache. Note the * potentially dirty read of numFree before acquiring the lock which is a * slight performance enhancement. The value is verified after the lock is * actually acquired. @@ -982,8 +907,6 @@ GetBlocks( if (n >= sharedPtr->buckets[bucket].numFree) { cachePtr->buckets[bucket].firstPtr = sharedPtr->buckets[bucket].firstPtr; - cachePtr->buckets[bucket].lastPtr = - sharedPtr->buckets[bucket].lastPtr; cachePtr->buckets[bucket].numFree = sharedPtr->buckets[bucket].numFree; sharedPtr->buckets[bucket].firstPtr = NULL; @@ -993,11 +916,10 @@ GetBlocks( cachePtr->buckets[bucket].firstPtr = blockPtr; sharedPtr->buckets[bucket].numFree -= n; cachePtr->buckets[bucket].numFree = n; - while (n-- > 1) { + while (--n > 0) { blockPtr = blockPtr->nextBlock; } sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock; - cachePtr->buckets[bucket].lastPtr = blockPtr; blockPtr->nextBlock = NULL; } } @@ -1005,7 +927,7 @@ GetBlocks( } if (cachePtr->buckets[bucket].numFree == 0) { - size_t size; + register size_t size; /* * If no blocks could be moved from shared, first look for a larger @@ -1014,13 +936,13 @@ GetBlocks( blockPtr = NULL; n = NBUCKETS; - size = 0; - while (n-- > (size_t)bucket + 1) { + size = 0; /* lint */ + while (--n > bucket) { if (cachePtr->buckets[n].numFree > 0) { size = bucketInfo[n].blockSize; blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; - cachePtr->buckets[n].numFree--; + --cachePtr->buckets[n].numFree; break; } } @@ -1031,7 +953,7 @@ GetBlocks( if (blockPtr == NULL) { size = MAXALLOC; - blockPtr = (Block*)TclpSysAlloc(size, 0); + blockPtr = malloc(size); if (blockPtr == NULL) { return 0; } @@ -1044,50 +966,15 @@ GetBlocks( n = size / bucketInfo[bucket].blockSize; cachePtr->buckets[bucket].numFree = n; cachePtr->buckets[bucket].firstPtr = blockPtr; - while (n-- > 1) { + while (--n > 0) { blockPtr->nextBlock = (Block *) ((char *) blockPtr + bucketInfo[bucket].blockSize); blockPtr = blockPtr->nextBlock; } - cachePtr->buckets[bucket].lastPtr = blockPtr; blockPtr->nextBlock = NULL; } return 1; } - -/* - *---------------------------------------------------------------------- - * - * TclInitThreadAlloc -- - * - * Initializes the allocator cache-maintenance structures. - * It is done early and protected during the Tcl_InitSubsystems(). - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclInitThreadAlloc(void) -{ - unsigned int i; - - listLockPtr = TclpNewAllocMutex(); - objLockPtr = TclpNewAllocMutex(); - for (i = 0; i < NBUCKETS; ++i) { - bucketInfo[i].blockSize = MINALLOC << i; - bucketInfo[i].maxBlocks = ((size_t)1) << (NBUCKETS - 1 - i); - bucketInfo[i].numMove = i < NBUCKETS - 1 ? - (size_t)1 << (NBUCKETS - 2 - i) : 1; - bucketInfo[i].lockPtr = TclpNewAllocMutex(); - } - TclpInitAllocCache(); -} /* *---------------------------------------------------------------------- @@ -1112,8 +999,8 @@ TclFinalizeThreadAlloc(void) unsigned int i; for (i = 0; i < NBUCKETS; ++i) { - TclpFreeAllocMutex(bucketInfo[i].lockPtr); - bucketInfo[i].lockPtr = NULL; + TclpFreeAllocMutex(bucketInfo[i].lockPtr); + bucketInfo[i].lockPtr = NULL; } TclpFreeAllocMutex(objLockPtr); @@ -1130,9 +1017,9 @@ TclFinalizeThreadAlloc(void) * * TclFinalizeThreadAllocThread -- * - * This procedure is used to destroy single thread private resources - * defined in this file. Called either during Tcl_FinalizeThread() or - * Tcl_Finalize(). + * This procedure is used to destroy single thread private resources used + * in this file. + * Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread). * * Results: * None. @@ -1146,7 +1033,7 @@ TclFinalizeThreadAlloc(void) void TclFinalizeThreadAllocThread(void) { - Cache *cachePtr = (Cache *)TclpGetAllocCache(); + Cache *cachePtr = TclpGetAllocCache(); if (cachePtr != NULL) { TclpFreeAllocCache(cachePtr); } @@ -1171,7 +1058,7 @@ TclFinalizeThreadAllocThread(void) void Tcl_GetMemoryInfo( - TCL_UNUSED(Tcl_DString *)) + Tcl_DString *dsPtr) { Tcl_Panic("Tcl_GetMemoryInfo called when threaded memory allocator not in use"); } |
