diff options
Diffstat (limited to 'generic/tclThreadAlloc.c')
| -rw-r--r-- | generic/tclThreadAlloc.c | 148 |
1 files changed, 82 insertions, 66 deletions
diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index f754bde..106e908 100644 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -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 @@ -97,16 +95,14 @@ typedef struct 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 */ + int numObjects; /* Number of objects for thread */ int totalAssigned; /* Total space assigned to thread */ Bucket buckets[NBUCKETS]; /* The buckets for this thread */ } Cache; @@ -133,7 +129,7 @@ static void UnlockBucket(Cache *cachePtr, int bucket); static void PutBlocks(Cache *cachePtr, int bucket, int numMove); static int GetBlocks(Cache *cachePtr, int bucket); static Block * Ptr2Block(char *ptr); -static char * Block2Ptr(Block *blockPtr, int bucket, size_t reqSize); +static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); /* @@ -145,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) = TclpGetAllocCache(); \ - if ((cachePtr) == NULL) { \ - (cachePtr) = GetCache(); \ - } \ - } while (0) -#endif /* *---------------------------------------------------------------------- @@ -308,7 +284,7 @@ TclFreeAllocCache( char * TclpAlloc( - size_t reqSize) + unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; @@ -328,7 +304,10 @@ TclpAlloc( } #endif - GETCACHE(cachePtr); + cachePtr = TclpGetAllocCache(); + if (cachePtr == NULL) { + cachePtr = GetCache(); + } /* * Increment the requested size to include room for the Block structure. @@ -340,7 +319,7 @@ TclpAlloc( blockPtr = NULL; size = reqSize + sizeof(Block); #if RCHECK - size++; + ++size; #endif if (size > MAXALLOC) { bucket = NBUCKETS; @@ -351,13 +330,13 @@ TclpAlloc( } 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; } } @@ -395,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 @@ -414,8 +396,8 @@ TclpFree( cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = 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) { @@ -442,7 +424,7 @@ TclpFree( char * TclpRealloc( char *ptr, - size_t reqSize) + unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; @@ -467,7 +449,10 @@ 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 @@ -478,7 +463,7 @@ TclpRealloc( blockPtr = Ptr2Block(ptr); size = reqSize + sizeof(Block); #if RCHECK - size++; + ++size; #endif bucket = blockPtr->sourceBucket; if (bucket != NBUCKETS) { @@ -531,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) { - register Cache *cachePtr; + 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 @@ -573,7 +556,7 @@ TclThreadAllocObj(void) } while (--numMove >= 0) { objPtr = &newObjsPtr[numMove]; - objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; + objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; } } @@ -584,8 +567,8 @@ TclThreadAllocObj(void) */ objPtr = cachePtr->firstObjPtr; - cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr; - cachePtr->numObjects--; + cachePtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1; + --cachePtr->numObjects; return objPtr; } @@ -602,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 - * *---------------------------------------------------------------------- */ @@ -613,17 +592,19 @@ 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. */ - objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; + objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; - cachePtr->numObjects++; + ++cachePtr->numObjects; /* * If the number of free objects has exceeded the high water mark, move @@ -722,16 +703,16 @@ MoveObjs( */ while (--numMove) { - objPtr = objPtr->internalRep.otherValuePtr; + objPtr = objPtr->internalRep.twoPtrValue.ptr1; } - fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr; + 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. */ - objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr; + objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr; toPtr->firstObjPtr = fromFirstObjPtr; } @@ -755,7 +736,7 @@ static char * Block2Ptr( Block *blockPtr, int bucket, - size_t reqSize) + unsigned int reqSize) { register void *ptr; @@ -812,9 +793,17 @@ 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 @@ -953,7 +942,7 @@ GetBlocks( size = bucketInfo[n].blockSize; blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; - cachePtr->buckets[n].numFree--; + --cachePtr->buckets[n].numFree; break; } } @@ -1010,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); @@ -1023,6 +1012,33 @@ TclFinalizeThreadAlloc(void) TclpFreeAllocCache(NULL); } +/* + *---------------------------------------------------------------------- + * + * TclFinalizeThreadAllocThread -- + * + * 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. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeThreadAllocThread(void) +{ + Cache *cachePtr = TclpGetAllocCache(); + if (cachePtr != NULL) { + TclpFreeAllocCache(cachePtr); + } +} + #else /* !(TCL_THREADS && USE_THREAD_ALLOC) */ /* *---------------------------------------------------------------------- |
