From 45696d8f2371cceca1e38719ef49036cdd67c250 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat 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