aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/mmgr/aset.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 0135ba0e0b3..5e97ebe8969 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.69 2006/11/08 19:27:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.70 2006/12/27 22:30:48 tgl Exp $
*
* NOTE:
* This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -141,6 +141,7 @@ typedef struct AllocSetContext
Size initBlockSize; /* initial block size */
Size maxBlockSize; /* maximum block size */
Size nextBlockSize; /* next block size to allocate */
+ Size allocChunkLimit; /* effective chunk size limit */
AllocBlock keeper; /* if not NULL, keep this block over resets */
} AllocSetContext;
@@ -329,6 +330,20 @@ AllocSetContextCreate(MemoryContext parent,
context->nextBlockSize = initBlockSize;
/*
+ * Compute the allocation chunk size limit for this context. It can't
+ * be more than ALLOC_CHUNK_LIMIT because of the fixed number of
+ * freelists. If maxBlockSize is small then requests exceeding the
+ * maxBlockSize should be treated as large chunks, too. We have to
+ * have allocChunkLimit a power of two, because the requested and
+ * actually-allocated sizes of any chunk must be on the same side of
+ * the limit, else we get confused about whether the chunk is "big".
+ */
+ context->allocChunkLimit = ALLOC_CHUNK_LIMIT;
+ while (context->allocChunkLimit >
+ (Size) (maxBlockSize - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ))
+ context->allocChunkLimit >>= 1;
+
+ /*
* Grab always-allocated space, if requested
*/
if (minContextSize > ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ)
@@ -512,7 +527,7 @@ AllocSetAlloc(MemoryContext context, Size size)
* If requested size exceeds maximum for chunks, allocate an entire block
* for this request.
*/
- if (size > ALLOC_CHUNK_LIMIT)
+ if (size > set->allocChunkLimit)
{
chunk_size = MAXALIGN(size);
blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
@@ -775,7 +790,7 @@ AllocSetFree(MemoryContext context, void *pointer)
set->header.name, chunk);
#endif
- if (chunk->size > ALLOC_CHUNK_LIMIT)
+ if (chunk->size > set->allocChunkLimit)
{
/*
* Big chunks are certain to have been allocated as single-chunk
@@ -868,7 +883,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
return pointer;
}
- if (oldsize > ALLOC_CHUNK_LIMIT)
+ if (oldsize > set->allocChunkLimit)
{
/*
* The chunk must have been allocated as a single-chunk block. Find
@@ -943,7 +958,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
*/
AllocPointer newPointer;
- if (size <= ALLOC_CHUNK_LIMIT)
+ if (size <= set->allocChunkLimit)
{
AllocBlock block = set->blocks;
char *chunk_end;
@@ -1122,7 +1137,7 @@ AllocSetCheck(MemoryContext context)
name, (unsigned long) chsize, chunk, block);
/* single-chunk block? */
- if (chsize > ALLOC_CHUNK_LIMIT &&
+ if (chsize > set->allocChunkLimit &&
chsize + ALLOC_CHUNKHDRSZ != blk_used)
elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
name, chunk, block);