77#define Slab_BLOCKHDRSZ MAXALIGN(sizeof(SlabBlock))
79#ifdef MEMORY_CONTEXT_CHECKING
85#define Slab_CONTEXT_HDRSZ(chunksPerBlock) \
86 (sizeof(SlabContext) + ((chunksPerBlock) * sizeof(bool)))
88#define Slab_CONTEXT_HDRSZ(chunksPerBlock) sizeof(SlabContext)
95#define SLAB_BLOCKLIST_COUNT 3
98#define SLAB_MAXIMUM_EMPTY_BLOCKS 10
113#ifdef MEMORY_CONTEXT_CHECKING
157#define Slab_CHUNKHDRSZ sizeof(MemoryChunk)
158#define SlabChunkGetPointer(chk) \
159 ((void *) (((char *) (chk)) + sizeof(MemoryChunk)))
165#define SlabBlockGetChunk(slab, block, n) \
166 ((MemoryChunk *) ((char *) (block) + Slab_BLOCKHDRSZ \
167 + ((n) * (slab)->fullChunkSize)))
169#if defined(MEMORY_CONTEXT_CHECKING) || defined(USE_ASSERT_CHECKING)
176#define SlabChunkIndex(slab, block, chunk) \
177 (((char *) (chunk) - (char *) SlabBlockGetChunk(slab, block, 0)) / \
178 (slab)->fullChunkSize)
186#define SlabChunkMod(slab, block, chunk) \
187 (((char *) (chunk) - (char *) SlabBlockGetChunk(slab, block, 0)) % \
188 (slab)->fullChunkSize)
196#define SlabIsValid(set) ((set) && IsA(set, SlabContext))
202#define SlabBlockIsValid(block) \
203 ((block) && SlabIsValid((block)->slab))
230 index = -((-nfree) >> blocklist_shift);
334 "sizeof(MemoryChunk) is not maxaligned");
345#ifdef MEMORY_CONTEXT_CHECKING
358 if (chunksPerBlock == 0)
359 elog(
ERROR,
"block size %zu for slab is too small for %zu-byte chunks",
360 blockSize, chunkSize);
371 errdetail(
"Failed while creating memory context \"%s\".",
413#ifdef MEMORY_CONTEXT_CHECKING
415 slab->isChunkFree = (
bool *) ((
char *) slab +
sizeof(
SlabContext));
444#ifdef MEMORY_CONTEXT_CHECKING
456#ifdef CLOBBER_FREED_MEMORY
476#ifdef CLOBBER_FREED_MEMORY
541#ifdef MEMORY_CONTEXT_CHECKING
542 chunk->requested_size = size;
552#ifdef RANDOMIZE_ALLOCATED_MEMORY
639 elog(
ERROR,
"unexpected alloc chunk size %zu (expected %u)", size,
751#ifdef MEMORY_CONTEXT_CHECKING
755 elog(
ERROR,
"detected double pfree in %s %p",
760 elog(
WARNING,
"detected write past chunk end in %s %p",
775#ifdef CLOBBER_FREED_MEMORY
831#ifdef CLOBBER_FREED_MEMORY
887 elog(
ERROR,
"could not find block containing chunk %p", chunk);
894 elog(
ERROR,
"slab allocator does not support realloc()");
1000 freechunks += block->
nfree;
1010 "%zu total in %zu blocks; %u empty blocks; %zu free (%zu chunks); %zu used",
1012 freespace, freechunks, totalspace - freespace);
1018 totals->nblocks += nblocks;
1019 totals->freechunks += freechunks;
1020 totals->totalspace += totalspace;
1021 totals->freespace += freespace;
1026#ifdef MEMORY_CONTEXT_CHECKING
1057 elog(
WARNING,
"problem in slab %s: empty block %p should have %d free chunks but has %d chunks free",
1078 elog(
WARNING,
"problem in slab %s: block %p is on blocklist %d but should be on blocklist %d",
1083 elog(
WARNING,
"problem in slab %s: empty block %p incorrectly stored on blocklist element %d",
1087 if (block->
slab != slab)
1088 elog(
WARNING,
"problem in slab %s: bogus slab link in block %p",
1108 elog(
WARNING,
"problem in slab %s: bogus free list link %p in block %p",
1113 slab->isChunkFree[
chunkidx] =
true;
1123 elog(
WARNING,
"problem in slab %s: mismatch detected between nunused chunks and unused pointer in block %p",
1139 slab->isChunkFree[
chunkidx] =
true;
1147 if (!slab->isChunkFree[
j])
1165 elog(
WARNING,
"problem in slab %s: bogus block link in block %p, chunk %p",
1166 name, block, chunk);
1171 elog(
WARNING,
"problem in slab %s: detected write past chunk end in block %p, chunk %p",
1172 name, block, chunk);
1180 if (nfree != block->
nfree)
1181 elog(
WARNING,
"problem in slab %s: nfree in block %p is %d but %d chunk were found as free",
#define Assert(condition)
#define StaticAssertDecl(condition, errmessage)
int errcode(int sqlerrcode)
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
static void dlist_delete_from(dlist_head *head, dlist_node *node)
#define dlist_head_element(type, membername, lhead)
static void dlist_delete(dlist_node *node)
static uint32 dclist_count(const dclist_head *head)
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 void dclist_delete_from(dclist_head *head, dlist_node *node)
static dlist_node * dclist_pop_head_node(dclist_head *head)
static void dclist_push_head(dclist_head *head, dlist_node *node)
static void dclist_init(dclist_head *head)
#define dclist_foreach_modify(iter, lhead)
#define dlist_container(type, membername, ptr)
#define dclist_foreach(iter, lhead)
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_DESTROY_MEMPOOL(context)
#define VALGRIND_MAKE_MEM_DEFINED(addr, 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 MEMORYCHUNK_MAX_BLOCKOFFSET
#define MEMORYCHUNK_MAX_VALUE
#define MemoryChunkGetPointer(c)
static void * MemoryChunkGetBlock(MemoryChunk *chunk)
#define PointerGetMemoryChunk(p)
static void MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block, Size value, MemoryContextMethodID methodid)
void * SlabAlloc(MemoryContext context, Size size, int flags)
static pg_noinline void * SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
void SlabFree(void *pointer)
void SlabReset(MemoryContext context)
static MemoryChunk * SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block)
#define SlabChunkGetPointer(chk)
MemoryContext SlabContextCreate(MemoryContext parent, const char *name, Size blockSize, Size chunkSize)
static int32 SlabBlocklistIndex(SlabContext *slab, int nfree)
static void * SlabAllocSetupNewChunk(MemoryContext context, SlabBlock *block, MemoryChunk *chunk, Size size)
Size SlabGetChunkSpace(void *pointer)
#define Slab_CONTEXT_HDRSZ(chunksPerBlock)
bool SlabIsEmpty(MemoryContext context)
MemoryContext SlabGetChunkContext(void *pointer)
static int32 SlabFindNextBlockListIndex(SlabContext *slab)
pg_noreturn static pg_noinline void SlabAllocInvalidSize(MemoryContext context, Size size)
#define SlabBlockGetChunk(slab, block, n)
void * SlabRealloc(void *pointer, Size size, int flags)
void SlabStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
void SlabDelete(MemoryContext context)
#define SLAB_BLOCKLIST_COUNT
#define SlabBlockIsValid(block)
#define SLAB_MAXIMUM_EMPTY_BLOCKS
dlist_head blocklist[SLAB_BLOCKLIST_COUNT]