79 #define ALLOC_MINBITS 3
80 #define ALLOCSET_NUM_FREELISTS 11
81 #define ALLOC_CHUNK_LIMIT (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS))
83 #define ALLOC_CHUNK_FRACTION 4
100 #define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
101 #define ALLOC_CHUNKHDRSZ sizeof(struct AllocChunkData)
176 #ifdef MEMORY_CONTEXT_CHECKING
181 #define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T * 2 + SIZEOF_VOID_P)
183 #define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T + SIZEOF_VOID_P)
187 #if (ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF) != 0
202 #define ALLOCCHUNK_PRIVATE_LEN offsetof(AllocChunkData, aset)
208 #define AllocPointerIsValid(pointer) PointerIsValid(pointer)
214 #define AllocSetIsValid(set) PointerIsValid(set)
216 #define AllocPointerGetChunk(ptr) \
217 ((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))
218 #define AllocChunkGetPointer(chk) \
219 ((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))
244 #define MAX_FREE_CONTEXTS 100
276 bool print_to_stderr);
278 #ifdef MEMORY_CONTEXT_CHECKING
294 #ifdef MEMORY_CONTEXT_CHECKING
332 #ifdef HAVE__BUILTIN_CLZ
340 "ALLOC_CHUNK_LIMIT must be less than 64kB");
392 "sizeof(AllocChunkData) is not maxaligned");
395 "padding calculation in AllocChunkData is wrong");
404 initBlockSize >= 1024);
406 maxBlockSize >= initBlockSize &&
408 Assert(minContextSize == 0 ||
409 (minContextSize ==
MAXALIGN(minContextSize) &&
410 minContextSize >= 1024 &&
411 minContextSize <= maxBlockSize));
429 if (freeListIndex >= 0)
460 if (minContextSize != 0)
461 firstBlockSize =
Max(firstBlockSize, minContextSize);
463 firstBlockSize =
Max(firstBlockSize, initBlockSize);
475 (
errcode(ERRCODE_OUT_OF_MEMORY),
477 errdetail(
"Failed while creating memory context \"%s\".",
490 block->
endptr = ((
char *) set) + firstBlockSize;
527 "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
568 #ifdef MEMORY_CONTEXT_CHECKING
570 AllocSetCheck(context);
581 while (block != NULL)
590 #ifdef CLOBBER_FREED_MEMORY
591 wipe_mem(datastart, block->
freeptr - datastart);
605 #ifdef CLOBBER_FREED_MEMORY
606 wipe_mem(block, block->
freeptr - ((
char *) block));
636 #ifdef MEMORY_CONTEXT_CHECKING
638 AllocSetCheck(context);
684 while (block != NULL)
691 #ifdef CLOBBER_FREED_MEMORY
692 wipe_mem(block, block->
freeptr - ((
char *) block));
751 chunk->
size = chunk_size;
752 #ifdef MEMORY_CONTEXT_CHECKING
753 chunk->requested_size = size;
755 if (size < chunk_size)
758 #ifdef RANDOMIZE_ALLOCATED_MEMORY
806 chunk->
aset = (
void *) set;
808 #ifdef MEMORY_CONTEXT_CHECKING
809 chunk->requested_size = size;
811 if (size < chunk->size)
814 #ifdef RANDOMIZE_ALLOCATED_MEMORY
833 Assert(chunk_size >= size);
839 if ((block = set->
blocks) != NULL)
882 chunk->
size = availchunk;
883 #ifdef MEMORY_CONTEXT_CHECKING
884 chunk->requested_size = 0;
916 while (blksize < required_size)
926 while (block == NULL && blksize > 1024 * 1024)
929 if (blksize < required_size)
941 block->
endptr = ((
char *) block) + blksize;
965 chunk->
aset = (
void *) set;
966 chunk->
size = chunk_size;
967 #ifdef MEMORY_CONTEXT_CHECKING
968 chunk->requested_size = size;
970 if (size < chunk->size)
973 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1001 #ifdef MEMORY_CONTEXT_CHECKING
1003 if (chunk->requested_size < chunk->
size)
1004 if (!sentinel_ok(pointer, chunk->requested_size))
1005 elog(
WARNING,
"detected write past chunk end in %s %p",
1022 if (block->
aset != set ||
1024 block->
freeptr != ((
char *) block) +
1026 elog(
ERROR,
"could not find block containing chunk %p", chunk);
1038 #ifdef CLOBBER_FREED_MEMORY
1039 wipe_mem(block, block->
freeptr - ((
char *) block));
1050 #ifdef CLOBBER_FREED_MEMORY
1051 wipe_mem(pointer, chunk->
size);
1054 #ifdef MEMORY_CONTEXT_CHECKING
1056 chunk->requested_size = 0;
1084 oldsize = chunk->
size;
1086 #ifdef MEMORY_CONTEXT_CHECKING
1088 if (chunk->requested_size < oldsize)
1089 if (!sentinel_ok(pointer, chunk->requested_size))
1090 elog(
WARNING,
"detected write past chunk end in %s %p",
1111 if (block->
aset != set ||
1113 block->
freeptr != ((
char *) block) +
1115 elog(
ERROR,
"could not find block containing chunk %p", chunk);
1128 oldblksize = block->
endptr - ((
char *) block);
1142 block->
freeptr = block->
endptr = ((
char *) block) + blksize;
1153 chunk->size = chksize;
1155 #ifdef MEMORY_CONTEXT_CHECKING
1156 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1158 if (size > chunk->requested_size)
1159 randomize_mem((
char *) pointer + chunk->requested_size,
1160 size - chunk->requested_size);
1169 if (oldsize > chunk->requested_size)
1171 oldsize - chunk->requested_size);
1174 chunk->requested_size = size;
1177 if (size < chunk->size)
1178 set_sentinel(pointer, size);
1203 else if (oldsize >= size)
1205 #ifdef MEMORY_CONTEXT_CHECKING
1206 Size oldrequest = chunk->requested_size;
1208 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1210 if (size > oldrequest)
1211 randomize_mem((
char *) pointer + oldrequest,
1215 chunk->requested_size = size;
1221 if (size > oldrequest)
1230 set_sentinel(pointer, size);
1266 if (newPointer == NULL)
1282 #ifdef MEMORY_CONTEXT_CHECKING
1283 oldsize = chunk->requested_size;
1289 memcpy(newPointer, pointer, oldsize);
1349 Size freechunks = 0;
1358 for (block = set->
blocks; block != NULL; block = block->
next)
1361 totalspace += block->
endptr - ((
char *) block);
1368 for (chunk = set->
freelist[fidx]; chunk != NULL;
1378 char stats_string[200];
1380 snprintf(stats_string,
sizeof(stats_string),
1381 "%zu total in %zu blocks; %zu free (%zu chunks); %zu used",
1382 totalspace, nblocks, freespace, freechunks,
1383 totalspace - freespace);
1384 printfunc(context, passthru, stats_string, print_to_stderr);
1397 #ifdef MEMORY_CONTEXT_CHECKING
1414 Size total_allocated = 0;
1416 for (prevblock = NULL, block = set->
blocks;
1418 prevblock = block, block = block->
next)
1421 long blk_used = block->
freeptr - bpoz;
1425 if (set->
keeper == block)
1426 total_allocated += block->
endptr - ((
char *) set);
1428 total_allocated += block->
endptr - ((
char *) block);
1435 if (set->
keeper != block)
1436 elog(
WARNING,
"problem in alloc set %s: empty block %p",
1443 if (block->
aset != set ||
1444 block->
prev != prevblock ||
1447 elog(
WARNING,
"problem in alloc set %s: corrupt header in block %p",
1453 while (bpoz < block->freeptr)
1462 chsize = chunk->
size;
1463 dsize = chunk->requested_size;
1469 elog(
WARNING,
"problem in alloc set %s: req size > alloc size for chunk %p in block %p",
1470 name, chunk, block);
1472 elog(
WARNING,
"problem in alloc set %s: bad size %zu for chunk %p in block %p",
1473 name, chsize, chunk, block);
1478 elog(
WARNING,
"problem in alloc set %s: bad single-chunk %p in block %p",
1479 name, chunk, block);
1487 if (dsize > 0 && chunk->
aset != (
void *) set)
1488 elog(
WARNING,
"problem in alloc set %s: bogus aset link in block %p, chunk %p",
1489 name, block, chunk);
1494 if (chunk->
aset == (
void *) set && dsize < chsize &&
1496 elog(
WARNING,
"problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
1497 name, block, chunk);
1503 if (chunk->
aset == (
void *) set)
1513 elog(
WARNING,
"problem in alloc set %s: found inconsistent memory block %p",
Datum idx(PG_FUNCTION_ARGS)
struct AllocChunkData AllocChunkData
#define AllocSetIsValid(set)
static void AllocSetReset(MemoryContext context)
static bool AllocSetIsEmpty(MemoryContext context)
struct AllocBlockData * AllocBlock
#define MAX_FREE_CONTEXTS
static int AllocSetFreeIndex(Size size)
static const MemoryContextMethods AllocSetMethods
#define AllocPointerGetChunk(ptr)
static void AllocSetDelete(MemoryContext context)
static void * AllocSetRealloc(MemoryContext context, void *pointer, Size size)
#define ALLOCCHUNK_RAWSIZE
static void * AllocSetAlloc(MemoryContext context, Size size)
static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer)
struct AllocBlockData AllocBlockData
#define ALLOCSET_NUM_FREELISTS
struct AllocSetContext AllocSetContext
#define ALLOC_CHUNK_FRACTION
struct AllocChunkData * AllocChunk
struct AllocSetFreeList AllocSetFreeList
#define AllocChunkGetPointer(chk)
#define ALLOC_CHUNK_LIMIT
static void AllocSetStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
static AllocSetFreeList context_freelists[2]
#define ALLOCCHUNK_PRIVATE_LEN
static void AllocSetFree(MemoryContext context, void *pointer)
MemoryContext AllocSetContextCreateInternal(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
AllocSetContext * AllocSet
#define offsetof(type, field)
#define MemSetAligned(start, val, len)
#define StaticAssertStmt(condition, errmessage)
#define PG_USED_FOR_ASSERTS_ONLY
#define AssertArg(condition)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(fmt[strlen(fmt) - 1] !='\n')
MemoryContext TopMemoryContext
void MemoryContextStats(MemoryContext context)
void MemoryContextCreate(MemoryContext node, NodeTag tag, const MemoryContextMethods *methods, MemoryContext parent, const char *name)
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
struct MemoryContextData * MemoryContext
PGDLLIMPORT const uint8 pg_leftmost_one_pos[256]
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
AllocSetContext * first_free