From 0fccf4121ac39fe3e63d8f0b6940003bc792b760 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Tue, 13 Oct 2026 13:08:45 +1300 Subject: [PATCH v4 2/2] fixup! MemCTX: Add minimal system context type --- src/backend/utils/mmgr/Makefile | 4 +- src/backend/utils/mmgr/README | 19 +- src/backend/utils/mmgr/mcxt.c | 22 +- src/backend/utils/mmgr/meson.build | 2 +- .../utils/mmgr/{systemcxt.c => systemctx.c} | 320 +++++++++--------- src/include/utils/memutils.h | 2 +- src/include/utils/memutils_internal.h | 26 +- src/tools/pgindent/typedefs.list | 4 +- 8 files changed, 201 insertions(+), 198 deletions(-) rename src/backend/utils/mmgr/{systemcxt.c => systemctx.c} (52%) diff --git a/src/backend/utils/mmgr/Makefile b/src/backend/utils/mmgr/Makefile index 8d04b1ae041..44a719ff279 100644 --- a/src/backend/utils/mmgr/Makefile +++ b/src/backend/utils/mmgr/Makefile @@ -22,7 +22,7 @@ OBJS = \ mcxt.o \ memdebug.o \ portalmem.o \ - slab.o - systemcxt.o + slab.o \ + systemctx.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/utils/mmgr/README b/src/backend/utils/mmgr/README index 1ec4f54074d..59105fe0966 100644 --- a/src/backend/utils/mmgr/README +++ b/src/backend/utils/mmgr/README @@ -495,15 +495,16 @@ other allocator types also exist which are special-purpose: allocations. Blocks are only free'd back to the operating system when the context is reset or deleted. -* systemctx.c (SystemContext) is best suited for those use cases that require - long-lived allocations, but have minimal allocation traffic that doesn't - require the lowest latencies, and generally are expected to hold only few - allocations. Allocations get a small header, but are otherwise forwarded - directly the system allocator; similarly, pfree() is forwarded directly to - the system allocator as well. - The most suitable use cases are for contexts that require very few and - long-lived allocations. The context header is also small, so this can be - suitable when a large number of contexts are required. +* systemctx.c (SystemContext) is best suited for cases that require long-lived + allocations, but have minimal allocation traffic that doesn't require the + lowest latencies. Because headers for each allocation are much larger than + with other context types, this context type is not well suited when many + small allocations are required. Every allocation results in a malloc() + call, and every pfree results in a free(). The most suitable use cases are + for contexts that require very few and long-lived allocations. The memory + overhead for the context itself is much smaller than with other context + types, so this implementation can be suitable when a large number of + contexts are required. For further details, please read the header comment in the corresponding .c file. diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 67853db1dd0..8f73e72b8d8 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -132,18 +132,18 @@ static const MemoryContextMethods mcxt_methods[] = { [MCTX_BUMP_ID].check = BumpCheck, #endif - /* systemcxt.c */ - [MCTX_SYSTEM_ID].alloc = SystemCxtAlloc, - [MCTX_SYSTEM_ID].free_p = SystemCxtFree, - [MCTX_SYSTEM_ID].realloc = SystemCxtRealloc, - [MCTX_SYSTEM_ID].reset = SystemCxtReset, - [MCTX_SYSTEM_ID].delete_context = SystemCxtDelete, - [MCTX_SYSTEM_ID].get_chunk_context = SystemCxtGetChunkContext, - [MCTX_SYSTEM_ID].get_chunk_space = SystemCxtGetChunkSpace, - [MCTX_SYSTEM_ID].is_empty = SystemCxtIsEmpty, - [MCTX_SYSTEM_ID].stats = SystemCxtStats, + /* systemctx.c */ + [MCTX_SYSTEM_ID].alloc = SystemContextAlloc, + [MCTX_SYSTEM_ID].free_p = SystemContextFree, + [MCTX_SYSTEM_ID].realloc = SystemContextRealloc, + [MCTX_SYSTEM_ID].reset = SystemContextReset, + [MCTX_SYSTEM_ID].delete_context = SystemContextDelete, + [MCTX_SYSTEM_ID].get_chunk_context = SystemContextGetChunkContext, + [MCTX_SYSTEM_ID].get_chunk_space = SystemContextGetChunkSpace, + [MCTX_SYSTEM_ID].is_empty = SystemContextIsEmpty, + [MCTX_SYSTEM_ID].stats = SystemContextStats, #ifdef MEMORY_CONTEXT_CHECKING - [MCTX_SYSTEM_ID].check = SystemCxtCheck, + [MCTX_SYSTEM_ID].check = SystemContextCheck, #endif /* diff --git a/src/backend/utils/mmgr/meson.build b/src/backend/utils/mmgr/meson.build index 5a9d6bbb36f..65e55f430ea 100644 --- a/src/backend/utils/mmgr/meson.build +++ b/src/backend/utils/mmgr/meson.build @@ -11,5 +11,5 @@ backend_sources += files( 'memdebug.c', 'portalmem.c', 'slab.c', - 'systemcxt.c', + 'systemctx.c', ) diff --git a/src/backend/utils/mmgr/systemcxt.c b/src/backend/utils/mmgr/systemctx.c similarity index 52% rename from src/backend/utils/mmgr/systemcxt.c rename to src/backend/utils/mmgr/systemctx.c index 23ff06e692d..1de718130f4 100644 --- a/src/backend/utils/mmgr/systemcxt.c +++ b/src/backend/utils/mmgr/systemctx.c @@ -1,33 +1,24 @@ /*------------------------------------------------------------------------- -* - * systemcxt.c + * + * systemctx.c * System context allocator definitions. * - * systemcxt.c (SystemContext) has no concept of grouping several allocations - * into blocks like many of the other allocators do. Each palloc() results in - * a malloc(), and each pfree() results in a free(), therefore, this isn't - * suitable for cases that require many allocations. The most suitable use - * cases are for contexts that require very few and long-lived allocations. - * The context header is also small, so this can be suitable when a large - * number of contexts are required. - * System is a MemoryContext implementation designed for memory usages which - * require their own memory context, but which generally have few allocations - * that generally have a very long lifetime. Compared to ASet, every - * allocation of a System memory context gets an External chunk, i.e. every - * palloc results in a malloc. + * SystemContext has no concept of grouping several allocations into blocks + * like many of the other allocators do. Each palloc() results in a malloc(), + * and each pfree() results in a free(), therefore, this isn't suitable for + * cases that require many allocations. The most suitable use cases are for + * contexts that require very few and long-lived allocations. * - * Portions Copyright (c) 2024-2026, PostgreSQL Global Development Group + * The memory overhead for the context itself is much smaller than with other + * context types, so this implementation can be suitable when a large number + * of contexts are required. * - * IDENTIFICATION - * src/backend/utils/mmgr/systemcxt.c + * Portions Copyright (c) 2026, PostgreSQL Global Development Group * - * NOTE: - * SystemCxt is best suited to cases where a memory context with long lifetimes - * is required, but is expected to hold only a small number of small - * allocations, with a total memory usage smaller than the minimum aset block - * size. + * IDENTIFICATION + * src/backend/utils/mmgr/systemctx.c * - * Allocations are MAXALIGNed. + * NOTE: Allocations are MAXALIGNed. * *------------------------------------------------------------------------- */ @@ -44,14 +35,14 @@ typedef struct SystemContext { MemoryContextData header; /* Standard memory-context fields */ - dlist_head allocations; /* list of all allocations of this memcxt */ + dlist_head allocations; /* list of all allocated SystemBlocks */ } SystemContext; /* Struct definition for SystemContext's malloc()'d header. */ typedef struct SystemBlock { - dlist_node node; /* node in SystemCtx->allocations */ - size_t sz; /* size of the requested allocation */ + dlist_node node; /* node in SystemContext->allocations */ + size_t sz; /* malloc'd size of this allocation */ SystemContext *context; /* direct pointer to the owning context */ } SystemBlock; @@ -60,31 +51,40 @@ typedef struct SystemBlock #define SYSTEM_CHUNKHDRSZ (sizeof(MemoryChunk)) /* - * SystemCxtIsValid - * True iff cxt is valid allocation cxt. + * SystemContextIsValid + * True iff ctx is a valid SystemContext. */ -#define SystemCxtIsValid(cxt) \ - ((cxt) && IsA(cxt, SystemContext)) +#define SystemContextIsValid(ctx) ((ctx) && IsA(ctx, SystemContext)) -#define ExternalChunkGetBlock(chunk) \ +/* + * ChunkGetBlock + * Return address of SystemBlock for given MemoryChunk. + */ +#define ChunkGetBlock(chunk) \ ((SystemBlock *) (((char *) chunk) - SYSTEM_BLOCKHDRSZ)) +/* + * BlockGetChunk + * Return address of MemoryChunk for given SystemBlock. + */ +#define BlockGetChunk(blk) \ + ((MemoryChunk *) (((char *) blk) + SYSTEM_BLOCKHDRSZ)) /* * SystemContextCreate - * Create a SystemCxt memory context + * Create a SystemContext memory context */ MemoryContext SystemContextCreate(MemoryContext parent, const char *name) { - SystemContext *cxt; + SystemContext *ctx; /* - * Allocate the context struct. Unlike other memory contexts, this - * context doesn't have an attached chunk of palloc'able memory. + * Allocate the context struct. Unlike other memory contexts, we don't + * add additional space here for the initial block. */ - cxt = (SystemContext *) malloc(SYSTEM_CONTEXTSIZE); - if (cxt == NULL) + ctx = (SystemContext *) malloc(SYSTEM_CONTEXTSIZE); + if (ctx == NULL) { MemoryContextStats(TopMemoryContext); ereport(ERROR, @@ -94,33 +94,33 @@ SystemContextCreate(MemoryContext parent, const char *name) name))); } - VALGRIND_CREATE_MEMPOOL(cxt, 0, false); - VALGRIND_MEMPOOL_ALLOC(cxt, cxt, SYSTEM_CONTEXTSIZE); + VALGRIND_CREATE_MEMPOOL(ctx, 0, false); + VALGRIND_MEMPOOL_ALLOC(ctx, ctx, SYSTEM_CONTEXTSIZE); - dlist_init(&cxt->allocations); + dlist_init(&ctx->allocations); /* Finally, do the type-independent part of context creation */ - MemoryContextCreate((MemoryContext) cxt, T_SystemContext, MCTX_SYSTEM_ID, + MemoryContextCreate((MemoryContext) ctx, T_SystemContext, MCTX_SYSTEM_ID, parent, name); - ((MemoryContext) cxt)->mem_allocated = SYSTEM_CONTEXTSIZE; + ((MemoryContext) ctx)->mem_allocated = SYSTEM_CONTEXTSIZE; - return (MemoryContext) cxt; + return (MemoryContext) ctx; } /* - * SystemCxtAlloc - * Alloc memory into the SystemCxt memory context. + * SystemContextAlloc + * Alloc memory into the SystemContext memory context. */ void * -SystemCxtAlloc(MemoryContext context, size_t size, int flags) +SystemContextAlloc(MemoryContext context, size_t size, int flags) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; size_t blksize; SystemBlock *block; MemoryChunk *chunk; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); /* validate 'size' is within the limits for the given 'flags' */ MemoryContextCheckSize(context, size, flags); @@ -138,18 +138,18 @@ SystemCxtAlloc(MemoryContext context, size_t size, int flags) if (block == NULL) return MemoryContextAllocationFailure(context, size, flags); - VALGRIND_MEMPOOL_ALLOC(cxt, block, SYSTEM_BLOCKHDRSZ); + VALGRIND_MEMPOOL_ALLOC(ctx, block, SYSTEM_BLOCKHDRSZ); context->mem_allocated += blksize; dlist_node_init(&block->node); - block->context = cxt; + block->context = ctx; block->sz = blksize; - dlist_push_tail(&cxt->allocations, &block->node); + dlist_push_tail(&ctx->allocations, &block->node); - chunk = (MemoryChunk *) (((char *) block) + SYSTEM_BLOCKHDRSZ); + chunk = BlockGetChunk(block); MemoryChunkSetHdrMaskExternal(chunk, MCTX_SYSTEM_ID); @@ -170,13 +170,13 @@ SystemCxtAlloc(MemoryContext context, size_t size, int flags) } /* - * SystemCxtAlloc - * Free memory from the SystemCxt memory context. + * SystemContextFree + * Free memory from the SystemContext memory context. */ void -SystemCxtFree(void *pointer) +SystemContextFree(void *pointer) { - SystemContext *cxt; + SystemContext *ctx; MemoryChunk *chunk = PointerGetMemoryChunk(pointer); SystemBlock *block; @@ -184,43 +184,43 @@ SystemCxtFree(void *pointer) Assert(MemoryChunkIsExternal(chunk)); - block = ExternalChunkGetBlock(chunk); + block = ChunkGetBlock(chunk); - cxt = block->context; + ctx = block->context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); #ifdef MEMORY_CONTEXT_CHECKING /* Test for someone scribbling on unused space in chunk */ if (!sentinel_ok(pointer, chunk->requested_size)) elog(WARNING, "detected write past chunk end in %s %p", - cxt->header.name, chunk); + ctx->header.name, chunk); #endif /* ok, remove block from the list, and free it */ - dlist_delete_from(&cxt->allocations, &block->node); + dlist_delete_from(&ctx->allocations, &block->node); - cxt->header.mem_allocated -= block->sz; + ctx->header.mem_allocated -= block->sz; #ifdef CLOBBER_FREED_MEMORY wipe_mem(block, block->sz); #endif - VALGRIND_MEMPOOL_FREE(cxt, block); + VALGRIND_MEMPOOL_FREE(ctx, block); free(block); } /* - * SystemCxtAlloc - * Realloc memory in the SystemCxt memory context. + * SystemContextRealloc + * Realloc memory in the SystemContext memory context. */ void * -SystemCxtRealloc(void *pointer, size_t size, int flags) +SystemContextRealloc(void *pointer, size_t size, int flags) { SystemBlock *block, *new_block; - SystemContext *cxt; + SystemContext *ctx; MemoryChunk *chunk = PointerGetMemoryChunk(pointer); size_t new_blksz; @@ -228,23 +228,22 @@ SystemCxtRealloc(void *pointer, size_t size, int flags) Assert(MemoryChunkIsExternal(chunk)); - block = ExternalChunkGetBlock(chunk); + block = ChunkGetBlock(chunk); - cxt = block->context; + ctx = block->context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); /* only check size in paths where the limits could be hit */ - MemoryContextCheckSize((MemoryContext) cxt, size, flags); + MemoryContextCheckSize((MemoryContext) ctx, size, flags); #ifdef MEMORY_CONTEXT_CHECKING /* Test for someone scribbling on unused space in chunk */ if (!sentinel_ok(pointer, chunk->requested_size)) elog(WARNING, "detected write past chunk end in %s %p", - cxt->header.name, chunk); + ctx->header.name, chunk); #endif - #ifdef MEMORY_CONTEXT_CHECKING /* adjust for sentinel byte, and align */ new_blksz = MAXALIGN(size + 1); @@ -253,30 +252,28 @@ SystemCxtRealloc(void *pointer, size_t size, int flags) #endif new_blksz += SYSTEM_BLOCKHDRSZ + SYSTEM_CHUNKHDRSZ; - /* - * Temporarily unlink the allocation, because the address of the - * allocation may change. - */ - dlist_delete_from_thoroughly(&cxt->allocations, &block->node); - new_block = realloc(block, new_blksz); if (new_block == NULL) { VALGRIND_MAKE_MEM_NOACCESS(chunk, SYSTEM_CHUNKHDRSZ); - return MemoryContextAllocationFailure((MemoryContext) cxt, size, flags); + return MemoryContextAllocationFailure((MemoryContext) ctx, size, flags); } + /* + * Temporarily unlink the allocation, because the address of the + * allocation may change. + */ + dlist_delete_from_thoroughly(&ctx->allocations, &new_block->node); + /* Move the block-header vchunk */ - VALGRIND_MEMPOOL_CHANGE(cxt, block, new_block, SYSTEM_BLOCKHDRSZ); + VALGRIND_MEMPOOL_CHANGE(ctx, block, new_block, SYSTEM_BLOCKHDRSZ); block = new_block; - dlist_push_tail(&cxt->allocations, &block->node); + dlist_push_tail(&ctx->allocations, &block->node); - chunk = (MemoryChunk *) (((char *) block) + SYSTEM_BLOCKHDRSZ); + chunk = BlockGetChunk(block); - /* - * randomize the newly allocated portion, old_len .. new_len - */ + /* when enlarging, randomize the enlarged portion */ #ifdef RANDOMIZE_ALLOCATED_MEMORY if (new_blksz > block->sz) randomize_mem(((char *) block) + block->sz, new_blksz - block->sz); @@ -288,6 +285,10 @@ SystemCxtRealloc(void *pointer, size_t size, int flags) set_sentinel(MemoryChunkGetPointer(chunk), size); #endif + /* adjust memory accounting for the context */ + ctx->header.mem_allocated -= block->sz; + ctx->header.mem_allocated += new_blksz; + /* and adjust the size indicator of the block header */ block->sz = new_blksz; @@ -298,41 +299,41 @@ SystemCxtRealloc(void *pointer, size_t size, int flags) } /* - * SystemCxtReset - * Reset the SystemCxt memory context. + * SystemContextReset + * Reset the SystemContext memory context. */ void -SystemCxtReset(MemoryContext context) +SystemContextReset(MemoryContext context) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); - while (!dlist_is_empty(&cxt->allocations)) + while (!dlist_is_empty(&ctx->allocations)) { SystemBlock *block = dlist_container(SystemBlock, node, - dlist_pop_head_node(&cxt->allocations)); + dlist_pop_head_node(&ctx->allocations)); size_t blksize = block->sz; #ifdef CLOBBER_FREED_MEMORY wipe_mem(block, blksize); #endif - cxt->header.mem_allocated -= blksize; + ctx->header.mem_allocated -= blksize; /* - * We need to free the block header's vchunk explicitly, although - * the user-data vchunks within will go away in the TRIM below. - * Otherwise Valgrind complains about leaked allocations. + * We need to free the block header's vchunk explicitly, although the + * user-data vchunks within will go away in the TRIM below. Otherwise + * Valgrind complains about leaked allocations. */ - VALGRIND_MEMPOOL_FREE(cxt, block); + VALGRIND_MEMPOOL_FREE(ctx, block); free(block); } - Assert(cxt->header.mem_allocated == SYSTEM_CONTEXTSIZE); - Assert(SystemCxtIsEmpty(context)); + Assert(ctx->header.mem_allocated == SYSTEM_CONTEXTSIZE); + Assert(SystemContextIsEmpty(context)); /* * Instruct Valgrind to throw away all the vchunks associated with this @@ -340,63 +341,63 @@ SystemCxtReset(MemoryContext context) * of the vchunks for whatever user data is getting discarded by the * context reset. */ - VALGRIND_MEMPOOL_TRIM(cxt, cxt, SYSTEM_CONTEXTSIZE); + VALGRIND_MEMPOOL_TRIM(ctx, ctx, SYSTEM_CONTEXTSIZE); } /* - * SystemCxtAlloc - * Delete this SystemCxt memory context. + * SystemContextDelete + * Delete this SystemContext memory context. */ void -SystemCxtDelete(MemoryContext context) +SystemContextDelete(MemoryContext context) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); #ifdef MEMORY_CONTEXT_CHECKING - SystemCxtCheck(context); + SystemContextCheck(context); #endif - SystemCxtReset(context); + SystemContextReset(context); VALGRIND_DESTROY_MEMPOOL(context); - free(cxt); + free(ctx); } /* - * SystemCxtGetChunkContext + * SystemContextGetChunkContext * Return the MemoryContext that 'pointer' belongs to. */ MemoryContext -SystemCxtGetChunkContext(void *pointer) +SystemContextGetChunkContext(void *pointer) { - MemoryChunk *chunk = PointerGetMemoryChunk(pointer); - SystemBlock *block; - SystemContext *cxt; + MemoryChunk *chunk = PointerGetMemoryChunk(pointer); + SystemBlock *block; + SystemContext *ctx; VALGRIND_MAKE_MEM_DEFINED(chunk, SYSTEM_CHUNKHDRSZ); Assert(MemoryChunkIsExternal(chunk)); - block = ExternalChunkGetBlock(chunk); + block = ChunkGetBlock(chunk); VALGRIND_MAKE_MEM_NOACCESS(chunk, SYSTEM_CHUNKHDRSZ); - cxt = block->context; + ctx = block->context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); - return (MemoryContext) cxt; + return (MemoryContext) ctx; } /* - * SystemCxtGetChunkSpace -* Given a palloc'd chunk, determine the total space + * SystemContextGetChunkSpace + * Given a palloc'd chunk, determine the total space * it occupies (including all memory-allocation overhead). */ size_t -SystemCxtGetChunkSpace(void *pointer) +SystemContextGetChunkSpace(void *pointer) { MemoryChunk *chunk = PointerGetMemoryChunk(pointer); SystemBlock *block; @@ -404,7 +405,7 @@ SystemCxtGetChunkSpace(void *pointer) VALGRIND_MAKE_MEM_DEFINED(chunk, SYSTEM_CHUNKHDRSZ); Assert(MemoryChunkIsExternal(chunk)); - block = ExternalChunkGetBlock(chunk); + block = ChunkGetBlock(chunk); VALGRIND_MAKE_MEM_NOACCESS(chunk, SYSTEM_CHUNKHDRSZ); @@ -412,22 +413,22 @@ SystemCxtGetChunkSpace(void *pointer) } /* - * SystemCxtIsEmpty -* Is the SystemContext empty of any allocated space? + * SystemContextIsEmpty + * Is the SystemContext empty of any allocated space? */ bool -SystemCxtIsEmpty(MemoryContext context) +SystemContextIsEmpty(MemoryContext context) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; - Assert(SystemCxtIsValid(cxt)); + Assert(SystemContextIsValid(ctx)); - return dlist_is_empty(&cxt->allocations); + return dlist_is_empty(&ctx->allocations); } /* - * SystemCxtStats - * Compute stats about memory consumption of a SystemCxt context. + * SystemContextStats + * Compute stats about memory consumption of a SystemContext context. * * printfunc: if not NULL, pass a human-readable stats string to this. * passthru: pass this pointer through to printfunc. @@ -435,18 +436,16 @@ SystemCxtIsEmpty(MemoryContext context) * print_to_stderr: print stats to stderr if true, elog otherwise. */ void -SystemCxtStats(MemoryContext context, MemoryStatsPrintFunc printfunc, - void *passthru, MemoryContextCounters *totals, - bool print_to_stderr) +SystemContextStats(MemoryContext context, MemoryStatsPrintFunc printfunc, + void *passthru, MemoryContextCounters *totals, + bool print_to_stderr) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; dlist_iter iter; - size_t totalspace; + size_t totalspace = SYSTEM_CONTEXTSIZE; size_t nchunks = 0; - totalspace = MAXALIGN(sizeof(SystemContext)); - - dlist_foreach(iter, &cxt->allocations) + dlist_foreach(iter, &ctx->allocations) { SystemBlock *block = dlist_container(SystemBlock, node, iter.cur); @@ -460,7 +459,7 @@ SystemCxtStats(MemoryContext context, MemoryStatsPrintFunc printfunc, char stats_string[200]; snprintf(stats_string, sizeof(stats_string), - "%zu total in %zu chunks;", + "%zu total in %zu chunks", totalspace, nchunks); printfunc(context, passthru, stats_string, print_to_stderr); } @@ -474,7 +473,7 @@ SystemCxtStats(MemoryContext context, MemoryStatsPrintFunc printfunc, #ifdef MEMORY_CONTEXT_CHECKING /* - * SystemCxtCheck + * SystemContextCheck * Walk through chunks and check consistency of memory. * * NOTE: report errors as WARNING, *not* ERROR or FATAL. Otherwise you'll @@ -482,40 +481,43 @@ SystemCxtStats(MemoryContext context, MemoryStatsPrintFunc printfunc, * routine will be entered again when elog cleanup tries to release memory! */ void -SystemCxtCheck(MemoryContext context) +SystemContextCheck(MemoryContext context) { - SystemContext *cxt = (SystemContext *) context; + SystemContext *ctx = (SystemContext *) context; const char *name = context->name; dlist_iter iter; - size_t total_allocated = sizeof(SystemContext); + size_t total_allocated = SYSTEM_CONTEXTSIZE; /* walk all blocks in this context */ - dlist_foreach(iter, &cxt->allocations) + dlist_foreach(iter, &ctx->allocations) { SystemBlock *block = dlist_container(SystemBlock, node, iter.cur); - MemoryChunk *chunk = (MemoryChunk *) ((char *) block + SYSTEM_BLOCKHDRSZ); + MemoryChunk *chunk = BlockGetChunk(block); + void *pointer = MemoryChunkGetPointer(chunk); + size_t expected_sz; + + /* Allow access to the chunk header. */ + VALGRIND_MAKE_MEM_DEFINED(chunk, SYSTEM_CHUNKHDRSZ); total_allocated += block->sz; + expected_sz = MAXALIGN(chunk->requested_size + 1) + SYSTEM_BLOCKHDRSZ + + SYSTEM_CHUNKHDRSZ; - if (block->sz != MAXALIGN(chunk->requested_size + 1) + SYSTEM_BLOCKHDRSZ + SYSTEM_CHUNKHDRSZ) - { - elog(WARNING, "problem in SystemCxt %s: bad single-chunk %p in block %p", - name, chunk, block); - } + if (block->sz != expected_sz) + elog(WARNING, "problem in SystemContext %s: chunk %p has an unexpected size; block->sz is %zu but expected size is %zu bytes", + name, chunk, block->sz, expected_sz); - if (!sentinel_ok(chunk, chunk->requested_size + SYSTEM_CHUNKHDRSZ)) - { - elog(WARNING, "problem in SystemCxt %s: detected write past chunk end in block %p, chunk %p", + if (!sentinel_ok(pointer, chunk->requested_size)) + elog(WARNING, "problem in SystemContext %s: detected write past chunk end in block %p, chunk %p", name, block, chunk); - } + + VALGRIND_MAKE_MEM_NOACCESS(chunk, SYSTEM_CHUNKHDRSZ); } Assert(total_allocated == context->mem_allocated); - if (total_allocated != cxt->header.mem_allocated) - { - elog(WARNING, "problem in SystemCxt %s: sum of memory %zd does not match header's %zd", - name, total_allocated, cxt->header.mem_allocated); - } + if (total_allocated != ctx->header.mem_allocated) + elog(WARNING, "problem in SystemContext %s: sum of memory %zu does not match header's %zu", + name, total_allocated, ctx->header.mem_allocated); } #endif diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index 8cae0ae3d8d..25078ae39c8 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -150,7 +150,7 @@ extern MemoryContext BumpContextCreate(MemoryContext parent, Size initBlockSize, Size maxBlockSize); -/* systemcxt.c */ +/* systemctx.c */ extern MemoryContext SystemContextCreate(MemoryContext parent, const char *name); diff --git a/src/include/utils/memutils_internal.h b/src/include/utils/memutils_internal.h index 3f0af809828..97ebec7a493 100644 --- a/src/include/utils/memutils_internal.h +++ b/src/include/utils/memutils_internal.h @@ -95,20 +95,20 @@ extern void BumpStats(MemoryContext context, MemoryStatsPrintFunc printfunc, extern void BumpCheck(MemoryContext context); #endif - /* These functions implement the MemoryContext API for the Proxy context. */ -extern void *SystemCxtAlloc(MemoryContext context, size_t size, int flags); -extern void SystemCxtFree(void *pointer); -extern void *SystemCxtRealloc(void *pointer, size_t size, int flags); -extern void SystemCxtReset(MemoryContext context); -extern void SystemCxtDelete(MemoryContext context); -extern MemoryContext SystemCxtGetChunkContext(void *pointer); -extern size_t SystemCxtGetChunkSpace(void *pointer); -extern bool SystemCxtIsEmpty(MemoryContext context); -extern void SystemCxtStats(MemoryContext context, MemoryStatsPrintFunc printfunc, - void *passthru, MemoryContextCounters *totals, - bool print_to_stderr); +/* These functions implement the MemoryContext API for the System context. */ +extern void *SystemContextAlloc(MemoryContext context, size_t size, int flags); +extern void SystemContextFree(void *pointer); +extern void *SystemContextRealloc(void *pointer, size_t size, int flags); +extern void SystemContextReset(MemoryContext context); +extern void SystemContextDelete(MemoryContext context); +extern MemoryContext SystemContextGetChunkContext(void *pointer); +extern size_t SystemContextGetChunkSpace(void *pointer); +extern bool SystemContextIsEmpty(MemoryContext context); +extern void SystemContextStats(MemoryContext context, MemoryStatsPrintFunc printfunc, + void *passthru, MemoryContextCounters *totals, + bool print_to_stderr); #ifdef MEMORY_CONTEXT_CHECKING -extern void SystemCxtCheck(MemoryContext context); +extern void SystemContextCheck(MemoryContext context); #endif /* diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index ce3ab753927..e512b3e522c 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2429,8 +2429,6 @@ ProjectionInfo ProjectionPath PromptInterruptContext ProtocolVersion -ProxyContext -ProxyChunk PrsStorage PruneFreezeParams PruneFreezeResult @@ -3061,6 +3059,8 @@ SysScanDesc SysScanDescData SyscacheCallbackFunction SysloggerStartupData +SystemBlock +SystemContext SystemRowsSamplerData SystemSamplerData SystemTimeSamplerData -- 2.53.0