From 45696d8f2371cceca1e38719ef49036cdd67c250 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Mon, 6 Apr 2026 13:00:00 +0530
Subject: [PATCH v20260406 4/6] Avoid creating ABI incompatibility because of
 HAVE_RESIZABLE_SHMEM

Per the suggestion at https://www.postgresql.org/message-id/CAEze2Wjn2cpQEPwzLajc0XdcMy8T=d1AWjg3UAmMUT2TmHkQkA@mail.gmail.com
---
 src/backend/port/sysv_shmem.c                 | 14 +++++-
 src/backend/port/win32_shmem.c                | 22 +++++++++
 src/backend/storage/ipc/shmem.c               | 48 +++++++------------
 src/include/storage/pg_shmem.h                |  2 -
 src/include/storage/shmem.h                   |  5 --
 .../modules/resizable_shmem/resizable_shmem.c | 22 +++++----
 src/test/modules/test_shmem/test_shmem.c      |  6 ---
 7 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 8d859dfbbfb..bb2a81417c6 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -1013,7 +1013,6 @@ PGSharedMemoryDetach(void)
 	}
 }
 
-#ifdef HAVE_RESIZABLE_SHMEM
 /*
  * Make sure that the memory of given size from the given address is released.
  *
@@ -1024,6 +1023,11 @@ PGSharedMemoryDetach(void)
 void
 PGSharedMemoryEnsureFreed(void *addr, Size size)
 {
+#ifndef HAVE_RESIZABLE_SHMEM
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("resizable shared memory is not supported on this platform")));
+#else
 	if (!AnonymousShmem)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1035,6 +1039,7 @@ PGSharedMemoryEnsureFreed(void *addr, Size size)
 	if (madvise(addr, size, MADV_REMOVE) == -1)
 		ereport(ERROR,
 				(errmsg("could not free shared memory: %m")));
+#endif
 }
 
 /*
@@ -1047,6 +1052,11 @@ PGSharedMemoryEnsureFreed(void *addr, Size size)
 void
 PGSharedMemoryEnsureAllocated(void *addr, Size size)
 {
+#ifndef HAVE_RESIZABLE_SHMEM
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("resizable shared memory is not supported on this platform")));
+#else
 	if (!AnonymousShmem)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1058,5 +1068,5 @@ PGSharedMemoryEnsureAllocated(void *addr, Size size)
 	if (madvise(addr, size, MADV_POPULATE_WRITE) == -1)
 		ereport(ERROR,
 				(errmsg("could not allocate shared memory: %m")));
+#endif
 }
-#endif							/* HAVE_RESIZABLE_SHMEM */
diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index dc2ee018845..c1f30665e66 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -671,3 +671,25 @@ GetOSPageSize(void)
 
 	return os_page_size;
 }
+
+/*
+ * PGSharedMemoryEnsureFreed / PGSharedMemoryEnsureAllocated
+ *
+ * Not supported on Windows.  These are only meaningful on platforms with
+ * resizable shared memory (mmap + madvise).
+ */
+void
+PGSharedMemoryEnsureFreed(void *addr, Size size)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("resizable shared memory is not supported on this platform")));
+}
+
+void
+PGSharedMemoryEnsureAllocated(void *addr, Size size)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("resizable shared memory is not supported on this platform")));
+}
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 03de5d88d51..4a3e8a8769e 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -185,14 +185,12 @@ typedef struct
 /*
  * A convenient macro to get the space required for a shmem request consistently.
  * A resizable structure, requested by non-zero maximum_size, requires space for
- * its maximum size.
+ * its maximum size. Please note that on the platforms that do not support
+ * resizable shmem, the maximum_size is ensured to be 0 i.e. all the structures
+ * are treated as fixed-size structures.
  */
-#ifdef HAVE_RESIZABLE_SHMEM
 #define SHMEM_REQUEST_SPACE_SIZE(request) \
 	((request)->options->maximum_size > 0 ? (request)->options->maximum_size : (request)->options->size)
-#else
-#define SHMEM_REQUEST_SPACE_SIZE(request) ((request)->options->size)
-#endif
 
 static List *pending_shmem_requests;
 
