46 #define Generation_BLOCKHDRSZ MAXALIGN(sizeof(GenerationBlock))
47 #define Generation_CHUNKHDRSZ sizeof(MemoryChunk)
49 #define Generation_CHUNK_FRACTION 8
102 #define GenerationIsValid(set) \
103 (PointerIsValid(set) && IsA(set, GenerationContext))
109 #define GenerationBlockIsValid(block) \
110 (PointerIsValid(block) && GenerationIsValid((block)->context))
116 #define GenerationBlockIsEmpty(b) ((b)->nchunks == 0)
123 #define ExternalChunkGetBlock(chunk) \
124 (GenerationBlock *) ((char *) chunk - Generation_BLOCKHDRSZ)
127 #define KeeperBlock(set) \
128 ((GenerationBlock *) (((char *) set) + \
129 MAXALIGN(sizeof(GenerationContext))))
132 #define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set)))
173 "sizeof(MemoryChunk) is not maxaligned");
187 initBlockSize >= 1024);
189 maxBlockSize >= initBlockSize &&
191 Assert(minContextSize == 0 ||
192 (minContextSize ==
MAXALIGN(minContextSize) &&
193 minContextSize >= 1024 &&
194 minContextSize <= maxBlockSize));
200 if (minContextSize != 0)
201 allocSize =
Max(allocSize, minContextSize);
203 allocSize =
Max(allocSize, initBlockSize);
214 (
errcode(ERRCODE_OUT_OF_MEMORY),
216 errdetail(
"Failed while creating memory context \"%s\".",
290 #ifdef MEMORY_CONTEXT_CHECKING
355 #ifdef MEMORY_CONTEXT_CHECKING
368 context->mem_allocated += blksize;
384 #ifdef MEMORY_CONTEXT_CHECKING
390 #ifdef RANDOMIZE_ALLOCATED_MEMORY
432 #ifdef MEMORY_CONTEXT_CHECKING
438 #ifdef RANDOMIZE_ALLOCATED_MEMORY
482 if (blksize < required_size)
490 context->mem_allocated += blksize;
536 #ifdef MEMORY_CONTEXT_CHECKING
577 if (freeblock != NULL &&
582 set->
block = freeblock;
618 block->
endptr = ((
char *) block) + blksize;
632 #if defined(USE_VALGRIND) || defined(CLOBBER_FREED_MEMORY)
636 #ifdef CLOBBER_FREED_MEMORY
637 wipe_mem(datastart, block->
freeptr - datastart);
676 #ifdef CLOBBER_FREED_MEMORY
677 wipe_mem(block, block->
blksize);
694 #if (defined(MEMORY_CONTEXT_CHECKING) && defined(USE_ASSERT_CHECKING)) \
695 || defined(CLOBBER_FREED_MEMORY)
713 #if (defined(MEMORY_CONTEXT_CHECKING) && defined(USE_ASSERT_CHECKING)) \
714 || defined(CLOBBER_FREED_MEMORY)
715 chunksize = block->
endptr - (
char *) pointer;
729 #if (defined(MEMORY_CONTEXT_CHECKING) && defined(USE_ASSERT_CHECKING)) \
730 || defined(CLOBBER_FREED_MEMORY)
735 #ifdef MEMORY_CONTEXT_CHECKING
738 if (!sentinel_ok(pointer,
chunk->requested_size))
739 elog(
WARNING,
"detected write past chunk end in %s %p",
743 #ifdef CLOBBER_FREED_MEMORY
744 wipe_mem(pointer, chunksize);
747 #ifdef MEMORY_CONTEXT_CHECKING
822 oldsize = block->
endptr - (
char *) pointer;
840 #ifdef MEMORY_CONTEXT_CHECKING
843 if (!sentinel_ok(pointer,
chunk->requested_size))
844 elog(
WARNING,
"detected write past chunk end in %s %p",
858 #ifdef MEMORY_CONTEXT_CHECKING
865 #ifdef MEMORY_CONTEXT_CHECKING
868 #ifdef RANDOMIZE_ALLOCATED_MEMORY
870 if (
size > oldrequest)
871 randomize_mem((
char *) pointer + oldrequest,
881 if (
size > oldrequest)
889 set_sentinel(pointer,
size);
911 if (newPointer == NULL)
927 #ifdef MEMORY_CONTEXT_CHECKING
928 oldsize =
chunk->requested_size;
934 memcpy(newPointer, pointer, oldsize);
986 chunksize = block->
endptr - (
char *) pointer;
1040 Size nfreechunks = 0;
1056 nfreechunks += block->
nfree;
1063 char stats_string[200];
1065 snprintf(stats_string,
sizeof(stats_string),
1066 "%zu total in %zu blocks (%zu chunks); %zu free (%zu chunks); %zu used",
1067 totalspace, nblocks, nchunks, freespace,
1068 nfreechunks, totalspace - freespace);
1069 printfunc(
context, passthru, stats_string, print_to_stderr);
1082 #ifdef MEMORY_CONTEXT_CHECKING
1098 Size total_allocated = 0;
1107 bool has_external_chunk =
false;
1109 total_allocated += block->
blksize;
1116 elog(
WARNING,
"problem in Generation %s: number of free chunks %d in block %p exceeds %d allocated",
1121 elog(
WARNING,
"problem in Generation %s: bogus context link in block %p",
1129 while (ptr < block->freeptr)
1142 has_external_chunk =
true;
1156 if (chunkblock != block)
1157 elog(
WARNING,
"problem in Generation %s: bogus block link in block %p, chunk %p",
1165 if (chunksize < chunk->requested_size ||
1167 elog(
WARNING,
"problem in Generation %s: bogus chunk size in block %p, chunk %p",
1173 elog(
WARNING,
"problem in Generation %s: detected write past chunk end in block %p, chunk %p",
1188 if (nchunks != block->
nchunks)
1189 elog(
WARNING,
"problem in Generation %s: number of allocated chunks %d in block %p does not match header %d",
1192 if (nfree != block->
nfree)
1193 elog(
WARNING,
"problem in Generation %s: number of free chunks %d in block %p does not match header %d",
1196 if (has_external_chunk && nchunks > 1)
1197 elog(
WARNING,
"problem in Generation %s: external chunk on non-dedicated block %p",
#define Assert(condition)
#define StaticAssertDecl(condition, errmessage)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
static void GenerationBlockInit(GenerationContext *context, GenerationBlock *block, Size blksize)
#define IsKeeperBlock(set, block)
static pg_noinline void * GenerationAllocLarge(MemoryContext context, Size size, int flags)
#define Generation_CHUNK_FRACTION
void GenerationReset(MemoryContext context)
static Size GenerationBlockFreeBytes(GenerationBlock *block)
void * GenerationAlloc(MemoryContext context, Size size, int flags)
static void GenerationBlockFree(GenerationContext *set, GenerationBlock *block)
void GenerationFree(void *pointer)
MemoryContext GenerationGetChunkContext(void *pointer)
Size GenerationGetChunkSpace(void *pointer)
struct GenerationContext GenerationContext
#define Generation_CHUNKHDRSZ
static void GenerationBlockMarkEmpty(GenerationBlock *block)
#define GenerationBlockIsValid(block)
bool GenerationIsEmpty(MemoryContext context)
static pg_noinline void * GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags, Size chunk_size)
void GenerationStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
#define GenerationBlockIsEmpty(b)
static void * GenerationAllocChunkFromBlock(MemoryContext context, GenerationBlock *block, Size size, Size chunk_size)
void * GenerationRealloc(void *pointer, Size size, int flags)
#define Generation_BLOCKHDRSZ
MemoryContext GenerationContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
void GenerationDelete(MemoryContext context)
#define GenerationIsValid(set)
#define ExternalChunkGetBlock(chunk)
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
static bool dlist_has_next(const dlist_head *head, const dlist_node *node)
static void dlist_delete(dlist_node *node)
static void dlist_push_head(dlist_head *head, dlist_node *node)
#define dlist_foreach_modify(iter, lhead)
static bool dlist_is_empty(const dlist_head *head)
static dlist_node * dlist_head_node(dlist_head *head)
#define dlist_container(type, membername, ptr)
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)
#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 AllocHugeSizeIsValid(size)
static void MemoryContextCheckSize(MemoryContext context, Size size, int flags)
#define MEMORYCHUNK_MAX_BLOCKOFFSET
#define MEMORYCHUNK_MAX_VALUE
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
#define pg_nextpower2_size_t
static pg_noinline void Size size
GenerationContext * context
GenerationBlock * freeblock