diff options
Diffstat (limited to 'generic/tclAlloc.c')
| -rw-r--r-- | generic/tclAlloc.c | 540 | 
1 files changed, 284 insertions, 256 deletions
| diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index e51ba8e..ae61e85 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -1,10 +1,10 @@ -/*  +/*   * tclAlloc.c --   * - *	This is a very fast storage allocator.  It allocates blocks of a - *	small number of different sizes, and keeps free lists of each size. - *	Blocks that don't exactly fit are passed up to the next larger size. - *	Blocks over a certain size are directly allocated from the system. + *	This is a very fast storage allocator. It allocates blocks of a small + *	number of different sizes, and keeps free lists of each size. Blocks + *	that don't exactly fit are passed up to the next larger size. Blocks + *	over a certain size are directly allocated from the system.   *   * Copyright (c) 1983 Regents of the University of California.   * Copyright (c) 1996-1997 Sun Microsystems, Inc. @@ -12,10 +12,8 @@   *   * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.   * - * 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.16.2.1 2004/10/28 21:12:37 andreas_kupries Exp $ + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES.   */  /* @@ -23,65 +21,58 @@   * that has significantly reduced lock contention.   */ -#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC) || defined(TCL_MEM_DEBUG) -  #include "tclInt.h" -#include "tclPort.h" +#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC)  #if USE_TCLALLOC -#ifdef TCL_DEBUG -#   define DEBUG -/* #define MSTATS */ -#   define RCHECK -#endif -  /* - * We should really make use of AC_CHECK_TYPE(caddr_t) - * here, but it can wait until Tcl uses config.h properly. + * We should really make use of AC_CHECK_TYPE(caddr_t) here, but it can wait + * until Tcl uses config.h properly.   */ -#if defined(MAC_TCL) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) + +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)  typedef unsigned long caddr_t;  #endif  /* - * 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 - * 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 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 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.   */  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[TCL_ALLOCALIGN];	/* align struct to TCL_ALLOCALIGN bytes */      struct { -	unsigned char	ovu_magic0;	/* magic number */ -	unsigned char	ovu_index;	/* bucket # */ -	unsigned char	ovu_unused;	/* unused */ -	unsigned char	ovu_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 char magic0;		/* magic number */ +	unsigned char index;		/* bucket # */ +	unsigned char unused;		/* unused */ +	unsigned char magic1;		/* other magic number */ +#ifndef NDEBUG +	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 +#define overMagic0	ovu.magic0 +#define overMagic1	ovu.magic1 +#define bucketIndex	ovu.index +#define rangeCheckMagic	ovu.rmagic +#define realBlockSize	ovu.size  }; -#define MAGIC		0xef		/* magic # on accounting info */ -#define RMAGIC		0x5555		/* magic # on range info */ +#define MAGIC		0xef	/* magic # on accounting info */ +#define RMAGIC		0x5555	/* magic # on range info */ -#ifdef RCHECK -#define	RSLOP		sizeof (unsigned short) +#ifndef NDEBUG +#define	RSLOP		sizeof(unsigned short)  #else  #define	RSLOP		0  #endif @@ -89,37 +80,45 @@ union overhead {  #define OVERHEAD (sizeof(union overhead) + RSLOP)  /* - * 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 + * 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 MINBLOCK bytes. The overhead information   * precedes the data area returned to the user.   */ -#define NBUCKETS	13 +#define MINBLOCK	((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) +#define NBUCKETS	(13 - (MINBLOCK >> 4))  #define MAXMALLOC	(1<<(NBUCKETS+2)) -static	union overhead *nextf[NBUCKETS]; +static union overhead *nextf[NBUCKETS]; -/*  - * The following structure is used to keep track of all system memory  - * currently owned by Tcl.  When finalizing, all this memory will - * be returned to the system. +/* + * The following structure is used to keep track of all system memory + * currently owned by Tcl. When finalizing, all this memory will be returned + * to the system.   */  struct block {      struct block *nextPtr;	/* Linked list. */ -    struct block *prevPtr;	/* Linked list for big blocks, ensures 8-byte  +    struct block *prevPtr;	/* Linked list for big blocks, ensures 8-byte  				 * alignment for suballocated blocks. */  }; -static struct block *blockList;		/* Tracks the suballocated blocks. */ -static struct block bigBlocks = {	/* Big blocks aren't suballocated. */ +static struct block *blockList;	/* Tracks the suballocated blocks. */ +static struct block bigBlocks={	/* Big blocks aren't suballocated. */      &bigBlocks, &bigBlocks  };  /* - * The allocator is protected by a special mutex that must be - * explicitly initialized.  Futhermore, because Tcl_Alloc may be - * used before anything else in Tcl, we make this module self-initializing - * after all with the allocInit variable. + * The allocator is protected by a special mutex that must be explicitly + * initialized. Futhermore, because Tcl_Alloc may be used before anything else + * in Tcl, we make this module self-initializing after all with the allocInit + * variable.   */  #ifdef TCL_THREADS @@ -127,21 +126,19 @@ static Tcl_Mutex *allocMutexPtr;  #endif  static int allocInit = 0; -  #ifdef MSTATS  /* - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. + * numMallocs[i] is the difference between the number of mallocs and frees for + * a given block size.   */ -static	unsigned int nmalloc[NBUCKETS+1]; -#include <stdio.h> +static	unsigned int numMallocs[NBUCKETS+1];  #endif -#if defined(DEBUG) || defined(RCHECK) -#define	ASSERT(p)   if (!(p)) panic(# p) -#define RANGE_ASSERT(p) if (!(p)) panic(# p) +#if !defined(NDEBUG) +#define	ASSERT(p)	if (!(p)) Tcl_Panic(# p) +#define RANGE_ASSERT(p) if (!(p)) Tcl_Panic(# p)  #else  #define	ASSERT(p)  #define RANGE_ASSERT(p) @@ -151,8 +148,7 @@ static	unsigned int nmalloc[NBUCKETS+1];   * Prototypes for functions used only in this file.   */ -static void 		MoreCore _ANSI_ARGS_((int bucket)); - +static void		MoreCore(int bucket);  /*   *------------------------------------------------------------------------- @@ -171,7 +167,7 @@ static void 		MoreCore _ANSI_ARGS_((int bucket));   */  void -TclInitAlloc() +TclInitAlloc(void)  {      if (!allocInit) {  	allocInit = 1; @@ -186,29 +182,28 @@ TclInitAlloc()   *   * TclFinalizeAllocSubsystem --   * - *	Release all resources being used by this subsystem, including  - *	aggressively freeing all memory allocated by TclpAlloc() that  - *	has not yet been released with TclpFree(). - *	 - *	After this function is called, all memory allocated with  - *	TclpAlloc() should be considered unusable. + *	Release all resources being used by this subsystem, including + *	aggressively freeing all memory allocated by TclpAlloc() that has not + *	yet been released with TclpFree(). + * + *	After this function is called, all memory allocated with TclpAlloc() + *	should be considered unusable.   *   * Results:   *	None.   *   * Side effects: - *	This subsystem is self-initializing, since memory can be  - *	allocated before Tcl is formally initialized.  After this call, - *	this subsystem has been reset to its initial state and is  - *	usable again. + *	This subsystem is self-initializing, since memory can be allocated + *	before Tcl is formally initialized. After this call, this subsystem + *	has been reset to its initial state and is usable again.   *   *-------------------------------------------------------------------------   */  void -TclFinalizeAllocSubsystem() +TclFinalizeAllocSubsystem(void)  { -    int i; +    unsigned int i;      struct block *blockPtr, *nextPtr;      Tcl_MutexLock(allocMutexPtr); @@ -226,14 +221,14 @@ TclFinalizeAllocSubsystem()      bigBlocks.nextPtr = &bigBlocks;      bigBlocks.prevPtr = &bigBlocks; -    for (i = 0; i < NBUCKETS; i++) { +    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);  } @@ -255,29 +250,33 @@ TclFinalizeAllocSubsystem()   */  char * -TclpAlloc(nbytes) -    unsigned int nbytes;	/* Number of bytes to allocate. */ +TclpAlloc( +    unsigned int numBytes)	/* Number of bytes to allocate. */  { -    register union overhead *op; +    register union overhead *overPtr;      register long bucket; -    register unsigned amt; -    struct block *bigBlockPtr; +    register unsigned amount; +    struct block *bigBlockPtr = NULL;      if (!allocInit) {  	/* -	 * We have to make the "self initializing" because Tcl_Alloc -	 * may be used before any other part of Tcl.  E.g., see -	 * main() for tclsh! +	 * We have to make the "self initializing" because Tcl_Alloc may be +	 * used before any other part of Tcl. E.g., see main() for tclsh!  	 */ +  	TclInitAlloc();      }      Tcl_MutexLock(allocMutexPtr); +      /* -     * First the simple case: we simple allocate big blocks directly +     * First the simple case: we simple allocate big blocks directly.       */ -    if (nbytes + OVERHEAD >= MAXMALLOC) { -	bigBlockPtr = (struct block *) TclpSysAlloc((unsigned)  -		(sizeof(struct block) + OVERHEAD + nbytes), 0); + +    if (numBytes >= MAXMALLOC - OVERHEAD) { +	if (numBytes <= UINT_MAX - OVERHEAD -sizeof(struct block)) { +	    bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) +		    (sizeof(struct block) + OVERHEAD + numBytes), 0); +	}  	if (bigBlockPtr == NULL) {  	    Tcl_MutexUnlock(allocMutexPtr);  	    return NULL; @@ -287,77 +286,83 @@ 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 + +#ifndef NDEBUG  	/* -	 * Record allocated size of block and -	 * bound space with magic numbers. +	 * 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 -     * stored in hash buckets which satisfies request. -     * Account for space used per block for accounting. +     * Convert amount of memory requested into closest block size stored in +     * hash buckets which satisfies request. Account for space used per block +     * for accounting.       */ -#ifndef RCHECK -    amt = 8;	/* size of first bucket */ -    bucket = 0; -#else -    amt = 16;	/* size of first bucket */ -    bucket = 1; -#endif -    while (nbytes + OVERHEAD > amt) { -	amt <<= 1; -	if (amt == 0) { + +    amount = MINBLOCK;		/* size of first bucket */ +    bucket = MINBLOCK >> 4; + +    while (numBytes + OVERHEAD > amount) { +	amount <<= 1; +	if (amount == 0) {  	    Tcl_MutexUnlock(allocMutexPtr); -	    return (NULL); +	    return NULL;  	}  	bucket++;      } -    ASSERT( bucket < NBUCKETS ); +    ASSERT(bucket < NBUCKETS);      /* -     * If nothing in hash bucket right now, -     * request more memory from the system. +     * 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); +	    return NULL;  	}      } +      /*       * 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 + +#ifndef NDEBUG      /* -     * Record allocated size of block and -     * bound space with magic numbers. +     * 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));  }  /* @@ -379,28 +384,29 @@ TclpAlloc(nbytes)   */  static void -MoreCore(bucket) -    int bucket;		/* What bucket to allocat to. */ +MoreCore( +    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. +     * 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); -    amt = MAXMALLOC; -    nblks = amt / sz; -    ASSERT(nblks*sz == amt); +    size = 1 << (bucket + 3); +    ASSERT(size > 0); -    blockPtr = (struct block *) TclpSysAlloc((unsigned)  -	    (sizeof(struct block) + amt), 1); +    amount = MAXMALLOC; +    numBlocks = amount / size; +    ASSERT(numBlocks*size == amount); + +    blockPtr = (struct block *) TclpSysAlloc((unsigned) +	    (sizeof(struct block) + amount), 1);      /* no more room! */      if (blockPtr == NULL) {  	return; @@ -408,18 +414,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. +     * 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 = NULL;  }  /* @@ -439,47 +445,51 @@ MoreCore(bucket)   */  void -TclpFree(cp) -    char *cp;		/* Pointer to memory to free. */ -{    +TclpFree( +    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); +  	Tcl_MutexUnlock(allocMutexPtr);  	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);  } @@ -500,34 +510,34 @@ TclpFree(cp)   */  char * -TclpRealloc(cp, nbytes) -    char *cp;			/* Pointer to alloced block. */ -    unsigned int nbytes;	/* New size of memory. */ -{    +TclpRealloc( +    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. @@ -535,11 +545,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); +	bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, +		sizeof(struct block) + OVERHEAD + numBytes);  	if (bigBlockPtr == NULL) {  	    Tcl_MutexUnlock(allocMutexPtr);  	    return NULL; @@ -547,63 +557,69 @@ TclpRealloc(cp, nbytes)  	if (prevPtr->nextPtr != bigBlockPtr) {  	    /* -	     * If the block has moved, splice the new block into the list where -	     * the old block used to be.  +	     * If the block has moved, splice the new block into the list +	     * where the old block used to be.  	     */  	    prevPtr->nextPtr = bigBlockPtr;  	    nextPtr->prevPtr = bigBlockPtr;  	} -	op = (union overhead *) (bigBlockPtr + 1); +	overPtr = (union overhead *) (bigBlockPtr + 1); +  #ifdef MSTATS -	nmalloc[NBUCKETS]++; +	numMallocs[NBUCKETS]++;  #endif -#ifdef RCHECK + +#ifndef NDEBUG  	/*  	 * 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(newPtr, 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; + +#ifndef NDEBUG +    overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); +    BLOCK_END(overPtr) = RMAGIC;  #endif +      Tcl_MutexUnlock(allocMutexPtr); -    return(cp); +    return(oldPtr);  }  /* @@ -611,9 +627,9 @@ TclpRealloc(cp, nbytes)   *   * mstats --   * - *	Prints two lines of numbers, one showing the length of the  - *	free list for each size category, the second showing the  - *	number of mallocs - frees for each size category. + *	Prints two lines of numbers, one showing the length of the free list + *	for each size category, the second showing the number of mallocs - + *	frees for each size category.   *   * Results:   *	None. @@ -626,35 +642,39 @@ TclpRealloc(cp, nbytes)  #ifdef MSTATS  void -mstats(s) -    char *s;	/* Where to write info. */ +mstats( +    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); -    fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n",  -	    MAXMALLOC, nmalloc[NBUCKETS]); +	    totalUsed, totalFree); +    fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", +	    MAXMALLOC, numMallocs[NBUCKETS]); +      Tcl_MutexUnlock(allocMutexPtr);  }  #endif -#else  /* !USE_TCLALLOC */ +#else	/* !USE_TCLALLOC */  /*   *---------------------------------------------------------------------- @@ -673,10 +693,10 @@ mstats(s)   */  char * -TclpAlloc(nbytes) -    unsigned int nbytes;	/* Number of bytes to allocate. */ +TclpAlloc( +    unsigned int numBytes)	/* Number of bytes to allocate. */  { -    return (char*) malloc(nbytes); +    return (char *) malloc(numBytes);  }  /* @@ -696,10 +716,10 @@ TclpAlloc(nbytes)   */  void -TclpFree(cp) -    char *cp;		/* Pointer to memory to free. */ -{    -    free(cp); +TclpFree( +    char *oldPtr)		/* Pointer to memory to free. */ +{ +    free(oldPtr);      return;  } @@ -720,12 +740,20 @@ TclpFree(cp)   */  char * -TclpRealloc(cp, nbytes) -    char *cp;			/* Pointer to alloced block. */ -    unsigned int nbytes;	/* New size of memory. */ -{    -    return (char*) realloc(cp, nbytes); +TclpRealloc( +    char *oldPtr,		/* Pointer to alloced block. */ +    unsigned int numBytes)	/* New size of memory. */ +{ +    return (char *) realloc(oldPtr, numBytes);  }  #endif /* !USE_TCLALLOC */  #endif /* !TCL_THREADS */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ | 