@@ -296,10 +294,8 @@ typedef struct
 	void	   *location;		/* location in shared mem */
 	Size		size;			/* # bytes requested for the structure */
 	Size		allocated_size; /* # bytes actually allocated */
-#ifdef HAVE_RESIZABLE_SHMEM
 	Size		maximum_size;	/* the maximum size the structure can grow to */
 	Size		reserved_space; /* the total address space reserved */
-#endif
 } ShmemIndexEnt;
 
 /* To get reliable results for NUMA inquiry we need to "touch pages" once */
@@ -308,9 +304,7 @@ static bool firstNumaTouch = true;
 static void CallShmemCallbacksAfterStartup(const ShmemCallbacks *callbacks);
 static void InitShmemIndexEntry(ShmemRequest *request);
 static bool AttachShmemIndexEntry(ShmemRequest *request, bool missing_ok);
-#ifdef HAVE_RESIZABLE_SHMEM
 static Size EstimateAllocatedSize(ShmemIndexEnt *entry);
-#endif
 
 Datum		pg_numa_available(PG_FUNCTION_ARGS);
 
@@ -376,16 +370,22 @@ ShmemRequestInternal(ShmemStructOpts *options, ShmemRequestKind kind)
 	if (options->name == NULL)
 		elog(ERROR, "shared memory request is missing 'name' option");
 
+#ifndef HAVE_RESIZABLE_SHMEM
+	if (options->maximum_size > 0)
+		elog(ERROR, "resizable shared memory is not supported on this platform");
+#else
+	if (options->maximum_size > 0 && shared_memory_type != SHMEM_TYPE_MMAP)
+		elog(ERROR, "resizable shared memory requires shared_memory_type = mmap");
+#endif
+
 	if (IsUnderPostmaster)
 	{
 		if (options->size <= 0 && options->size != SHMEM_ATTACH_UNKNOWN_SIZE)
 			elog(ERROR, "invalid size %zd for shared memory request for \"%s\"",
 				 options->size, options->name);
-#ifdef HAVE_RESIZABLE_SHMEM
 		if (options->maximum_size < 0 && options->maximum_size != SHMEM_ATTACH_UNKNOWN_SIZE)
 			elog(ERROR, "invalid maximum_size %zd for shared memory request for \"%s\"",
 				 options->maximum_size, options->name);
-#endif
 	}
 	else
 	{
@@ -394,28 +394,21 @@ ShmemRequestInternal(ShmemStructOpts *options, ShmemRequestKind kind)
 		if (options->size <= 0)
 			elog(ERROR, "invalid size %zd for shared memory request for \"%s\"",
 				 options->size, options->name);
-#ifdef HAVE_RESIZABLE_SHMEM
 		if (options->maximum_size == SHMEM_ATTACH_UNKNOWN_SIZE)
 			elog(ERROR, "SHMEM_ATTACH_UNKNOWN_SIZE cannot be used during startup");
 		if (options->maximum_size < 0)
 			elog(ERROR, "invalid maximum_size %zd for shared memory request for \"%s\"",
 				 options->maximum_size, options->name);
-#endif
 	}
 
 	if (options->alignment != 0 && pg_nextpower2_size_t(options->alignment) != options->alignment)
 		elog(ERROR, "invalid alignment %zu for shared memory request for \"%s\"",
 			 options->alignment, options->name);
 
-#ifdef HAVE_RESIZABLE_SHMEM
 	if (options->maximum_size > 0 && options->size > options->maximum_size)
 		elog(ERROR, "resizable shared memory structure \"%s\" should have maximum size (%zd) greater than size (%zd)",
 			 options->name, options->maximum_size, options->size);
 
-	if (options->maximum_size > 0 && shared_memory_type != SHMEM_TYPE_MMAP)
-		elog(ERROR, "resizable shared memory requires shared_memory_type = mmap");
-#endif
-
 	/* Check that we're in the right state */
 	if (shmem_request_state != SRS_REQUESTING)
 		elog(ERROR, "ShmemRequestStruct can only be called from a shmem_request callback");
@@ -620,7 +613,6 @@ InitShmemIndexEntry(ShmemRequest *request)
 	index_entry->size = request->options->size;
 	index_entry->allocated_size = allocated_size;
 	index_entry->location = structPtr;
