diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | generic/tclAlloc.c | 34 | ||||
-rwxr-xr-x | generic/tclThreadAlloc.c | 81 |
3 files changed, 71 insertions, 50 deletions
@@ -1,3 +1,9 @@ +2007-06-29 Daniel Steffen <das@users.sourceforge.net> + + * 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). + 2007-06-27 Don Porter <dgp@users.sourceforge.net> * generic/tclCmdMZ.c: Corrected broken trace reversal logic in diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index e51ba8e..f3dfb35 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.16.2.1 2004/10/28 21:12:37 andreas_kupries Exp $ + * RCS: @(#) $Id: tclAlloc.c,v 1.16.2.2 2007/06/29 03:17:33 das Exp $ */ /* @@ -45,6 +45,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 @@ -56,8 +66,8 @@ typedef unsigned long caddr_t; */ union overhead { - union overhead *ov_next; /* when free */ - unsigned char ov_padding[8]; /* Ensure the structure is 8-byte aligned. */ + union overhead *ov_next; /* when free */ + unsigned char ov_padding[ALLOCALIGN];/* align struct to ALLOCALIGN bytes */ struct { unsigned char ovu_magic0; /* magic number */ unsigned char ovu_index; /* bucket # */ @@ -90,11 +100,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 + * 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]; @@ -208,7 +219,7 @@ TclInitAlloc() void TclFinalizeAllocSubsystem() { - int i; + unsigned int i; struct block *blockPtr, *nextPtr; Tcl_MutexLock(allocMutexPtr); @@ -310,13 +321,10 @@ TclpAlloc(nbytes) * 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 + + amount = MINBLOCK; /* size of first bucket */ + bucket = MINBLOCK >> 4; + while (nbytes + OVERHEAD > amt) { amt <<= 1; if (amt == 0) { diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 69f0e9f..9ff31db 100755 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -11,7 +11,7 @@ * 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.4.2.7 2005/12/20 22:16:34 dkf Exp $ + * RCS: @(#) $Id: tclThreadAlloc.c,v 1.4.2.8 2007/06/29 03:17:33 das Exp $ */ #include "tclInt.h" @@ -50,12 +50,14 @@ extern void TclpSetAllocCache(void *); #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 @@ -65,23 +67,36 @@ extern void TclpSetAllocCache(void *); * the Block overhead) 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. */ - } b_s; - } b_u; - size_t b_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 b_next b_u.next -#define b_bucket b_u.b_s.bucket -#define b_magic1 b_u.b_s.magic1 -#define b_magic2 b_u.b_s.magic2 +#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 + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1)) +#define NBUCKETS (11 - (MINALLOC >> 5)) +#define MAXALLOC (MINALLOC << (NBUCKETS - 1)) /* * The following structure defines a bucket of blocks with @@ -122,19 +137,7 @@ struct binfo { int maxblocks; /* Max blocks before move to share. */ int nmove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ -} binfo[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}, -}; +} binfo[NBUCKETS]; /* * Static functions defined in this file. @@ -187,7 +190,7 @@ GetCache(void) if (listLockPtr == NULL) { Tcl_Mutex *initLockPtr; - int i; + unsigned int i; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); @@ -195,6 +198,9 @@ GetCache(void) listLockPtr = TclpNewAllocMutex(); objLockPtr = TclpNewAllocMutex(); for (i = 0; i < NBUCKETS; ++i) { + 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(); } } @@ -243,7 +249,7 @@ TclFreeAllocCache(void *arg) { Cache *cachePtr = arg; Cache **nextPtrPtr; - register int bucket; + register unsigned int bucket; /* * Flush blocks. @@ -624,7 +630,7 @@ Tcl_GetMemoryInfo(Tcl_DString *dsPtr) { Cache *cachePtr; char buf[200]; - int n; + unsigned int n; Tcl_MutexLock(listLockPtr); cachePtr = firstCachePtr; @@ -969,7 +975,8 @@ GetBlocks(Cache *cachePtr, int bucket) void TclFinalizeThreadAlloc() { - int i; + unsigned int i; + for (i = 0; i < NBUCKETS; ++i) { TclpFreeAllocMutex(binfo[i].lockPtr); binfo[i].lockPtr = NULL; |