summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--generic/tclAlloc.c34
-rwxr-xr-xgeneric/tclThreadAlloc.c81
3 files changed, 71 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index b75b531..1282067 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;