-#ifdef HAVE_RESIZABLE_SHMEM
 	index_entry->reserved_space = allocated_size;
 	index_entry->maximum_size = request->options->maximum_size;
 	if (request->options->maximum_size > 0)
@@ -628,7 +620,6 @@ InitShmemIndexEntry(ShmemRequest *request)
 		/* Adjust allocated size of a resizable structure. */
 		index_entry->allocated_size = EstimateAllocatedSize(index_entry);
 	}
-#endif
 
 	/* Initialize depending on the kind of shmem area it is */
 	switch (request->kind)
@@ -683,7 +674,6 @@ AttachShmemIndexEntry(ShmemRequest *request, bool missing_ok)
 						name, index_entry->size, request->options->size)));
 	}
 
-#ifdef HAVE_RESIZABLE_SHMEM
 	if (index_entry->maximum_size != request->options->maximum_size &&
 		request->options->maximum_size != SHMEM_ATTACH_UNKNOWN_SIZE)
 	{
@@ -693,7 +683,6 @@ AttachShmemIndexEntry(ShmemRequest *request, bool missing_ok)
 						name, index_entry->maximum_size,
 						request->options->maximum_size)));
 	}
-#endif
 
 	/*
 	 * Re-establish the caller's pointer variable, or do other actions to
@@ -716,7 +705,6 @@ AttachShmemIndexEntry(ShmemRequest *request, bool missing_ok)
 	return true;
 }
 
-#ifdef HAVE_RESIZABLE_SHMEM
 /*
  * Estimate the actual memory allocated for a resizable structure.
  *
@@ -760,6 +748,11 @@ EstimateAllocatedSize(ShmemIndexEnt *entry)
 void
 ShmemResizeStruct(const char *name, Size new_size)
 {
+#ifndef HAVE_RESIZABLE_SHMEM
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("resizable shared memory is not supported on this platform")));
+#else
 	ShmemIndexEnt *result;
 	bool		found;
 	Size		page_size = GetOSPageSize();
@@ -822,8 +815,8 @@ ShmemResizeStruct(const char *name, Size new_size)
 	result->allocated_size = EstimateAllocatedSize(result);
 
 	LWLockRelease(ShmemIndexLock);
+#endif
 }
-#endif							/* HAVE_RESIZABLE_SHMEM */
 
 /*
  *	InitShmemAllocator() --- set up basic pointers to shared memory.
@@ -1300,7 +1293,6 @@ pg_get_shmem_allocations(PG_FUNCTION_ARGS)
 		values[1] = Int64GetDatum((char *) ent->location - (char *) ShmemSegHdr);
 		values[2] = Int64GetDatum(ent->size);
 		values[3] = Int64GetDatum(ent->allocated_size);
-#ifdef HAVE_RESIZABLE_SHMEM
 		values[4] = Int64GetDatum(ent->maximum_size);
 		values[5] = Int64GetDatum(ent->reserved_space);
 
@@ -1311,12 +1303,6 @@ pg_get_shmem_allocations(PG_FUNCTION_ARGS)
 		 * the segment.
 		 */
 		named_allocated += ent->reserved_space;
-#else
-		values[4] = Int64GetDatum(0);
-		values[5] = Int64GetDatum(ent->allocated_size);
-
-		named_allocated += ent->allocated_size;
-#endif
 
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
 							 values, nulls);
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 3d5aceba59c..f0efbf2aec1 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -89,10 +89,8 @@ extern PGShmemHeader *PGSharedMemoryCreate(Size size,
 										   PGShmemHeader **shim);
 extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2);
 extern void PGSharedMemoryDetach(void);
-#ifdef HAVE_RESIZABLE_SHMEM
 extern void PGSharedMemoryEnsureFreed(void *addr, Size size);
 extern void PGSharedMemoryEnsureAllocated(void *addr, Size size);
-#endif
 extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags);
 extern Size GetOSPageSize(void);
 
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index f356027e500..8140a0255ae 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -57,8 +57,6 @@ typedef struct ShmemStructOpts
 	 */
 	size_t		alignment;
 
-#ifdef HAVE_RESIZABLE_SHMEM
-
 	/*
 	 * Maximum size this structure can grow upto in future. The memory is not
 	 * allocated right away but the corresponding address space is reserved so
@@ -68,7 +66,6 @@ typedef struct ShmemStructOpts
 	 * structures.
 	 */
 	ssize_t		maximum_size;
