From 9c5d0803176d9bb74741a87ea0761a89a4ec850b Mon Sep 17 00:00:00 2001
From: David Rowley <dgrowley@gmail.com>
Date: Tue, 13 Oct 2026 13:08:45 +1300
Subject: [PATCH v5 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}   | 315 +++++++++---------
 src/include/utils/memutils.h                  |   2 +-
 src/include/utils/memutils_internal.h         |  26 +-
 src/tools/pgindent/typedefs.list              |   4 +-
 8 files changed, 200 insertions(+), 194 deletions(-)
 rename src/backend/utils/mmgr/{systemcxt.c => systemctx.c} (51%)

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 51%
rename from src/backend/utils/mmgr/systemcxt.c
rename to src/backend/utils/mmgr/systemctx.c
index 23ff06e692d..6bc2b8f0af6 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);
@@ -257,26 +256,27 @@ SystemCxtRealloc(void *pointer, size_t size, int flags)
 	 * Temporarily unlink the allocation, because the address of the
 	 * allocation may change.
 	 */
-	dlist_delete_from_thoroughly(&cxt->allocations, &block->node);
+	dlist_delete_from_thoroughly(&ctx->allocations, &block->node);
 
 	new_block = realloc(block, new_blksz);
-	if (new_block == NULL)
+	if (unlikely(new_block == NULL))
 	{
+		/* don't leak the block on failed realloc */
+		dlist_push_tail(&ctx->allocations, &block->node);
+
 		VALGRIND_MAKE_MEM_NOACCESS(chunk, SYSTEM_CHUNKHDRSZ);
-		return MemoryContextAllocationFailure((MemoryContext) cxt, size, flags);
+		return MemoryContextAllocationFailure((MemoryContext) ctx, size, flags);
 	}
 
 	/* 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 +288,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 +302,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 +344,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 +408,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 +416,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 +439,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 +462,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 +476,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 +484,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

