diff options
author | das <das> | 2007-06-29 03:17:05 (GMT) |
---|---|---|
committer | das <das> | 2007-06-29 03:17:05 (GMT) |
commit | ae7210b56be78ad42c79081b2eafc7355436994f (patch) | |
tree | f802ee916ce4de9b28cef06781a387111b9f0df6 /generic | |
parent | 8493984d04745ef57714bf30c9dfd9da3f073dad (diff) | |
download | tcl-ae7210b56be78ad42c79081b2eafc7355436994f.zip tcl-ae7210b56be78ad42c79081b2eafc7355436994f.tar.gz tcl-ae7210b56be78ad42c79081b2eafc7355436994f.tar.bz2 |
* generic/tclAlloc.c: on Darwin, ensure memory allocated by
* generic/tclThreadAlloc.c: the custom TclpAlloc()s is aligned to
16 byte boundaries (as is the case with the Darwin system malloc).
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclAlloc.c | 48 | ||||
-rwxr-xr-x | generic/tclThreadAlloc.c | 102 |
2 files changed, 82 insertions, 68 deletions
diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index df6db05..d64ad38 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.24 2007/04/17 14:49:53 dkf Exp $ + * RCS: @(#) $Id: tclAlloc.c,v 1.25 2007/06/29 03:17:05 das Exp $ */ /* @@ -44,6 +44,16 @@ typedef unsigned long caddr_t; #endif /* + * Alignment for allocated memory. + */ + +#if defined(__APPLE__) +#define ALLOCALIGN 16 +#else +#define ALLOCALIGN 8 +#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 @@ -55,17 +65,17 @@ typedef unsigned long caddr_t; */ union overhead { - union overhead *next; /* when free */ - unsigned char padding[8]; /* Ensure the structure is 8-byte aligned. */ + union overhead *next; /* when free */ + unsigned char padding[ALLOCALIGN]; /* align struct to ALLOCALIGN bytes */ struct { - unsigned char magic0; /* magic number */ - unsigned char index; /* bucket # */ - unsigned char unused; /* unused */ - unsigned char 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 rmagic; /* range magic number */ - unsigned long size; /* actual block size */ - unsigned short 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 overMagic0 ovu.magic0 @@ -96,11 +106,12 @@ union overhead { /* * 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. + * 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) + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1)) +#define NBUCKETS (13 - (MINBLOCK >> 4)) #define MAXMALLOC (1<<(NBUCKETS+2)) static union overhead *nextf[NBUCKETS]; @@ -211,7 +222,7 @@ TclInitAlloc(void) void TclFinalizeAllocSubsystem(void) { - int i; + unsigned int i; struct block *blockPtr, *nextPtr; Tcl_MutexLock(allocMutexPtr); @@ -319,13 +330,8 @@ TclpAlloc( * for accounting. */ -#ifndef RCHECK - amount = 8; /* size of first bucket */ - bucket = 0; -#else - amount = 16; /* size of first bucket */ - bucket = 1; -#endif + amount = MINBLOCK; /* size of first bucket */ + bucket = MINBLOCK >> 4; while (numBytes + OVERHEAD > amount) { amount <<= 1; diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index c0bb338..2cde913 100755 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -11,12 +11,12 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclThreadAlloc.c,v 1.21 2006/08/10 12:15:31 dkf Exp $ + * RCS: @(#) $Id: tclThreadAlloc.c,v 1.22 2007/06/29 03:17:05 das Exp $ */ #include "tclInt.h" #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) - + /* * If range checking is enabled, an additional byte will be allocated to store * the magic number at the end of the requested memory. @@ -40,12 +40,14 @@ #define NOBJHIGH 1200 /* - * The following defines the number of buckets in the bucket cache and those - * block sizes from (1<<4) to (1<<(3+NBUCKETS)) + * Alignment for allocated memory. */ -#define NBUCKETS 11 -#define MAXALLOC 16284 +#if defined(__APPLE__) +#define ALLOCALIGN 16 +#else +#define ALLOCALIGN 8 +#endif /* * The following union stores accounting information for each block including @@ -54,23 +56,36 @@ * is also maintained. */ -typedef struct Block { - union { - struct Block *next; /* Next in free list. */ - struct { - unsigned char magic1; /* First magic number. */ - unsigned char bucket; /* Bucket block allocated from. */ - unsigned char unused; /* Padding. */ - unsigned char magic2; /* Second magic number. */ - } s; - } u; - size_t reqSize; /* Requested allocation size. */ +typedef union Block { + struct { + union { + union Block *next; /* Next in free list. */ + struct { + unsigned char magic1; /* First magic number. */ + unsigned char bucket; /* Bucket block allocated from. */ + unsigned char unused; /* Padding. */ + unsigned char magic2; /* Second magic number. */ + } s; + } u; + size_t reqSize; /* Requested allocation size. */ + } b; + unsigned char padding[ALLOCALIGN]; } Block; -#define nextBlock u.next -#define sourceBucket u.s.bucket -#define magicNum1 u.s.magic1 -#define magicNum2 u.s.magic2 +#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 + +/* + * The following defines the minimum and and maximum block sizes and the number + * of buckets in the bucket cache. + */ + +#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 @@ -114,19 +129,7 @@ static struct { int maxBlocks; /* Max blocks before move to share. */ int numMove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ -} bucketInfo[NBUCKETS] = { - { 16, 1024, 512, NULL}, - { 32, 512, 256, NULL}, - { 64, 256, 128, NULL}, - { 128, 128, 64, NULL}, - { 256, 64, 32, NULL}, - { 512, 32, 16, NULL}, - { 1024, 16, 8, NULL}, - { 2048, 8, 4, NULL}, - { 4096, 4, 2, NULL}, - { 8192, 2, 1, NULL}, - {16284, 1, 1, NULL}, -}; +} bucketInfo[NBUCKETS]; /* * Static functions defined in this file. @@ -178,7 +181,7 @@ GetCache(void) if (listLockPtr == NULL) { Tcl_Mutex *initLockPtr; - int i; + unsigned int i; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); @@ -186,6 +189,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(); } } @@ -234,7 +241,7 @@ TclFreeAllocCache( { Cache *cachePtr = arg; Cache **nextPtrPtr; - register int bucket; + register unsigned int bucket; /* * Flush blocks. @@ -379,12 +386,12 @@ TclpFree( blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == NBUCKETS) { - cachePtr->totalAssigned -= blockPtr->reqSize; + cachePtr->totalAssigned -= blockPtr->blockReqSize; free(blockPtr); return; } - cachePtr->buckets[bucket].totalAssigned -= blockPtr->reqSize; + cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; ++cachePtr->buckets[bucket].numFree; @@ -450,12 +457,12 @@ TclpRealloc( min = 0; } if (size > min && size <= bucketInfo[bucket].blockSize) { - cachePtr->buckets[bucket].totalAssigned -= blockPtr->reqSize; + cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; cachePtr->buckets[bucket].totalAssigned += reqSize; return Block2Ptr(blockPtr, bucket, reqSize); } } else if (size > MAXALLOC) { - cachePtr->totalAssigned -= blockPtr->reqSize; + cachePtr->totalAssigned -= blockPtr->blockReqSize; cachePtr->totalAssigned += reqSize; blockPtr = realloc(blockPtr, size); if (blockPtr == NULL) { @@ -470,8 +477,8 @@ TclpRealloc( new = TclpAlloc(reqSize); if (new != NULL) { - if (reqSize > blockPtr->reqSize) { - reqSize = blockPtr->reqSize; + if (reqSize > blockPtr->blockReqSize) { + reqSize = blockPtr->blockReqSize; } memcpy(new, ptr, reqSize); TclpFree(ptr); @@ -617,7 +624,7 @@ Tcl_GetMemoryInfo( { Cache *cachePtr; char buf[200]; - int n; + unsigned int n; Tcl_MutexLock(listLockPtr); cachePtr = firstCachePtr; @@ -719,7 +726,7 @@ Block2Ptr( blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; - blockPtr->reqSize = reqSize; + blockPtr->blockReqSize = reqSize; ptr = ((void *) (blockPtr + 1)); #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; @@ -739,10 +746,10 @@ Ptr2Block( blockPtr, blockPtr->magicNum1, blockPtr->magicNum2); } #if RCHECK - if (((unsigned char *) ptr)[blockPtr->reqSize] != MAGIC) { + 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->reqSize]); + ((unsigned char *) ptr)[blockPtr->blockReqSize]); } #endif return blockPtr; @@ -973,7 +980,8 @@ GetBlocks( void TclFinalizeThreadAlloc(void) { - int i; + unsigned int i; + for (i = 0; i < NBUCKETS; ++i) { TclpFreeAllocMutex(bucketInfo[i].lockPtr); bucketInfo[i].lockPtr = NULL; |