-#endif
 
 	/*
 	 * When the shmem area is initialized or attached to, pointer to it is
@@ -181,9 +178,7 @@ typedef struct ShmemCallbacks
 
 extern void RegisterShmemCallbacks(const ShmemCallbacks *callbacks);
 extern bool ShmemAddrIsValid(const void *addr);
-#ifdef HAVE_RESIZABLE_SHMEM
 extern void ShmemResizeStruct(const char *name, Size new_size);
-#endif
 
 /*
  * These macros provide syntactic sugar for calling the underlying functions
diff --git a/src/test/modules/resizable_shmem/resizable_shmem.c b/src/test/modules/resizable_shmem/resizable_shmem.c
index 66754582b32..fb3dfd64b4b 100644
--- a/src/test/modules/resizable_shmem/resizable_shmem.c
+++ b/src/test/modules/resizable_shmem/resizable_shmem.c
@@ -135,20 +135,24 @@ resizable_shmem_request(void *arg)
 {
 	Size		initial_size = add_size(offsetof(TestResizableShmemStruct, data),
 										mul_size(test_initial_entries, TEST_ENTRY_SIZE));
+
+/*
+ * Create resizable structure on the platforms which support it. Otherwise create
+ * as a fixed-size structure. Other way would be to conditionally include
+ * .maximum_size in the call to ShmemRequestStruct().
+ */
 #ifdef HAVE_RESIZABLE_SHMEM
 	Size		max_size = add_size(offsetof(TestResizableShmemStruct, data),
 									mul_size(test_max_entries, TEST_ENTRY_SIZE));
 
-	/* A preprocessor macro to conditionally include the maximum_size field. */
-#define MAXIMUM_SIZE_ARG		.maximum_size = max_size,
 #else
-#define MAXIMUM_SIZE_ARG
+	Size		max_size = 0;
 #endif
 
 	/* Register our resizable shared memory structure */
 	ShmemRequestStruct(.name = "resizable_shmem",
 					   .size = use_unknown_size ? SHMEM_ATTACH_UNKNOWN_SIZE : initial_size,
-					   MAXIMUM_SIZE_ARG
+					   .maximum_size = max_size,
 					   .ptr = (void **) &resizable_shmem,
 		);
 }
@@ -172,11 +176,14 @@ resizable_shmem_shmem_init(void *arg)
 /*
  * Resize the shared memory structure to accommodate the specified number of
  * entries.
+ *
+ * On the plaforms which do not support resizable shared memory,
+ * ShmemResizeStruct() will raise an error, so this function will fail if the
+ * caller tries to resize the structure.
  */
 Datum
 resizable_shmem_resize(PG_FUNCTION_ARGS)
 {
-#ifdef HAVE_RESIZABLE_SHMEM
 	int32		new_entries = PG_GETARG_INT32(0);
 	Size		new_size;
 
@@ -191,11 +198,6 @@ resizable_shmem_resize(PG_FUNCTION_ARGS)
 	resizable_shmem->num_entries = new_entries;
 
 	PG_RETURN_VOID();
-#else
-	ereport(ERROR,
-			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-			 errmsg("resizable shared memory is not supported on this platform")));
-#endif
 }
 
 /*
diff --git a/src/test/modules/test_shmem/test_shmem.c b/src/test/modules/test_shmem/test_shmem.c
index fc2fd67887f..0dd469891ee 100644
--- a/src/test/modules/test_shmem/test_shmem.c
+++ b/src/test/modules/test_shmem/test_shmem.c
@@ -108,14 +108,8 @@ PG_FUNCTION_INFO_V1(test_shmem_resize_fixed);
 Datum
 test_shmem_resize_fixed(PG_FUNCTION_ARGS)
 {
-#ifdef HAVE_RESIZABLE_SHMEM
 	int32		new_size = PG_GETARG_INT32(0);
 
 	ShmemResizeStruct("test_shmem area", new_size);
 	PG_RETURN_VOID();
-#else
-	ereport(ERROR,
-			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-			 errmsg("resizable shared memory is not supported on this platform")));
-#endif
 }
-- 
2.34.1

