* 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
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;
context->maxBlockSize = maxBlockSize;
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 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;
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
return pointer;
}
- if (oldsize > ALLOC_CHUNK_LIMIT)
+ if (oldsize > set->allocChunkLimit)
{
/*
* The chunk must have been allocated as a single-chunk block. Find
*/
AllocPointer newPointer;
- if (size <= ALLOC_CHUNK_LIMIT)
+ if (size <= set->allocChunkLimit)
{
AllocBlock block = set->blocks;
char *chunk_end;
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);