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
104 #define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
105 #define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
132 #define GetFreeListLink(chkptr) \
133 (AllocFreeListLink *) ((char *) (chkptr) + ALLOC_CHUNKHDRSZ)
136 #define FreeListIdxIsValid(fidx) \
137 ((fidx) >= 0 && (fidx) < ALLOCSET_NUM_FREELISTS)
140 #define GetChunkSizeFromFreeListIdx(fidx) \
141 ((((Size) 1) << ALLOC_MINBITS) << (fidx))
195 #define AllocPointerIsValid(pointer) PointerIsValid(pointer)
201 #define AllocSetIsValid(set) \
202 (PointerIsValid(set) && IsA(set, AllocSetContext))
208 #define AllocBlockIsValid(block) \
209 (PointerIsValid(block) && AllocSetIsValid((block)->aset))
216 #define ExternalChunkGetBlock(chunk) \
217 (AllocBlock) ((char *) chunk - ALLOC_BLOCKHDRSZ)
242 #define MAX_FREE_CONTEXTS 100
294 #ifdef HAVE_BITSCAN_REVERSE
302 "ALLOC_CHUNK_LIMIT must be less than 64kB");
354 "sizeof(MemoryChunk) is not maxaligned");
357 "sizeof(AllocFreeListLink) larger than minimum allocation size");
372 initBlockSize >= 1024);
374 maxBlockSize >= initBlockSize &&
376 Assert(minContextSize == 0 ||
377 (minContextSize ==
MAXALIGN(minContextSize) &&
378 minContextSize >= 1024 &&
379 minContextSize <= maxBlockSize));
398 if (freeListIndex >= 0)
429 if (minContextSize != 0)
430 firstBlockSize =
Max(firstBlockSize, minContextSize);
432 firstBlockSize =
Max(firstBlockSize, initBlockSize);
444 (
errcode(ERRCODE_OUT_OF_MEMORY),
446 errdetail(
"Failed while creating memory context \"%s\".",
459 block->
endptr = ((
char *) set) + firstBlockSize;
492 "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
541 #ifdef MEMORY_CONTEXT_CHECKING
543 AllocSetCheck(context);
557 while (block != NULL)
566 #ifdef CLOBBER_FREED_MEMORY
567 wipe_mem(datastart, block->
freeptr - datastart);
581 #ifdef CLOBBER_FREED_MEMORY
582 wipe_mem(block, block->
freeptr - ((
char *) block));
611 #ifdef MEMORY_CONTEXT_CHECKING
613 AllocSetCheck(context);
662 while (block != NULL)
669 #ifdef CLOBBER_FREED_MEMORY
670 wipe_mem(block, block->
freeptr - ((
char *) block));
716 #ifdef MEMORY_CONTEXT_CHECKING
738 #ifdef MEMORY_CONTEXT_CHECKING
739 chunk->requested_size = size;
741 Assert(size < chunk_size);
744 #ifdef RANDOMIZE_ALLOCATED_MEMORY
806 #ifdef MEMORY_CONTEXT_CHECKING
807 chunk->requested_size = size;
812 #ifdef RANDOMIZE_ALLOCATED_MEMORY
831 Assert(chunk_size >= size);
837 if ((block = set->
blocks) != NULL)
882 #ifdef MEMORY_CONTEXT_CHECKING
920 while (blksize < required_size)
930 while (block == NULL && blksize > 1024 * 1024)
933 if (blksize < required_size)
945 block->
endptr = ((
char *) block) + blksize;
972 #ifdef MEMORY_CONTEXT_CHECKING
973 chunk->requested_size = size;
975 if (size < chunk_size)
978 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1016 elog(
ERROR,
"could not find block containing chunk %p", chunk);
1020 #ifdef MEMORY_CONTEXT_CHECKING
1023 Assert(chunk->requested_size < (block->
endptr - (
char *) pointer));
1024 if (!sentinel_ok(pointer, chunk->requested_size))
1025 elog(
WARNING,
"detected write past chunk end in %s %p",
1040 #ifdef CLOBBER_FREED_MEMORY
1041 wipe_mem(block, block->
freeptr - ((
char *) block));
1064 #ifdef MEMORY_CONTEXT_CHECKING
1067 if (!sentinel_ok(pointer, chunk->requested_size))
1068 elog(
WARNING,
"detected write past chunk end in %s %p",
1072 #ifdef CLOBBER_FREED_MEMORY
1081 #ifdef MEMORY_CONTEXT_CHECKING
1134 elog(
ERROR,
"could not find block containing chunk %p", chunk);
1138 oldchksize = block->
endptr - (
char *) pointer;
1140 #ifdef MEMORY_CONTEXT_CHECKING
1142 Assert(chunk->requested_size < oldchksize);
1143 if (!sentinel_ok(pointer, chunk->requested_size))
1144 elog(
WARNING,
"detected write past chunk end in %s %p",
1148 #ifdef MEMORY_CONTEXT_CHECKING
1157 oldblksize = block->
endptr - ((
char *) block);
1171 block->
freeptr = block->
endptr = ((
char *) block) + blksize;
1183 #ifdef MEMORY_CONTEXT_CHECKING
1184 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1190 if (size > chunk->requested_size)
1191 randomize_mem((
char *) pointer + chunk->requested_size,
1192 size - chunk->requested_size);
1204 if (
Min(size, oldchksize) > chunk->requested_size)
1206 Min(size, oldchksize) - chunk->requested_size);
1210 chunk->requested_size = size;
1213 set_sentinel(pointer, size);
1251 #ifdef MEMORY_CONTEXT_CHECKING
1253 if (chunk->requested_size < oldchksize)
1254 if (!sentinel_ok(pointer, chunk->requested_size))
1255 elog(
WARNING,
"detected write past chunk end in %s %p",
1264 if (oldchksize >= size)
1266 #ifdef MEMORY_CONTEXT_CHECKING
1267 Size oldrequest = chunk->requested_size;
1269 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1271 if (size > oldrequest)
1272 randomize_mem((
char *) pointer + oldrequest,
1276 chunk->requested_size = size;
1282 if (size > oldrequest)
1290 if (size < oldchksize)
1291 set_sentinel(pointer, size);
1328 if (newPointer == NULL)
1344 #ifdef MEMORY_CONTEXT_CHECKING
1345 oldsize = chunk->requested_size;
1347 oldsize = oldchksize;
1352 memcpy(newPointer, pointer, oldsize);
1412 return block->
endptr - (
char *) chunk;
1460 Size freechunks = 0;
1471 for (block = set->
blocks; block != NULL; block = block->
next)
1474 totalspace += block->
endptr - ((
char *) block);
1482 while (chunk != NULL)
1502 char stats_string[200];
1504 snprintf(stats_string,
sizeof(stats_string),
1505 "%zu total in %zu blocks; %zu free (%zu chunks); %zu used",
1506 totalspace, nblocks, freespace, freechunks,
1507 totalspace - freespace);
1508 printfunc(context, passthru, stats_string, print_to_stderr);
1521 #ifdef MEMORY_CONTEXT_CHECKING
1538 Size total_allocated = 0;
1540 for (prevblock = NULL, block = set->
blocks;
1542 prevblock = block, block = block->
next)
1545 long blk_used = block->
freeptr - bpoz;
1548 bool has_external_chunk =
false;
1550 if (set->
keeper == block)
1551 total_allocated += block->
endptr - ((
char *) set);
1553 total_allocated += block->
endptr - ((
char *) block);
1560 if (set->
keeper != block)
1561 elog(
WARNING,
"problem in alloc set %s: empty block %p",
1568 if (block->
aset != set ||
1569 block->
prev != prevblock ||
1572 elog(
WARNING,
"problem in alloc set %s: corrupt header in block %p",
1578 while (bpoz < block->freeptr)
1590 has_external_chunk =
true;
1594 elog(
WARNING,
"problem in alloc set %s: bad single-chunk %p in block %p",
1595 name, chunk, block);
1602 elog(
WARNING,
"problem in alloc set %s: bad chunk size for chunk %p in block %p",
1603 name, chunk, block);
1612 elog(
WARNING,
"problem in alloc set %s: bad block offset for chunk %p in block %p",
1613 name, chunk, block);
1615 dsize = chunk->requested_size;
1619 elog(
WARNING,
"problem in alloc set %s: req size > alloc size for chunk %p in block %p",
1620 name, chunk, block);
1624 elog(
WARNING,
"problem in alloc set %s: bad size %zu for chunk %p in block %p",
1625 name, chsize, chunk, block);
1632 elog(
WARNING,
"problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
1633 name, block, chunk);
1646 elog(
WARNING,
"problem in alloc set %s: found inconsistent memory block %p",
1649 if (has_external_chunk && nchunks > 1)
1650 elog(
WARNING,
"problem in alloc set %s: external chunk on non-dedicated block %p",
Datum idx(PG_FUNCTION_ARGS)
void AllocSetReset(MemoryContext context)
#define AllocSetIsValid(set)
#define AllocBlockIsValid(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)
struct AllocBlockData AllocBlockData
void * AllocSetRealloc(void *pointer, Size size)
#define ALLOCSET_NUM_FREELISTS
struct AllocSetContext AllocSetContext
#define ALLOC_CHUNK_FRACTION
void AllocSetFree(void *pointer)
void AllocSetDelete(MemoryContext context)
struct AllocSetFreeList AllocSetFreeList
#define ALLOC_CHUNK_LIMIT
struct AllocFreeListLink AllocFreeListLink
static AllocSetFreeList context_freelists[2]
#define ExternalChunkGetBlock(chunk)
void * AllocSetAlloc(MemoryContext context, Size size)
MemoryContext AllocSetContextCreateInternal(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
AllocSetContext * AllocSet
#define MemSetAligned(start, val, len)
#define StaticAssertDecl(condition, errmessage)
#define StaticAssertStmt(condition, errmessage)
#define PG_USED_FOR_ASSERTS_ONLY
elog(ERROR, "%s: %s", p2, msg)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(fmt[strlen(fmt) - 1] !='\n')
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
MemoryContext TopMemoryContext
void MemoryContextStats(MemoryContext context)
void MemoryContextResetOnly(MemoryContext context)
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#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
#define MEMORYCHUNK_MAX_BLOCKOFFSET
static Size MemoryChunkGetValue(MemoryChunk *chunk)
#define MemoryChunkGetPointer(c)
static bool MemoryChunkIsExternal(MemoryChunk *chunk)
static void MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk, MemoryContextMethodID methodid)
static void * MemoryChunkGetBlock(MemoryChunk *chunk)
#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
int link(const char *src, const char *dst)