83#define ALLOC_MINBITS 3
84#define ALLOCSET_NUM_FREELISTS 11
85#define ALLOC_CHUNK_LIMIT (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS))
87#define ALLOC_CHUNK_FRACTION 4
92 "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
108#define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
109#define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
110#define FIRST_BLOCKHDRSZ (MAXALIGN(sizeof(AllocSetContext)) + \
138#define GetFreeListLink(chkptr) \
139 (AllocFreeListLink *) ((char *) (chkptr) + ALLOC_CHUNKHDRSZ)
142#define FreeListIdxIsValid(fidx) \
143 ((fidx) >= 0 && (fidx) < ALLOCSET_NUM_FREELISTS)
146#define GetChunkSizeFromFreeListIdx(fidx) \
147 ((((Size) 1) << ALLOC_MINBITS) << (fidx))
200#define AllocSetIsValid(set) \
201 ((set) && IsA(set, AllocSetContext))
207#define AllocBlockIsValid(block) \
208 ((block) && AllocSetIsValid((block)->aset))
215#define ExternalChunkGetBlock(chunk) \
216 (AllocBlock) ((char *) chunk - ALLOC_BLOCKHDRSZ)
241#define MAX_FREE_CONTEXTS 100
244#define KeeperBlock(set) \
245 ((AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext))))
248#define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set)))
300#ifdef HAVE_BITSCAN_REVERSE
308 "ALLOC_CHUNK_LIMIT must be less than 64kB");
360 "sizeof(MemoryChunk) is not maxaligned");
363 "sizeof(AllocFreeListLink) larger than minimum allocation size");
378 initBlockSize >= 1024);
380 maxBlockSize >= initBlockSize &&
404 if (freeListIndex >= 0)
452 errdetail(
"Failed while creating memory context \"%s\".",
554#ifdef MEMORY_CONTEXT_CHECKING
570 while (block !=
NULL)
579#ifdef CLOBBER_FREED_MEMORY
594#ifdef CLOBBER_FREED_MEMORY
640#ifdef MEMORY_CONTEXT_CHECKING
694 while (block !=
NULL)
701#ifdef CLOBBER_FREED_MEMORY
746#ifdef MEMORY_CONTEXT_CHECKING
771#ifdef MEMORY_CONTEXT_CHECKING
772 chunk->requested_size = size;
774 Assert(size < chunk_size);
777#ifdef RANDOMIZE_ALLOCATED_MEMORY
832#ifdef MEMORY_CONTEXT_CHECKING
833 chunk->requested_size = size;
835 if (size < chunk_size)
838#ifdef RANDOMIZE_ALLOCATED_MEMORY
915#ifdef MEMORY_CONTEXT_CHECKING
939 Assert(chunk_size >= size);
956 while (block ==
NULL && blksize > 1024 * 1024)
974 block->
endptr = ((
char *) block) + blksize;
1061#ifdef MEMORY_CONTEXT_CHECKING
1062 chunk->requested_size = size;
1067#ifdef RANDOMIZE_ALLOCATED_MEMORY
1086 Assert(chunk_size >= size);
1129#ifdef MEMORY_CONTEXT_CHECKING
1134 elog(
WARNING,
"detected write past chunk end in %s %p",
1149#ifdef CLOBBER_FREED_MEMORY
1177#ifdef MEMORY_CONTEXT_CHECKING
1181 elog(
WARNING,
"detected write past chunk end in %s %p",
1185#ifdef CLOBBER_FREED_MEMORY
1194#ifdef MEMORY_CONTEXT_CHECKING
1257#ifdef MEMORY_CONTEXT_CHECKING
1261 elog(
WARNING,
"detected write past chunk end in %s %p",
1265#ifdef MEMORY_CONTEXT_CHECKING
1295 block->
freeptr = block->
endptr = ((
char *) block) + blksize;
1303 set->blocks = block;
1307#ifdef MEMORY_CONTEXT_CHECKING
1308#ifdef RANDOMIZE_ALLOCATED_MEMORY
1314 if (size >
chunk->requested_size)
1316 size -
chunk->requested_size);
1334 chunk->requested_size = size;
1375#ifdef MEMORY_CONTEXT_CHECKING
1379 elog(
WARNING,
"detected write past chunk end in %s %p",
1390#ifdef MEMORY_CONTEXT_CHECKING
1393#ifdef RANDOMIZE_ALLOCATED_MEMORY
1400 chunk->requested_size = size;
1468#ifdef MEMORY_CONTEXT_CHECKING
1584 Size freechunks = 0;
1598 totalspace += block->
endptr - ((
char *) block);
1629 "%zu total in %zu blocks; %zu free (%zu chunks); %zu used",
1630 totalspace, nblocks, freespace, freechunks,
1631 totalspace - freespace);
1637 totals->nblocks += nblocks;
1638 totals->freechunks += freechunks;
1639 totals->totalspace += totalspace;
1640 totals->freespace += freespace;
1645#ifdef MEMORY_CONTEXT_CHECKING
1685 elog(
WARNING,
"problem in alloc set %s: empty block %p",
1692 if (block->
aset != set ||
1696 elog(
WARNING,
"problem in alloc set %s: corrupt header in block %p",
1718 elog(
WARNING,
"problem in alloc set %s: bad single-chunk %p in block %p",
1726 elog(
WARNING,
"problem in alloc set %s: bad chunk size for chunk %p in block %p",
1736 elog(
WARNING,
"problem in alloc set %s: bad block offset for chunk %p in block %p",
1739 dsize =
chunk->requested_size;
1743 elog(
WARNING,
"problem in alloc set %s: req size > alloc size for chunk %p in block %p",
1748 elog(
WARNING,
"problem in alloc set %s: bad size %zu for chunk %p in block %p",
1756 elog(
WARNING,
"problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
1770 elog(
WARNING,
"problem in alloc set %s: found inconsistent memory block %p",
1774 elog(
WARNING,
"problem in alloc set %s: external chunk on non-dedicated block %p",
Datum idx(PG_FUNCTION_ARGS)
void AllocSetReset(MemoryContext context)
static pg_noinline void * AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags, int fidx)
#define AllocSetIsValid(set)
#define AllocBlockIsValid(block)
void * AllocSetRealloc(void *pointer, Size size, int flags)
#define IsKeeperBlock(set, block)
#define GetFreeListLink(chkptr)
#define FreeListIdxIsValid(fidx)
Size AllocSetGetChunkSpace(void *pointer)
MemoryContext AllocSetGetChunkContext(void *pointer)
void AllocSetStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
#define GetChunkSizeFromFreeListIdx(fidx)
struct AllocBlockData * AllocBlock
#define MAX_FREE_CONTEXTS
static int AllocSetFreeIndex(Size size)
bool AllocSetIsEmpty(MemoryContext context)
void * AllocSetAlloc(MemoryContext context, Size size, int flags)
#define ALLOCSET_NUM_FREELISTS
#define ALLOC_CHUNK_FRACTION
void AllocSetFree(void *pointer)
void AllocSetDelete(MemoryContext context)
static void * AllocSetAllocChunkFromBlock(MemoryContext context, AllocBlock block, Size size, Size chunk_size, int fidx)
#define ALLOC_CHUNK_LIMIT
static AllocSetFreeList context_freelists[2]
static pg_noinline void * AllocSetAllocLarge(MemoryContext context, Size size, int flags)
#define ExternalChunkGetBlock(chunk)
MemoryContext AllocSetContextCreateInternal(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
AllocSetContext * AllocSet
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
#define MemSetAligned(start, val, len)
#define StaticAssertDecl(condition, errmessage)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
MemoryContext TopMemoryContext
void MemoryContextStats(MemoryContext context)
void * MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
void MemoryContextResetOnly(MemoryContext context)
#define VALGRIND_DESTROY_MEMPOOL(context)
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
#define VALGRIND_MEMPOOL_TRIM(context, addr, size)
#define VALGRIND_MEMPOOL_FREE(context, addr)
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
void(* MemoryStatsPrintFunc)(MemoryContext context, void *passthru, const char *stats_string, bool print_to_stderr)
#define ALLOCSET_SMALL_MINSIZE
#define ALLOCSET_DEFAULT_MINSIZE
#define AllocHugeSizeIsValid(size)
#define ALLOCSET_SEPARATE_THRESHOLD
#define ALLOCSET_SMALL_INITSIZE
#define ALLOCSET_DEFAULT_INITSIZE
static void MemoryContextCheckSize(MemoryContext context, Size size, int flags)
#define MEMORYCHUNK_MAX_BLOCKOFFSET
static Size MemoryChunkGetValue(MemoryChunk *chunk)
#define MemoryChunkGetPointer(c)
static bool MemoryChunkIsExternal(MemoryChunk *chunk)
static void * MemoryChunkGetBlock(MemoryChunk *chunk)
static void MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk, MemoryContextMethodID methodid)
#define PointerGetMemoryChunk(p)
static void MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block, Size value, MemoryContextMethodID methodid)
struct MemoryContextData * MemoryContext
static int pg_leftmost_one_pos32(uint32 word)
PGDLLIMPORT const uint8 pg_leftmost_one_pos[256]
MemoryChunk * freelist[ALLOCSET_NUM_FREELISTS]
AllocSetContext * first_free