diff options
Diffstat (limited to 'generic/tclThreadAlloc.c')
| -rwxr-xr-x[-rw-r--r--] | generic/tclThreadAlloc.c | 736 |
1 files changed, 354 insertions, 382 deletions
diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 9008d52..ad9f0a0 100644..100755 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -2,22 +2,31 @@ * tclThreadAlloc.c -- * * This is a very fast storage allocator for used with threads (designed - * avoid lock contention). The basic strategy is to allocate memory in - * fixed size blocks from block caches. - * + * avoid lock contention). The basic strategy is to allocate memory in + * fixed size blocks from block caches. + * * The Initial Developer of the Original Code is 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. + * 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 defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) + +#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG) + +#ifdef WIN32 +#include "tclWinInt.h" +#else +extern Tcl_Mutex *TclpNewAllocMutex(void); +extern void *TclpGetAllocCache(void); +extern void TclpSetAllocCache(void *); +#endif /* - * If range checking is enabled, an additional byte will be allocated to store - * the magic number at the end of the requested memory. + * If range checking is enabled, an additional byte will be allocated + * to store the magic number at the end of the requested memory. */ #ifndef RCHECK @@ -29,21 +38,33 @@ #endif /* - * The following define the number of Tcl_Obj's to allocate/move at a time and - * the high water mark to prune a per-thread cache. On a 32 bit system, - * sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k. + * The following define the number of Tcl_Obj's to allocate/move + * at a time and the high water mark to prune a per-thread cache. + * On a 32 bit system, sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k. + * */ - -#define NOBJALLOC 800 + +#define NOBJALLOC 800 #define NOBJHIGH 1200 /* - * The following union stores accounting information for each block including - * two small magic numbers and a bucket number when in use or a next pointer - * when free. The original requested size (not including the Block overhead) - * is also maintained. + * Alignment for allocated memory. */ +#if defined(__APPLE__) +#define ALLOCALIGN 16 +#else +#define ALLOCALIGN 8 +#endif + +/* + * The following union stores accounting information for + * each block including two small magic numbers and + * a bucket number when in use or a next pointer when + * free. The original requested size (not including + * the Block overhead) is also maintained. + */ + typedef union Block { struct { union { @@ -57,95 +78,93 @@ typedef union Block { } u; size_t reqSize; /* Requested allocation size. */ } b; - unsigned char padding[TCL_ALLOCALIGN]; + unsigned char padding[ALLOCALIGN]; } Block; -#define nextBlock b.u.next -#define sourceBucket b.u.s.bucket -#define magicNum1 b.u.s.magic1 -#define magicNum2 b.u.s.magic2 -#define MAGIC 0xEF -#define blockReqSize b.reqSize +#define b_next b.u.next +#define b_bucket b.u.s.bucket +#define b_magic1 b.u.s.magic1 +#define b_magic2 b.u.s.magic2 +#define MAGIC 0xef +#define b_reqsize b.reqSize /* * The following defines the minimum and and maximum block sizes and the number * of buckets in the bucket cache. */ -#define MINALLOC ((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) +#define MINALLOC ((sizeof(Block) + 8 + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1)) #define NBUCKETS (11 - (MINALLOC >> 5)) #define MAXALLOC (MINALLOC << (NBUCKETS - 1)) /* - * The following structure defines a bucket of blocks with various accounting - * and statistics information. + * The following structure defines a bucket of blocks with + * various accounting and statistics information. */ typedef struct Bucket { - Block *firstPtr; /* First block available */ - long numFree; /* Number of blocks available */ - - /* All fields below for accounting only */ - - 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 */ + Block *firstPtr; + long nfree; + long nget; + long nput; + long nwait; + long nlock; + long nrequest; } Bucket; /* - * The following structure defines a cache of buckets and objs, of which there - * will be (at most) one per thread. + * The following structure defines a cache of buckets and objs. */ 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 */ - int numObjects; /* Number of objects for thread */ - int totalAssigned; /* Total space assigned to thread */ - Bucket buckets[NBUCKETS]; /* The buckets for this thread */ + struct Cache *nextPtr; + Tcl_ThreadId owner; + Tcl_Obj *firstObjPtr; + int nobjs; + int nsysalloc; + Bucket buckets[NBUCKETS]; } Cache; /* - * The following array specifies various per-bucket limits and locks. The - * values are statically initialized to avoid calculating them repeatedly. + * The following array specifies various per-bucket + * limits and locks. The values are statically initialized + * to avoid calculating them repeatedly. */ -static struct { - size_t blockSize; /* Bucket blocksize. */ - int maxBlocks; /* Max blocks before move to share. */ - int numMove; /* Num blocks to move to share. */ - Tcl_Mutex *lockPtr; /* Share bucket lock. */ -} bucketInfo[NBUCKETS]; +struct binfo { + size_t blocksize; /* Bucket blocksize. */ + int maxblocks; /* Max blocks before move to share. */ + int nmove; /* Num blocks to move to share. */ + Tcl_Mutex *lockPtr; /* Share bucket lock. */ +} binfo[NBUCKETS]; /* * Static functions defined in this file. */ -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, int numMove); -static int GetBlocks(Cache *cachePtr, int bucket); -static Block * Ptr2Block(char *ptr); -static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); -static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); +static void LockBucket(Cache *cachePtr, int bucket); +static void UnlockBucket(Cache *cachePtr, int bucket); +static void PutBlocks(Cache *cachePtr, int bucket, int nmove); +static int GetBlocks(Cache *cachePtr, int bucket); +static Block *Ptr2Block(char *ptr); +static char *Block2Ptr(Block *blockPtr, int bucket, unsigned int reqsize); +static void MoveObjs(Cache *fromPtr, Cache *toPtr, int nmove); /* - * Local variables defined in this file and initialized at startup. + * Local variables defined in this file and initialized at + * startup. */ static Tcl_Mutex *listLockPtr; static Tcl_Mutex *objLockPtr; -static Cache sharedCache; -static Cache *sharedPtr = &sharedCache; -static Cache *firstCachePtr = &sharedCache; +static Cache sharedCache; +static Cache *sharedPtr = &sharedCache; +static Cache *firstCachePtr = &sharedCache; + /* *---------------------------------------------------------------------- * - * GetCache --- + * GetCache --- * * Gets per-thread memory cache, allocating it if necessary. * @@ -153,7 +172,7 @@ static Cache *firstCachePtr = &sharedCache; * Pointer to cache. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -177,11 +196,10 @@ GetCache(void) 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(); + binfo[i].blocksize = MINALLOC << i; + binfo[i].maxblocks = 1 << (NBUCKETS - 1 - i); + binfo[i].nmove = i < NBUCKETS-1 ? 1 << (NBUCKETS - 2 - i) : 1; + binfo[i].lockPtr = TclpNewAllocMutex(); } } Tcl_MutexUnlock(initLockPtr); @@ -193,24 +211,25 @@ GetCache(void) cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { - cachePtr = calloc(1, sizeof(Cache)); - if (cachePtr == NULL) { - Tcl_Panic("alloc: could not allocate new cache"); - } - Tcl_MutexLock(listLockPtr); - cachePtr->nextPtr = firstCachePtr; - firstCachePtr = cachePtr; - Tcl_MutexUnlock(listLockPtr); - cachePtr->owner = Tcl_GetCurrentThread(); + cachePtr = calloc(1, sizeof(Cache)); + if (cachePtr == NULL) { + panic("alloc: could not allocate new cache"); + } + Tcl_MutexLock(listLockPtr); + cachePtr->nextPtr = firstCachePtr; + firstCachePtr = cachePtr; + Tcl_MutexUnlock(listLockPtr); + cachePtr->owner = Tcl_GetCurrentThread(); TclpSetAllocCache(cachePtr); } return cachePtr; } + /* *---------------------------------------------------------------------- * - * TclFreeAllocCache -- + * TclFreeAllocCache -- * * Flush and delete a cache, removing from list of caches. * @@ -224,8 +243,7 @@ GetCache(void) */ void -TclFreeAllocCache( - void *arg) +TclFreeAllocCache(void *arg) { Cache *cachePtr = arg; Cache **nextPtrPtr; @@ -236,8 +254,8 @@ TclFreeAllocCache( */ for (bucket = 0; bucket < NBUCKETS; ++bucket) { - if (cachePtr->buckets[bucket].numFree > 0) { - PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].numFree); + if (cachePtr->buckets[bucket].nfree > 0) { + PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].nfree); } } @@ -245,10 +263,10 @@ TclFreeAllocCache( * Flush objs. */ - if (cachePtr->numObjects > 0) { - Tcl_MutexLock(objLockPtr); - MoveObjs(cachePtr, sharedPtr, cachePtr->numObjects); - Tcl_MutexUnlock(objLockPtr); + if (cachePtr->nobjs > 0) { + Tcl_MutexLock(objLockPtr); + MoveObjs(cachePtr, sharedPtr, cachePtr->nobjs); + Tcl_MutexUnlock(objLockPtr); } /* @@ -265,11 +283,12 @@ TclFreeAllocCache( Tcl_MutexUnlock(listLockPtr); free(cachePtr); } + /* *---------------------------------------------------------------------- * - * TclpAlloc -- + * TclpAlloc -- * * Allocate memory. * @@ -283,73 +302,72 @@ TclFreeAllocCache( */ char * -TclpAlloc( - unsigned int reqSize) +TclpAlloc(unsigned int reqsize) { - Cache *cachePtr; - Block *blockPtr; - register int bucket; - size_t size; + Cache *cachePtr; + Block *blockPtr; + register int bucket; + size_t size; -#ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; - if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { + if (((size_t) reqsize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } -#endif cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = GetCache(); } - + /* - * Increment the requested size to include room for the Block structure. - * Call malloc() directly if the required amount is greater than the - * largest block, otherwise pop the smallest block large enough, + * Increment the requested size to include room for + * the Block structure. 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. */ - blockPtr = NULL; - size = reqSize + sizeof(Block); + blockPtr = NULL; + size = reqsize + sizeof(Block); #if RCHECK ++size; #endif if (size > MAXALLOC) { bucket = NBUCKETS; - blockPtr = malloc(size); + blockPtr = malloc(size); if (blockPtr != NULL) { - cachePtr->totalAssigned += reqSize; + cachePtr->nsysalloc += reqsize; } } else { - bucket = 0; - while (bucketInfo[bucket].blockSize < size) { - ++bucket; - } - if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) { + bucket = 0; + while (binfo[bucket].blocksize < size) { + ++bucket; + } + if (cachePtr->buckets[bucket].nfree || 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].totalAssigned += reqSize; + cachePtr->buckets[bucket].firstPtr = blockPtr->b_next; + --cachePtr->buckets[bucket].nfree; + ++cachePtr->buckets[bucket].nget; + cachePtr->buckets[bucket].nrequest += reqsize; } } if (blockPtr == NULL) { - return NULL; + return NULL; } - return Block2Ptr(blockPtr, bucket, reqSize); + return Block2Ptr(blockPtr, bucket, reqsize); } + /* *---------------------------------------------------------------------- * - * TclpFree -- + * TclpFree -- * * Return blocks to the thread block cache. * @@ -363,52 +381,49 @@ TclpAlloc( */ void -TclpFree( - char *ptr) +TclpFree(char *ptr) { - Cache *cachePtr; - Block *blockPtr; - int bucket; - - if (ptr == NULL) { - return; - } - - cachePtr = TclpGetAllocCache(); - if (cachePtr == NULL) { - cachePtr = GetCache(); - } + if (ptr != NULL) { + Cache *cachePtr = TclpGetAllocCache(); + Block *blockPtr; + int bucket; - /* - * Get the block back from the user pointer and call system free directly - * for large blocks. Otherwise, push the block back on the bucket and move - * blocks to the shared cache if there are now too many free. - */ - - blockPtr = Ptr2Block(ptr); - bucket = blockPtr->sourceBucket; - if (bucket == NBUCKETS) { - cachePtr->totalAssigned -= blockPtr->blockReqSize; - free(blockPtr); - return; - } - - 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; + if (cachePtr == NULL) { + cachePtr = GetCache(); + } + + /* + * Get the block back from the user pointer and + * call system free directly for large blocks. + * Otherwise, push the block back on the bucket and + * move blocks to the shared cache if there are now + * too many free. + */ - if (cachePtr != sharedPtr && - cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) { - PutBlocks(cachePtr, bucket, bucketInfo[bucket].numMove); + blockPtr = Ptr2Block(ptr); + bucket = blockPtr->b_bucket; + if (bucket == NBUCKETS) { + cachePtr->nsysalloc -= blockPtr->b_reqsize; + free(blockPtr); + } else { + cachePtr->buckets[bucket].nrequest -= blockPtr->b_reqsize; + blockPtr->b_next = cachePtr->buckets[bucket].firstPtr; + cachePtr->buckets[bucket].firstPtr = blockPtr; + ++cachePtr->buckets[bucket].nfree; + ++cachePtr->buckets[bucket].nput; + if (cachePtr != sharedPtr && + cachePtr->buckets[bucket].nfree > binfo[bucket].maxblocks) { + PutBlocks(cachePtr, bucket, binfo[bucket].nmove); + } + } } } + /* *---------------------------------------------------------------------- * - * TclpRealloc -- + * TclpRealloc -- * * Re-allocate memory to a larger or smaller size. * @@ -422,32 +437,28 @@ TclpFree( */ char * -TclpRealloc( - char *ptr, - unsigned int reqSize) +TclpRealloc(char *ptr, unsigned int reqsize) { Cache *cachePtr; Block *blockPtr; - void *newPtr; + void *new; size_t size, min; int bucket; if (ptr == NULL) { - return TclpAlloc(reqSize); + return TclpAlloc(reqsize); } -#ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; - if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { + if (((size_t) reqsize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } -#endif cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { @@ -455,52 +466,54 @@ TclpRealloc( } /* - * 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 realloc() directly. + * 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 realloc() directly. */ blockPtr = Ptr2Block(ptr); - size = reqSize + sizeof(Block); + size = reqsize + sizeof(Block); #if RCHECK ++size; #endif - bucket = blockPtr->sourceBucket; + bucket = blockPtr->b_bucket; if (bucket != NBUCKETS) { if (bucket > 0) { - min = bucketInfo[bucket-1].blockSize; + min = binfo[bucket-1].blocksize; } else { min = 0; } - if (size > min && size <= bucketInfo[bucket].blockSize) { - cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; - cachePtr->buckets[bucket].totalAssigned += reqSize; - return Block2Ptr(blockPtr, bucket, reqSize); + if (size > min && size <= binfo[bucket].blocksize) { + cachePtr->buckets[bucket].nrequest -= blockPtr->b_reqsize; + cachePtr->buckets[bucket].nrequest += reqsize; + return Block2Ptr(blockPtr, bucket, reqsize); } } else if (size > MAXALLOC) { - cachePtr->totalAssigned -= blockPtr->blockReqSize; - cachePtr->totalAssigned += reqSize; + cachePtr->nsysalloc -= blockPtr->b_reqsize; + cachePtr->nsysalloc += reqsize; blockPtr = realloc(blockPtr, size); if (blockPtr == NULL) { return NULL; } - return Block2Ptr(blockPtr, NBUCKETS, reqSize); + return Block2Ptr(blockPtr, NBUCKETS, reqsize); } /* * Finally, perform an expensive malloc/copy/free. */ - newPtr = TclpAlloc(reqSize); - if (newPtr != NULL) { - if (reqSize > blockPtr->blockReqSize) { - reqSize = blockPtr->blockReqSize; + new = TclpAlloc(reqsize); + if (new != NULL) { + if (reqsize > blockPtr->b_reqsize) { + reqsize = blockPtr->b_reqsize; } - memcpy(newPtr, ptr, reqSize); - TclpFree(ptr); + memcpy(new, ptr, reqsize); + TclpFree(ptr); } - return newPtr; + return new; } + /* *---------------------------------------------------------------------- @@ -513,8 +526,8 @@ TclpRealloc( * Pointer to uninitialized Tcl_Obj. * * Side effects: - * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if - * list is empty. + * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's + * if list is empty. * *---------------------------------------------------------------------- */ @@ -523,39 +536,37 @@ Tcl_Obj * TclThreadAllocObj(void) { register Cache *cachePtr = TclpGetAllocCache(); + register int nmove; register Tcl_Obj *objPtr; + Tcl_Obj *newObjsPtr; if (cachePtr == NULL) { cachePtr = GetCache(); } /* - * Get this thread's obj list structure and move or allocate new objs if - * necessary. + * Get this thread's obj list structure and move + * or allocate new objs if necessary. */ - - if (cachePtr->numObjects == 0) { - register int numMove; - - Tcl_MutexLock(objLockPtr); - numMove = sharedPtr->numObjects; - if (numMove > 0) { - if (numMove > NOBJALLOC) { - numMove = NOBJALLOC; + + if (cachePtr->nobjs == 0) { + Tcl_MutexLock(objLockPtr); + nmove = sharedPtr->nobjs; + if (nmove > 0) { + if (nmove > NOBJALLOC) { + nmove = NOBJALLOC; } - MoveObjs(sharedPtr, cachePtr, numMove); + MoveObjs(sharedPtr, cachePtr, nmove); } - Tcl_MutexUnlock(objLockPtr); - if (cachePtr->numObjects == 0) { - Tcl_Obj *newObjsPtr; - - cachePtr->numObjects = numMove = NOBJALLOC; - newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove); + Tcl_MutexUnlock(objLockPtr); + if (cachePtr->nobjs == 0) { + cachePtr->nobjs = nmove = NOBJALLOC; + newObjsPtr = malloc(sizeof(Tcl_Obj) * nmove); if (newObjsPtr == NULL) { - Tcl_Panic("alloc: could not allocate %d new objects", numMove); + panic("alloc: could not allocate %d new objects", nmove); } - while (--numMove >= 0) { - objPtr = &newObjsPtr[numMove]; + while (--nmove >= 0) { + objPtr = &newObjsPtr[nmove]; objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; } @@ -568,9 +579,10 @@ TclThreadAllocObj(void) objPtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr; - --cachePtr->numObjects; + --cachePtr->nobjs; return objPtr; } + /* *---------------------------------------------------------------------- @@ -583,14 +595,14 @@ TclThreadAllocObj(void) * None. * * Side effects: - * May move free Tcl_Obj's to shared list upon hitting high water mark. + * May move free Tcl_Obj's to shared list upon hitting high + * water mark. * *---------------------------------------------------------------------- */ void -TclThreadFreeObj( - Tcl_Obj *objPtr) +TclThreadFreeObj(Tcl_Obj *objPtr) { Cache *cachePtr = TclpGetAllocCache(); @@ -601,22 +613,23 @@ TclThreadFreeObj( /* * Get this thread's list and push on the free Tcl_Obj. */ - + objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; - ++cachePtr->numObjects; - + ++cachePtr->nobjs; + /* - * If the number of free objects has exceeded the high water mark, move - * some blocks to the shared list. + * If the number of free objects has exceeded the high + * water mark, move some blocks to the shared list. */ - - if (cachePtr->numObjects > NOBJHIGH) { + + if (cachePtr->nobjs > NOBJHIGH) { Tcl_MutexLock(objLockPtr); MoveObjs(cachePtr, sharedPtr, NOBJALLOC); Tcl_MutexUnlock(objLockPtr); } } + /* *---------------------------------------------------------------------- @@ -629,14 +642,13 @@ TclThreadFreeObj( * None. * * Side effects: - * List appended to given dstring. + * List appended to given dstring. * *---------------------------------------------------------------------- */ void -Tcl_GetMemoryInfo( - Tcl_DString *dsPtr) +Tcl_GetMemoryInfo(Tcl_DString *dsPtr) { Cache *cachePtr; char buf[200]; @@ -647,27 +659,28 @@ Tcl_GetMemoryInfo( while (cachePtr != NULL) { Tcl_DStringStartSublist(dsPtr); if (cachePtr == sharedPtr) { - Tcl_DStringAppendElement(dsPtr, "shared"); + Tcl_DStringAppendElement(dsPtr, "shared"); } else { - sprintf(buf, "thread%p", cachePtr->owner); - Tcl_DStringAppendElement(dsPtr, buf); + sprintf(buf, "thread%d", (int) cachePtr->owner); + Tcl_DStringAppendElement(dsPtr, buf); } for (n = 0; n < NBUCKETS; ++n) { - 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].numWaits); + sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld", + (unsigned long) binfo[n].blocksize, + cachePtr->buckets[n].nfree, + cachePtr->buckets[n].nget, + cachePtr->buckets[n].nput, + cachePtr->buckets[n].nrequest, + cachePtr->buckets[n].nlock, + cachePtr->buckets[n].nwait); Tcl_DStringAppendElement(dsPtr, buf); } Tcl_DStringEndSublist(dsPtr); - cachePtr = cachePtr->nextPtr; + cachePtr = cachePtr->nextPtr; } Tcl_MutexUnlock(listLockPtr); } + /* *---------------------------------------------------------------------- @@ -680,46 +693,45 @@ Tcl_GetMemoryInfo( * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ static void -MoveObjs( - Cache *fromPtr, - Cache *toPtr, - int numMove) +MoveObjs(Cache *fromPtr, Cache *toPtr, int nmove) { register Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; - toPtr->numObjects += numMove; - fromPtr->numObjects -= numMove; + toPtr->nobjs += nmove; + fromPtr->nobjs -= nmove; /* - * Find the last object to be moved; set the next one (the first one not - * to be moved) as the first object in the 'from' cache. + * Find the last object to be moved; set the next one + * (the first one not to be moved) as the first object + * in the 'from' cache. */ - while (--numMove) { + while (--nmove) { objPtr = objPtr->internalRep.otherValuePtr; } - fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr; + fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr; /* - * Move all objects as a block - they are already linked to each other, we - * just have to update the first and last. + * 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; toPtr->firstObjPtr = fromFirstObjPtr; } + /* *---------------------------------------------------------------------- * - * Block2Ptr, Ptr2Block -- + * Block2Ptr, Ptr2Block -- * * Convert between internal blocks and user pointers. * @@ -733,91 +745,84 @@ MoveObjs( */ static char * -Block2Ptr( - Block *blockPtr, - int bucket, - unsigned int reqSize) +Block2Ptr(Block *blockPtr, int bucket, unsigned int reqsize) { register void *ptr; - blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; - blockPtr->sourceBucket = bucket; - blockPtr->blockReqSize = reqSize; + blockPtr->b_magic1 = blockPtr->b_magic2 = MAGIC; + blockPtr->b_bucket = bucket; + blockPtr->b_reqsize = reqsize; ptr = ((void *) (blockPtr + 1)); #if RCHECK - ((unsigned char *)(ptr))[reqSize] = MAGIC; + ((unsigned char *)(ptr))[reqsize] = MAGIC; #endif return (char *) ptr; } static Block * -Ptr2Block( - char *ptr) +Ptr2Block(char *ptr) { register Block *blockPtr; blockPtr = (((Block *) ptr) - 1); - if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { - Tcl_Panic("alloc: invalid block: %p: %x %x", - blockPtr, blockPtr->magicNum1, blockPtr->magicNum2); - } + if (blockPtr->b_magic1 != MAGIC #if RCHECK - if (((unsigned char *) ptr)[blockPtr->blockReqSize] != MAGIC) { - Tcl_Panic("alloc: invalid block: %p: %x %x %x", - blockPtr, blockPtr->magicNum1, blockPtr->magicNum2, - ((unsigned char *) ptr)[blockPtr->blockReqSize]); - } + || ((unsigned char *) ptr)[blockPtr->b_reqsize] != MAGIC #endif + || blockPtr->b_magic2 != MAGIC) { + panic("alloc: invalid block: %p: %x %x %x\n", + blockPtr, blockPtr->b_magic1, blockPtr->b_magic2, + ((unsigned char *) ptr)[blockPtr->b_reqsize]); + } return blockPtr; } + /* *---------------------------------------------------------------------- * - * LockBucket, UnlockBucket -- + * LockBucket, UnlockBucket -- * * Set/unset the lock to access a bucket in the shared cache. * * Results: - * None. + * None. * * Side effects: - * Lock activity and contention are monitored globally and on a per-cache - * basis. + * Lock activity and contention are monitored globally and on + * a per-cache basis. * *---------------------------------------------------------------------- */ static void -LockBucket( - Cache *cachePtr, - int bucket) +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; + if (Tcl_MutexTryLock(binfo[bucket].lockPtr) != TCL_OK) { + Tcl_MutexLock(binfo[bucket].lockPtr); + ++cachePtr->buckets[bucket].nwait; + ++sharedPtr->buckets[bucket].nwait; } #else - Tcl_MutexLock(bucketInfo[bucket].lockPtr); + Tcl_MutexLock(binfo[bucket].lockPtr); #endif - ++cachePtr->buckets[bucket].numLocks; - ++sharedPtr->buckets[bucket].numLocks; + ++cachePtr->buckets[bucket].nlock; + ++sharedPtr->buckets[bucket].nlock; } + static void -UnlockBucket( - Cache *cachePtr, - int bucket) +UnlockBucket(Cache *cachePtr, int bucket) { - Tcl_MutexUnlock(bucketInfo[bucket].lockPtr); + Tcl_MutexUnlock(binfo[bucket].lockPtr); } + /* *---------------------------------------------------------------------- * - * PutBlocks -- + * PutBlocks -- * * Return unused blocks to the shared cache. * @@ -831,42 +836,40 @@ UnlockBucket( */ static void -PutBlocks( - Cache *cachePtr, - int bucket, - int numMove) +PutBlocks(Cache *cachePtr, int bucket, int nmove) { register Block *lastPtr, *firstPtr; - register int n = numMove; + register int n = nmove; /* - * Before acquiring the lock, walk the block list to find the last block - * to be moved. + * Before acquiring the lock, walk the block list to find + * the last block to be moved. */ firstPtr = lastPtr = cachePtr->buckets[bucket].firstPtr; while (--n > 0) { - lastPtr = lastPtr->nextBlock; + lastPtr = lastPtr->b_next; } - cachePtr->buckets[bucket].firstPtr = lastPtr->nextBlock; - cachePtr->buckets[bucket].numFree -= numMove; + cachePtr->buckets[bucket].firstPtr = lastPtr->b_next; + cachePtr->buckets[bucket].nfree -= nmove; /* - * Aquire the lock and place the list of blocks at the front of the shared - * cache bucket. + * Aquire the lock and place the list of blocks at the front + * of the shared cache bucket. */ LockBucket(cachePtr, bucket); - lastPtr->nextBlock = sharedPtr->buckets[bucket].firstPtr; + lastPtr->b_next = sharedPtr->buckets[bucket].firstPtr; sharedPtr->buckets[bucket].firstPtr = firstPtr; - sharedPtr->buckets[bucket].numFree += numMove; + sharedPtr->buckets[bucket].nfree += nmove; UnlockBucket(cachePtr, bucket); } + /* *---------------------------------------------------------------------- * - * GetBlocks -- + * GetBlocks -- * * Get more blocks for a bucket. * @@ -880,69 +883,67 @@ PutBlocks( */ static int -GetBlocks( - Cache *cachePtr, - int bucket) +GetBlocks(Cache *cachePtr, int bucket) { register Block *blockPtr; register int n; + register size_t size; /* - * 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. + * First, atttempt to move blocks from the shared cache. Note + * the potentially dirty read of nfree before acquiring the lock + * which is a slight performance enhancement. The value is + * verified after the lock is actually acquired. */ - - if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].numFree > 0) { + + if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].nfree > 0) { LockBucket(cachePtr, bucket); - if (sharedPtr->buckets[bucket].numFree > 0) { + if (sharedPtr->buckets[bucket].nfree > 0) { /* - * Either move the entire list or walk the list to find the last - * block to move. + * Either move the entire list or walk the list to find + * the last block to move. */ - n = bucketInfo[bucket].numMove; - if (n >= sharedPtr->buckets[bucket].numFree) { + n = binfo[bucket].nmove; + if (n >= sharedPtr->buckets[bucket].nfree) { cachePtr->buckets[bucket].firstPtr = - sharedPtr->buckets[bucket].firstPtr; - cachePtr->buckets[bucket].numFree = - sharedPtr->buckets[bucket].numFree; + sharedPtr->buckets[bucket].firstPtr; + cachePtr->buckets[bucket].nfree = + sharedPtr->buckets[bucket].nfree; sharedPtr->buckets[bucket].firstPtr = NULL; - sharedPtr->buckets[bucket].numFree = 0; + sharedPtr->buckets[bucket].nfree = 0; } else { blockPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; - sharedPtr->buckets[bucket].numFree -= n; - cachePtr->buckets[bucket].numFree = n; + sharedPtr->buckets[bucket].nfree -= n; + cachePtr->buckets[bucket].nfree = n; while (--n > 0) { - blockPtr = blockPtr->nextBlock; + blockPtr = blockPtr->b_next; } - sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock; - blockPtr->nextBlock = NULL; + sharedPtr->buckets[bucket].firstPtr = blockPtr->b_next; + blockPtr->b_next = NULL; } } UnlockBucket(cachePtr, bucket); } - - if (cachePtr->buckets[bucket].numFree == 0) { - register size_t size; + + if (cachePtr->buckets[bucket].nfree == 0) { /* - * If no blocks could be moved from shared, first look for a larger - * block in this cache to split up. + * If no blocks could be moved from shared, first look for a + * larger block in this cache to split up. */ - blockPtr = NULL; + blockPtr = NULL; n = NBUCKETS; size = 0; /* lint */ while (--n > bucket) { - if (cachePtr->buckets[n].numFree > 0) { - size = bucketInfo[n].blockSize; + if (cachePtr->buckets[n].nfree > 0) { + size = binfo[n].blocksize; blockPtr = cachePtr->buckets[n].firstPtr; - cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; - --cachePtr->buckets[n].numFree; + cachePtr->buckets[n].firstPtr = blockPtr->b_next; + --cachePtr->buckets[n].nfree; break; } } @@ -963,26 +964,26 @@ GetBlocks( * Split the larger block into smaller blocks for this bucket. */ - n = size / bucketInfo[bucket].blockSize; - cachePtr->buckets[bucket].numFree = n; + n = size / binfo[bucket].blocksize; + cachePtr->buckets[bucket].nfree = n; cachePtr->buckets[bucket].firstPtr = blockPtr; while (--n > 0) { - blockPtr->nextBlock = (Block *) - ((char *) blockPtr + bucketInfo[bucket].blockSize); - blockPtr = blockPtr->nextBlock; + blockPtr->b_next = (Block *) + ((char *) blockPtr + binfo[bucket].blocksize); + blockPtr = blockPtr->b_next; } - blockPtr->nextBlock = NULL; + blockPtr->b_next = NULL; } return 1; } - + /* *---------------------------------------------------------------------- * * TclFinalizeThreadAlloc -- * - * This procedure is used to destroy all private resources used in this - * file. + * This procedure is used to destroy all private resources used in + * this file. * * Results: * None. @@ -994,13 +995,13 @@ GetBlocks( */ void -TclFinalizeThreadAlloc(void) +TclFinalizeThreadAlloc() { unsigned int i; for (i = 0; i < NBUCKETS; ++i) { - TclpFreeAllocMutex(bucketInfo[i].lockPtr); - bucketInfo[i].lockPtr = NULL; + TclpFreeAllocMutex(binfo[i].lockPtr); + binfo[i].lockPtr = NULL; } TclpFreeAllocMutex(objLockPtr); @@ -1012,37 +1013,15 @@ TclFinalizeThreadAlloc(void) TclpFreeAllocCache(NULL); } -#else /* !(TCL_THREADS && USE_THREAD_ALLOC) */ -/* - *---------------------------------------------------------------------- - * - * Tcl_GetMemoryInfo -- - * - * Return a list-of-lists of memory stats. - * - * Results: - * None. - * - * Side effects: - * List appended to given dstring. - * - *---------------------------------------------------------------------- - */ +#else /* ! defined(TCL_THREADS) && ! defined(USE_THREAD_ALLOC) */ -void -Tcl_GetMemoryInfo( - Tcl_DString *dsPtr) -{ - Tcl_Panic("Tcl_GetMemoryInfo called when threaded memory allocator not in use"); -} - /* *---------------------------------------------------------------------- * * TclFinalizeThreadAlloc -- * - * This procedure is used to destroy all private resources used in this - * file. + * This procedure is used to destroy all private resources used in + * this file. * * Results: * None. @@ -1054,16 +1033,9 @@ Tcl_GetMemoryInfo( */ void -TclFinalizeThreadAlloc(void) +TclFinalizeThreadAlloc() { - Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use"); + Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use."); } -#endif /* TCL_THREADS && USE_THREAD_ALLOC */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 4 - * fill-column: 78 - * End: - */ + +#endif /* TCL_THREADS */ |
