diff options
-rw-r--r-- | generic/tclAlloc.c | 294 |
1 files changed, 151 insertions, 143 deletions
diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index f51b039..8c1218d 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclAlloc.c,v 1.20 2004/05/04 20:09:33 dgp Exp $ + * RCS: @(#) $Id: tclAlloc.c,v 1.21 2004/10/06 12:44:52 dkf Exp $ */ /* @@ -44,34 +44,34 @@ typedef unsigned long caddr_t; /* * The overhead on a block is at least 8 bytes. When free, this space - * contains a pointer to the next free block, and the bottom two bits must - * be zero. When in use, the first byte is set to MAGIC, and the second + * contains a pointer to the next free block, and the bottom two bits must * be zero. When in use, the first byte is set to MAGIC, and the second * byte is the size index. The remaining bytes are for alignment. * If range checking is enabled then a second word holds the size of the * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). - * The order of elements is critical: ov_magic must overlay the low order - * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. + * The order of elements is critical: ov.magic must overlay the low order + * bits of ov.next, and ov.magic can not be a valid ov.next bit pattern. */ union overhead { - union overhead *ov_next; /* when free */ - unsigned char ov_padding[8]; /* Ensure the structure is 8-byte aligned. */ + union overhead *next; /* when free */ + unsigned char padding[8]; /* Ensure the structure is 8-byte + * aligned. */ struct { - unsigned char ovu_magic0; /* magic number */ - unsigned char ovu_index; /* bucket # */ - unsigned char ovu_unused; /* unused */ - unsigned char ovu_magic1; /* other magic number */ + unsigned char magic0; /* magic number */ + unsigned char index; /* bucket # */ + unsigned char unused; /* unused */ + unsigned char magic1; /* other magic number */ #ifdef RCHECK - unsigned short ovu_rmagic; /* range magic number */ - unsigned long ovu_size; /* actual block size */ - unsigned short ovu_unused2; /* padding to 8-byte align */ + unsigned short rmagic; /* range magic number */ + unsigned long size; /* actual block size */ + unsigned short unused2; /* padding to 8-byte align */ #endif - } ovu; -#define ov_magic0 ovu.ovu_magic0 -#define ov_magic1 ovu.ovu_magic1 -#define ov_index ovu.ovu_index -#define ov_rmagic ovu.ovu_rmagic -#define ov_size ovu.ovu_size + } ovu; +#define overMagic0 ovu.magic0 +#define overMagic1 ovu.magic1 +#define bucketIndex ovu.index +#define rangeCheckMagic ovu.rmagic +#define realBlockSize ovu.size }; @@ -87,6 +87,13 @@ union overhead { #define OVERHEAD (sizeof(union overhead) + RSLOP) /* + * Macro to make it easier to refer to the end-of-block guard magic. + */ + +#define BLOCK_END(overPtr) \ + (*(unsigned short *)((caddr_t)((overPtr) + 1) + (overPtr)->realBlockSize)) + +/* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is 8 bytes. The overhead information * precedes the data area returned to the user. @@ -129,11 +136,11 @@ static int allocInit = 0; #ifdef MSTATS /* - * nmalloc[i] is the difference between the number of mallocs and frees + * numMallocs[i] is the difference between the number of mallocs and frees * for a given block size. */ -static unsigned int nmalloc[NBUCKETS+1]; +static unsigned int numMallocs[NBUCKETS+1]; #include <stdio.h> #endif @@ -227,11 +234,11 @@ TclFinalizeAllocSubsystem() for (i = 0; i < NBUCKETS; i++) { nextf[i] = NULL; #ifdef MSTATS - nmalloc[i] = 0; + numMallocs[i] = 0; #endif } #ifdef MSTATS - nmalloc[i] = 0; + numMallocs[i] = 0; #endif Tcl_MutexUnlock(allocMutexPtr); } @@ -253,12 +260,12 @@ TclFinalizeAllocSubsystem() */ char * -TclpAlloc(nbytes) - unsigned int nbytes; /* Number of bytes to allocate. */ +TclpAlloc(numBytes) + unsigned int numBytes; /* Number of bytes to allocate. */ { - register union overhead *op; + register union overhead *overPtr; register long bucket; - register unsigned amt; + register unsigned amount; struct block *bigBlockPtr; if (!allocInit) { @@ -273,9 +280,9 @@ TclpAlloc(nbytes) /* * First the simple case: we simple allocate big blocks directly */ - if (nbytes + OVERHEAD >= MAXMALLOC) { + if (numBytes + OVERHEAD >= MAXMALLOC) { bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) - (sizeof(struct block) + OVERHEAD + nbytes), 0); + (sizeof(struct block) + OVERHEAD + numBytes), 0); if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; @@ -285,23 +292,23 @@ TclpAlloc(nbytes) bigBlockPtr->prevPtr = &bigBlocks; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr; - op = (union overhead *) (bigBlockPtr + 1); - op->ov_magic0 = op->ov_magic1 = MAGIC; - op->ov_index = 0xff; + overPtr = (union overhead *) (bigBlockPtr + 1); + overPtr->overMagic0 = overPtr->overMagic1 = MAGIC; + overPtr->bucketIndex = 0xff; #ifdef MSTATS - nmalloc[NBUCKETS]++; + numMallocs[NBUCKETS]++; #endif #ifdef RCHECK /* * Record allocated size of block and * bound space with magic numbers. */ - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - op->ov_rmagic = RMAGIC; - *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; + overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); + overPtr->rangeCheckMagic = RMAGIC; + BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); - return (void *)(op+1); + return (void *)(overPtr+1); } /* * Convert amount of memory requested into closest block size @@ -309,29 +316,29 @@ TclpAlloc(nbytes) * Account for space used per block for accounting. */ #ifndef RCHECK - amt = 8; /* size of first bucket */ + amount = 8; /* size of first bucket */ bucket = 0; #else - amt = 16; /* size of first bucket */ + amount = 16; /* size of first bucket */ bucket = 1; #endif - while (nbytes + OVERHEAD > amt) { - amt <<= 1; - if (amt == 0) { + while (numBytes + OVERHEAD > amount) { + amount <<= 1; + if (amount == 0) { Tcl_MutexUnlock(allocMutexPtr); return (NULL); } bucket++; } - ASSERT( bucket < NBUCKETS ); + ASSERT(bucket < NBUCKETS); /* * If nothing in hash bucket right now, * request more memory from the system. */ - if ((op = nextf[bucket]) == NULL) { + if ((overPtr = nextf[bucket]) == NULL) { MoreCore(bucket); - if ((op = nextf[bucket]) == NULL) { + if ((overPtr = nextf[bucket]) == NULL) { Tcl_MutexUnlock(allocMutexPtr); return (NULL); } @@ -339,23 +346,23 @@ TclpAlloc(nbytes) /* * Remove from linked list */ - nextf[bucket] = op->ov_next; - op->ov_magic0 = op->ov_magic1 = MAGIC; - op->ov_index = (unsigned char) bucket; + nextf[bucket] = overPtr->next; + overPtr->overMagic0 = overPtr->overMagic1 = MAGIC; + overPtr->bucketIndex = (unsigned char) bucket; #ifdef MSTATS - nmalloc[bucket]++; + numMallocs[bucket]++; #endif #ifdef RCHECK /* * Record allocated size of block and * bound space with magic numbers. */ - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - op->ov_rmagic = RMAGIC; - *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; + overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); + overPtr->rangeCheckMagic = RMAGIC; + BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); - return ((char *)(op + 1)); + return ((char *)(overPtr + 1)); } /* @@ -378,27 +385,27 @@ TclpAlloc(nbytes) static void MoreCore(bucket) - int bucket; /* What bucket to allocat to. */ + int bucket; /* What bucket to allocat to. */ { - register union overhead *op; - register long sz; /* size of desired block */ - long amt; /* amount to allocate */ - int nblks; /* how many blocks we get */ + register union overhead *overPtr; + register long size; /* size of desired block */ + long amount; /* amount to allocate */ + int numBlocks; /* how many blocks we get */ struct block *blockPtr; /* * sbrk_size <= 0 only for big, FLUFFY, requests (about * 2^30 bytes on a VAX, I think) or for a negative arg. */ - sz = 1 << (bucket + 3); - ASSERT(sz > 0); + size = 1 << (bucket + 3); + ASSERT(size > 0); - amt = MAXMALLOC; - nblks = amt / sz; - ASSERT(nblks*sz == amt); + amount = MAXMALLOC; + numBlocks = amount / size; + ASSERT(numBlocks*size == amount); blockPtr = (struct block *) TclpSysAlloc((unsigned) - (sizeof(struct block) + amt), 1); + (sizeof(struct block) + amount), 1); /* no more room! */ if (blockPtr == NULL) { return; @@ -406,18 +413,18 @@ MoreCore(bucket) blockPtr->nextPtr = blockList; blockList = blockPtr; - op = (union overhead *) (blockPtr + 1); + overPtr = (union overhead *) (blockPtr + 1); /* * Add new memory allocated to that on * free list for this hash bucket. */ - nextf[bucket] = op; - while (--nblks > 0) { - op->ov_next = (union overhead *)((caddr_t)op + sz); - op = (union overhead *)((caddr_t)op + sz); + nextf[bucket] = overPtr; + while (--numBlocks > 0) { + overPtr->next = (union overhead *)((caddr_t)overPtr + size); + overPtr = (union overhead *)((caddr_t)overPtr + size); } - op->ov_next = (union overhead *)NULL; + overPtr->next = (union overhead *)NULL; } /* @@ -437,35 +444,35 @@ MoreCore(bucket) */ void -TclpFree(cp) - char *cp; /* Pointer to memory to free. */ +TclpFree(oldPtr) + char *oldPtr; /* Pointer to memory to free. */ { register long size; - register union overhead *op; + register union overhead *overPtr; struct block *bigBlockPtr; - if (cp == NULL) { + if (oldPtr == NULL) { return; } Tcl_MutexLock(allocMutexPtr); - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); + overPtr = (union overhead *)((caddr_t)oldPtr - sizeof (union overhead)); - ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ - ASSERT(op->ov_magic1 == MAGIC); - if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { + 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(op->ov_rmagic == RMAGIC); - RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); - size = op->ov_index; - if ( size == 0xff ) { + RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC); + RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC); + size = overPtr->bucketIndex; + if (size == 0xff) { #ifdef MSTATS - nmalloc[NBUCKETS]--; + numMallocs[NBUCKETS]--; #endif - bigBlockPtr = (struct block *) op - 1; + bigBlockPtr = (struct block *) overPtr - 1; bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr; TclpSysFree(bigBlockPtr); @@ -473,10 +480,10 @@ TclpFree(cp) return; } ASSERT(size < NBUCKETS); - op->ov_next = nextf[size]; /* also clobbers ov_magic */ - nextf[size] = op; + overPtr->next = nextf[size]; /* also clobbers overMagic */ + nextf[size] = overPtr; #ifdef MSTATS - nmalloc[size]--; + numMallocs[size]--; #endif Tcl_MutexUnlock(allocMutexPtr); } @@ -498,34 +505,34 @@ TclpFree(cp) */ char * -TclpRealloc(cp, nbytes) - char *cp; /* Pointer to alloced block. */ - unsigned int nbytes; /* New size of memory. */ +TclpRealloc(oldPtr, numBytes) + char *oldPtr; /* Pointer to alloced block. */ + unsigned int numBytes; /* New size of memory. */ { int i; - union overhead *op; + union overhead *overPtr; struct block *bigBlockPtr; int expensive; - unsigned long maxsize; + unsigned long maxSize; - if (cp == NULL) { - return (TclpAlloc(nbytes)); + if (oldPtr == NULL) { + return (TclpAlloc(numBytes)); } Tcl_MutexLock(allocMutexPtr); - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); + overPtr = (union overhead *)((caddr_t)oldPtr - sizeof (union overhead)); - ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ - ASSERT(op->ov_magic1 == MAGIC); - if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { + 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 NULL; } - RANGE_ASSERT(op->ov_rmagic == RMAGIC); - RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); - i = op->ov_index; + RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC); + RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC); + i = overPtr->bucketIndex; /* * If the block isn't in a bin, just realloc it. @@ -533,11 +540,11 @@ TclpRealloc(cp, nbytes) if (i == 0xff) { struct block *prevPtr, *nextPtr; - bigBlockPtr = (struct block *) op - 1; + bigBlockPtr = (struct block *) overPtr - 1; prevPtr = bigBlockPtr->prevPtr; nextPtr = bigBlockPtr->nextPtr; bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, - sizeof(struct block) + OVERHEAD + nbytes); + sizeof(struct block) + OVERHEAD + numBytes); if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; @@ -553,55 +560,56 @@ TclpRealloc(cp, nbytes) nextPtr->prevPtr = bigBlockPtr; } - op = (union overhead *) (bigBlockPtr + 1); + overPtr = (union overhead *) (bigBlockPtr + 1); #ifdef MSTATS - nmalloc[NBUCKETS]++; + numMallocs[NBUCKETS]++; #endif #ifdef RCHECK /* * Record allocated size of block and update magic number bounds. */ - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; + overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); + BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); - return (char *)(op+1); + return (char *)(overPtr+1); } - maxsize = 1 << (i+3); + maxSize = 1 << (i+3); expensive = 0; - if ( nbytes + OVERHEAD > maxsize ) { + if (numBytes+OVERHEAD > maxSize) { expensive = 1; - } else if ( i > 0 && nbytes + OVERHEAD < (maxsize/2) ) { + } else if (i>0 && numBytes+OVERHEAD < maxSize/2) { expensive = 1; } if (expensive) { - void *newp; + void *newPtr; Tcl_MutexUnlock(allocMutexPtr); - newp = TclpAlloc(nbytes); - if ( newp == NULL ) { + newPtr = TclpAlloc(numBytes); + if (newPtr == NULL) { return NULL; } - maxsize -= OVERHEAD; - if ( maxsize < nbytes ) - nbytes = maxsize; - memcpy((VOID *) newp, (VOID *) cp, (size_t) nbytes); - TclpFree(cp); - return newp; + maxSize -= OVERHEAD; + if (maxSize < numBytes) { + numBytes = maxSize; + } + memcpy((VOID *) newPtr, (VOID *) oldPtr, (size_t) numBytes); + TclpFree(oldPtr); + return newPtr; } /* * Ok, we don't have to copy, it fits as-is */ #ifdef RCHECK - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; + overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); + BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); - return(cp); + return(oldPtr); } /* @@ -628,26 +636,26 @@ mstats(s) char *s; /* Where to write info. */ { register int i, j; - register union overhead *p; - int totfree = 0, - totused = 0; + register union overhead *overPtr; + int totalFree = 0, totalUsed = 0; Tcl_MutexLock(allocMutexPtr); fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s); for (i = 0; i < NBUCKETS; i++) { - for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) + for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) { fprintf(stderr, " %d", j); - totfree += j * (1 << (i + 3)); + } + totalFree += j * (1 << (i + 3)); } fprintf(stderr, "\nused:\t"); for (i = 0; i < NBUCKETS; i++) { - fprintf(stderr, " %d", nmalloc[i]); - totused += nmalloc[i] * (1 << (i + 3)); + fprintf(stderr, " %d", numMallocs[i]); + totalUsed += numMallocs[i] * (1 << (i + 3)); } fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n", - totused, totfree); + totalUsed, totalFree); fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", - MAXMALLOC, nmalloc[NBUCKETS]); + MAXMALLOC, numMallocs[NBUCKETS]); Tcl_MutexUnlock(allocMutexPtr); } #endif @@ -671,10 +679,10 @@ mstats(s) */ char * -TclpAlloc(nbytes) - unsigned int nbytes; /* Number of bytes to allocate. */ +TclpAlloc(numBytes) + unsigned int numBytes; /* Number of bytes to allocate. */ { - return (char*) malloc(nbytes); + return (char*) malloc(numBytes); } /* @@ -694,10 +702,10 @@ TclpAlloc(nbytes) */ void -TclpFree(cp) - char *cp; /* Pointer to memory to free. */ +TclpFree(oldPtr) + char *oldPtr; /* Pointer to memory to free. */ { - free(cp); + free(oldPtr); return; } @@ -718,11 +726,11 @@ TclpFree(cp) */ char * -TclpRealloc(cp, nbytes) - char *cp; /* Pointer to alloced block. */ - unsigned int nbytes; /* New size of memory. */ +TclpRealloc(oldPtr, numBytes) + char *oldPtr; /* Pointer to alloced block. */ + unsigned int numBytes; /* New size of memory. */ { - return (char*) realloc(cp, nbytes); + return (char*) realloc(oldPtr, numBytes); } #endif /* !USE_TCLALLOC */ |