From 07377b5f6722dcfd60b91458ca03cef8a5230e4c Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Thu, 21 Aug 2025 11:56:09 +0530
Subject: [PATCH 09/19] Refactor CalculateShmemSize()

This function calls many functions which return the amount of shared
memory required for different shared memory data structures. Up until
now, the returned total of these sizes was used to create a single
shared memory segment. But starting the previous patch, we create
multiple shared memory segments each of which contain one shared memory
structure related to shared buffers and one main memory segment
containing rest of the structures. Since CalculateShmemSize() is called
for every shared memory segment, and its return value is added to the
memory required for all the shared memory segments, we end up allocating
more memory than required.

Instead, CalculateShmemSize() is called only once. Each of its callees
are expected to a. return the size required from the main segment b. add
sizes to the AnonymousMappings corresponding to the other memory
segments.

For individual modules to add memory to their respective
AnonymousMappings, we need to know the different mappings upfront. Hence
ANON_MAPPINGS replaces next_free_segment.

TODOs:

1. This change however requires that the AnonymousMappings array and
   macros defining identifiers of each of the segments be
platform-independent.  This patch doesn't achieve that goal for all the
platforms for example windows. We need to fix that.

2. If postgres is invoked with -C shared_memory_size, it reports 0.
   That's because it report the GUC values before share memory sizes are
set in AnonymousMappings. Fix that too.

3.  Eliminate this assymetry in CalculateShmemSize().  See TODO in
    prologue of CalculateShmemSize().

4. This is one way to avoid requesting more memory in each segment. But
   there may be other ways to design CalculateShmemSize(). Need to think
and implement it better.

Author: Ashutosh Bapat
---
 src/backend/port/sysv_shmem.c         | 48 ++++++--------------
 src/backend/port/win32_shmem.c        |  7 +--
 src/backend/postmaster/postmaster.c   | 14 +++---
 src/backend/storage/buffer/buf_init.c | 55 ++++++++---------------
 src/backend/storage/ipc/ipci.c        | 65 ++++++++++++++++++++++-----
 src/backend/storage/ipc/shmem.c       |  8 ++--
 src/backend/tcop/postgres.c           | 14 +++---
 src/include/storage/bufmgr.h          |  2 +-
 src/include/storage/ipc.h             |  2 +-
 src/include/storage/pg_shmem.h        | 17 ++++++-
 10 files changed, 125 insertions(+), 107 deletions(-)

diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index dac011b766b..b85911bdfc4 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -94,21 +94,7 @@ typedef enum
 unsigned long UsedShmemSegID = 0;
 void	   *UsedShmemSegAddr = NULL;
 
-typedef struct AnonymousMapping
-{
-	int shmem_segment;
-	Size shmem_size; 			/* Size of the actually used memory */
-	Size shmem_reserved; 		/* Size of the reserved mapping */
-	Pointer shmem; 				/* Pointer to the start of the mapped memory */
-	Pointer seg_addr; 			/* SysV shared memory for the header */
-	unsigned long seg_id; 		/* IPC key */
-	int segment_fd; 			/* fd for the backing anon file */
-} AnonymousMapping;
-
-static AnonymousMapping Mappings[ANON_MAPPINGS];
-
-/* Keeps track of used mapping segments */
-static int next_free_segment = 0;
+AnonymousMapping Mappings[ANON_MAPPINGS];
 
 /*
  * Anonymous mapping layout we use looks like this:
@@ -168,7 +154,7 @@ static IpcMemoryState PGSharedMemoryAttach(IpcMemoryId shmId,
 										   void *attachAt,
 										   PGShmemHeader **addr);
 
-static const char*
+const char*
 MappingName(int shmem_segment)
 {
 	switch (shmem_segment)
@@ -193,7 +179,7 @@ MappingName(int shmem_segment)
 static void
 DebugMappings()
 {
-	for(int i = 0; i < next_free_segment; i++)
+	for(int i = 0; i < ANON_MAPPINGS; i++)
 	{
 		AnonymousMapping m = Mappings[i];
 		elog(DEBUG1, "Mapping[%s]: addr %p, size %zu",
@@ -851,9 +837,6 @@ PrepareHugePages()
 {
 	void	   *ptr = MAP_FAILED;
 
-	/* Reset to handle reinitialization */
-	next_free_segment = 0;
-
 	/* Complain if hugepages demanded but we can't possibly support them */
 #if !defined(MAP_HUGETLB)
 	if (huge_pages == HUGE_PAGES_ON)
@@ -876,8 +859,7 @@ PrepareHugePages()
 		 */
 		for(int segment = 0; segment < ANON_MAPPINGS; segment++)
 		{
-			int	numSemas;
-			Size segment_size = CalculateShmemSize(&numSemas, segment);
+			Size segment_size = Mappings[segment].shmem_req_size;
 
 			if (segment_size % hugepagesize != 0)
 				segment_size += hugepagesize - (segment_size % hugepagesize);
@@ -909,7 +891,7 @@ PrepareHugePages()
 static void
 AnonymousShmemDetach(int status, Datum arg)
 {
-	for(int i = 0; i < next_free_segment; i++)
+	for(int i = 0; i < ANON_MAPPINGS; i++)
 	{
 		AnonymousMapping m = Mappings[i];
 
@@ -927,7 +909,7 @@ AnonymousShmemDetach(int status, Datum arg)
 /*
  * PGSharedMemoryCreate
  *
- * Create a shared memory segment of the given size and initialize its
+ * Create a shared memory segment for the given mapping and initialize its
  * standard header.  Also, register an on_shmem_exit callback to release
  * the storage.
  *
@@ -937,7 +919,7 @@ AnonymousShmemDetach(int status, Datum arg)
  * postmaster or backend.
  */
 PGShmemHeader *
-PGSharedMemoryCreate(Size size,
+PGSharedMemoryCreate(AnonymousMapping *mapping,
 					 PGShmemHeader **shim)
 {
 	IpcMemoryKey NextShmemSegID;
@@ -945,7 +927,6 @@ PGSharedMemoryCreate(Size size,
 	PGShmemHeader *hdr;
 	struct stat statbuf;
 	Size		sysvsize, total_reserved;
-	AnonymousMapping *mapping = &Mappings[next_free_segment];
 
 	/*
 	 * We use the data directory's ID info (inode and device numbers) to
@@ -965,13 +946,12 @@ PGSharedMemoryCreate(Size size,
 				 errmsg("huge pages not supported with the current \"shared_memory_type\" setting")));
 
 	/* Room for a header? */
-	Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
+	Assert(mapping->shmem_req_size > MAXALIGN(sizeof(PGShmemHeader)));
 
 	/* Prepare the mapping information */
-	mapping->shmem_size = size;
-	mapping->shmem_segment = next_free_segment;
+	mapping->shmem_size = mapping->shmem_req_size;
 	total_reserved = (Size) MaxAvailableMemory * BLCKSZ;
-	mapping->shmem_reserved = total_reserved * SHMEM_RESIZE_RATIO[next_free_segment];
+	mapping->shmem_reserved = total_reserved * SHMEM_RESIZE_RATIO[mapping->shmem_segment];
 
 	/* Round up to be a multiple of BLCKSZ */
 	mapping->shmem_reserved = mapping->shmem_reserved + BLCKSZ -
@@ -982,8 +962,6 @@ PGSharedMemoryCreate(Size size,
 		/* On success, mapping data will be modified. */
 		CreateAnonymousSegment(mapping);
 
-		next_free_segment++;
-
 		/* Register on-exit routine to unmap the anonymous segment */
 		on_shmem_exit(AnonymousShmemDetach, (Datum) 0);
 
@@ -992,7 +970,7 @@ PGSharedMemoryCreate(Size size,
 	}
 	else
 	{
-		sysvsize = size;
+		sysvsize = mapping->shmem_req_size;
 
 		/* huge pages are only available with mmap */
 		SetConfigOption("huge_pages_status", "off",
@@ -1005,7 +983,7 @@ PGSharedMemoryCreate(Size size,
 	 * loop simultaneously.  (CreateDataDirLockFile() does not entirely ensure
 	 * that, but prefer fixing it over coping here.)
 	 */
-	NextShmemSegID = statbuf.st_ino + next_free_segment;
+	NextShmemSegID = statbuf.st_ino + mapping->shmem_segment;
 
 	for (;;)
 	{
@@ -1214,7 +1192,7 @@ PGSharedMemoryNoReAttach(void)
 void
 PGSharedMemoryDetach(void)
 {
-	for(int i = 0; i < next_free_segment; i++)
+	for(int i = 0; i < ANON_MAPPINGS; i++)
 	{
 		AnonymousMapping m = Mappings[i];
 
diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index 732fedee87e..1db07ff65d3 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -204,7 +204,7 @@ EnableLockPagesPrivilege(int elevel)
  * standard header.
  */
 PGShmemHeader *
-PGSharedMemoryCreate(Size size,
+PGSharedMemoryCreate(AnonymousMapping *mapping,
 					 PGShmemHeader **shim)
 {
 	void	   *memAddress;
@@ -216,7 +216,7 @@ PGSharedMemoryCreate(Size size,
 	DWORD		size_high;
 	DWORD		size_low;
 	SIZE_T		largePageSize = 0;
-	Size		orig_size = size;
+	Size		size = mapping->shmem_req_size;
 	DWORD		flProtect = PAGE_READWRITE;
 	DWORD		desiredAccess;
 
@@ -304,7 +304,7 @@ retry:
 				 * Use the original size, not the rounded-up value, when
 				 * falling back to non-huge pages.
 				 */
-				size = orig_size;
+				size = mapping->shmem_req_size;
 				flProtect = PAGE_READWRITE;
 				goto retry;
 			}
@@ -391,6 +391,7 @@ retry:
 	hdr->totalsize = size;
 	hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
 	hdr->dsm_control = 0;
+	mapping->shmem_size = size;
 
 	/* Save info for possible future use */
 	UsedShmemSegAddr = memAddress;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index e1d643b013d..b59d20b4ac2 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -963,13 +963,6 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	process_shmem_requests();
 
-	/*
-	 * Now that loadable modules have had their chance to request additional
-	 * shared memory, determine the value of any runtime-computed GUCs that
-	 * depend on the amount of shared memory required.
-	 */
-	InitializeShmemGUCs();
-
 	/*
 	 * Now that modules have been loaded, we can process any custom resource
 	 * managers specified in the wal_consistency_checking GUC.
@@ -1005,6 +998,13 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	CreateSharedMemoryAndSemaphores();
 
+	/*
+	 * Now that loadable modules have had their chance to request additional
+	 * shared memory, determine the value of any runtime-computed GUCs that
+	 * depend on the amount of shared memory required.
+	 */
+	InitializeShmemGUCs();
+
 	/*
 	 * Estimate number of openable files.  This must happen after setting up
 	 * semaphores, because on some platforms semaphores count as open files.
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 6d703e18f8b..6f148d1d80b 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -158,48 +158,31 @@ BufferManagerShmemInit(void)
  * data.
  */
 Size
-BufferManagerShmemSize(int shmem_segment)
+BufferManagerShmemSize(void)
 {
-	Size		size = 0;
+	size_t size;
 
-	if (shmem_segment == MAIN_SHMEM_SEGMENT)
-		return size;
+	/* size of buffer descriptors, plus alignment padding */
+	size = add_size(0, mul_size(NBuffers, sizeof(BufferDescPadded)));
+	size = add_size(size, PG_CACHE_LINE_SIZE);
+	Mappings[BUFFER_DESCRIPTORS_SHMEM_SEGMENT].shmem_req_size = size;
 
-	if (shmem_segment == BUFFER_DESCRIPTORS_SHMEM_SEGMENT)
-	{
-		/* size of buffer descriptors */
-		size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
-		/* to allow aligning buffer descriptors */
-		size = add_size(size, PG_CACHE_LINE_SIZE);
-	}
+	/* size of data pages, plus alignment padding */
+	size = add_size(0, PG_IO_ALIGN_SIZE);
+	size = add_size(size, mul_size(NBuffers, BLCKSZ));
+	Mappings[BUFFERS_SHMEM_SEGMENT].shmem_req_size = size;
 
-	if (shmem_segment == BUFFERS_SHMEM_SEGMENT)
-	{
-		/* size of data pages, plus alignment padding */
-		size = add_size(size, PG_IO_ALIGN_SIZE);
-		size = add_size(size, mul_size(NBuffers, BLCKSZ));
-	}
+	/* size of stuff controlled by freelist.c */
+	Mappings[STRATEGY_SHMEM_SEGMENT].shmem_req_size = StrategyShmemSize();
 
-	if (shmem_segment == STRATEGY_SHMEM_SEGMENT)
-	{
-		/* size of stuff controlled by freelist.c */
-		size = add_size(size, StrategyShmemSize());
-	}
+	/* size of I/O condition variables, plus alignment padding */
+	size = add_size(0, mul_size(NBuffers,
+								   sizeof(ConditionVariableMinimallyPadded)));
+	size = add_size(size, PG_CACHE_LINE_SIZE);
+	Mappings[BUFFER_IOCV_SHMEM_SEGMENT].shmem_req_size = size;
 
-	if (shmem_segment == BUFFER_IOCV_SHMEM_SEGMENT)
-	{
-		/* size of I/O condition variables */
-		size = add_size(size, mul_size(NBuffers,
-									   sizeof(ConditionVariableMinimallyPadded)));
-		/* to allow aligning the above */
-		size = add_size(size, PG_CACHE_LINE_SIZE);
-	}
-
-	if (shmem_segment == CHECKPOINT_BUFFERS_SHMEM_SEGMENT)
-	{
-		/* size of checkpoint sort array in bufmgr.c */
-		size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
-	}
+	/* size of checkpoint sort array in bufmgr.c */
+	Mappings[CHECKPOINT_BUFFERS_SHMEM_SEGMENT].shmem_req_size = mul_size(NBuffers, sizeof(CkptSortItem));
 
 	return size;
 }
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 2dbd81afc87..2cd278449f0 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -84,9 +84,23 @@ RequestAddinShmemSpace(Size size)
  *
  * If num_semaphores is not NULL, it will be set to the number of semaphores
  * required.
+ * 
+ * TODO: Right now the minions of this function return the size of shared memory
+ * required in the main shared memory segment but add sizes required from other
+ * segments in the respective mappings. I think we should change this assymetry.
+ * It's only the buffer manager which adds sizes for other segments, but in
+ * future there may be others. Further the buffer manager related other segments
+ * are expected to hold only one resizable structure thus their size should be
+ * set only once when changing shared buffer pool size (i.e. when changin
+ * shared_buffers GUC). We shouldn't allow adding more structures to these
+ * segments, and thus restrict adding sizes to the corresponding mappings after
+ * the initial size is set.
+ * 
+ * TODO: Also we should do something about numSemas, which is not required
+ * everywhere CalculateShmemSize is called.
  */
 Size
-CalculateShmemSize(int *num_semaphores, int shmem_segment)
+CalculateShmemSize(int *num_semaphores)
 {
 	Size		size;
 	int			numSemas;
@@ -113,7 +127,13 @@ CalculateShmemSize(int *num_semaphores, int shmem_segment)
 											 sizeof(ShmemIndexEnt)));
 	size = add_size(size, dsm_estimate_size());
 	size = add_size(size, DSMRegistryShmemSize());
-	size = add_size(size, BufferManagerShmemSize(shmem_segment));
+
+	/*
+	 * Buffer manager adds estimates for memory requirements for every shared
+	 * memory segment that it uses in the corresponding AnonymousMappings.
+	 * Consider size required from only the main shared memory segment here.
+	 */
+	size = add_size(size, BufferManagerShmemSize());
 	size = add_size(size, LockManagerShmemSize());
 	size = add_size(size, PredicateLockShmemSize());
 	size = add_size(size, ProcGlobalShmemSize());
@@ -154,8 +174,15 @@ CalculateShmemSize(int *num_semaphores, int shmem_segment)
 	/* include additional requested shmem from preload libraries */
 	size = add_size(size, total_addin_request);
 
+	/*
+	 * All the shared memory allocations considered so far happen in the main
+	 * shared memory segment.
+	 */
+	Mappings[MAIN_SHMEM_SEGMENT].shmem_req_size = size;
+
 	/* might as well round it off to a multiple of a typical page size */
-	size = add_size(size, 8192 - (size % 8192));
+	for (int segment = 0; segment < ANON_MAPPINGS; segment++)
+		Mappings[segment].shmem_req_size = add_size(Mappings[segment].shmem_req_size, 8192 - (Mappings[segment].shmem_req_size % 8192));
 
 	return size;
 }
@@ -201,26 +228,30 @@ CreateSharedMemoryAndSemaphores(void)
 {
 	PGShmemHeader *shim;
 	PGShmemHeader *seghdr;
-	Size		size;
 	int			numSemas;
 
 	Assert(!IsUnderPostmaster);
 
+	CalculateShmemSize(&numSemas);
+
 	/* Decide if we use huge pages or regular size pages */
 	PrepareHugePages();
 
 	for(int segment = 0; segment < ANON_MAPPINGS; segment++)
 	{
+		AnonymousMapping *mapping = &Mappings[segment];
+
+		mapping->shmem_segment = segment;
+
 		/* Compute the size of the shared-memory block */
-		size = CalculateShmemSize(&numSemas, segment);
-		elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
+		elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", mapping->shmem_req_size);
 
 		/*
 		 * Create the shmem segment.
 		 *
 		 * XXX: Do multiple shims are needed, one per segment?
 		 */
-		seghdr = PGSharedMemoryCreate(size, &shim);
+		seghdr = PGSharedMemoryCreate(mapping, &shim);
 
 		/*
 		 * Make sure that huge pages are never reported as "unknown" while the
@@ -232,9 +263,13 @@ CreateSharedMemoryAndSemaphores(void)
 		InitShmemAccessInSegment(seghdr, segment);
 
 		/*
-		 * Create semaphores
+		 * Shared memory for semaphores is allocated in the main shared memory.
+		 * Hence they are allocated after the main segment is created. Patch
+		 * proposed at https://commitfest.postgresql.org/patch/5997/ simplifies
+		 * this.
 		 */
-		PGReserveSemaphores(numSemas, segment);
+		if (segment == MAIN_SHMEM_SEGMENT)
+			PGReserveSemaphores(numSemas, segment);
 
 		/*
 		 * Set up shared memory allocation mechanism
@@ -357,7 +392,9 @@ CreateOrAttachShmemStructs(void)
  * InitializeShmemGUCs
  *
  * This function initializes runtime-computed GUCs related to the amount of
- * shared memory required for the current configuration.
+ * shared memory required for the current configuration. It assumes that the
+ * memory required by the shared memory segments is already calculated and is
+ * available in AnonymousMappings.
  */
 void
 InitializeShmemGUCs(void)
@@ -366,12 +403,16 @@ InitializeShmemGUCs(void)
 	Size		size_b;
 	Size		size_mb;
 	Size		hp_size;
-	int			num_semas;
+	int			num_semas = ProcGlobalSemas();
+	int		i;
 
 	/*
 	 * Calculate the shared memory size and round up to the nearest megabyte.
 	 */
-	size_b = CalculateShmemSize(&num_semas, MAIN_SHMEM_SEGMENT);
+	size_b = 0;
+	for (i = 0; i < ANON_MAPPINGS; i++)
+		size_b = add_size(size_b, Mappings[i].shmem_req_size);
+
 	size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
 	sprintf(buf, "%zu", size_mb);
 	SetConfigOption("shared_memory_size", buf,
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index e6cb919f0fc..90c21a97225 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -178,8 +178,8 @@ ShmemAllocInSegment(Size size, int shmem_segment)
 	if (!newSpace)
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
-				 errmsg("out of shared memory (%zu bytes requested)",
-						size)));
+				 errmsg("out of shared memory in segment %s (%zu bytes requested)",
+					MappingName(shmem_segment), size)));
 	return newSpace;
 }
 
@@ -286,8 +286,8 @@ ShmemAllocUnlockedInSegment(Size size, int shmem_segment)
 	if (newFree > Segments[shmem_segment].ShmemSegHdr->totalsize)
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
-				 errmsg("out of shared memory (%zu bytes requested)",
-						size)));
+				 errmsg("out of shared memory in segment %s (%zu bytes requested)",
+						MappingName(shmem_segment), size)));
 	Segments[shmem_segment].ShmemSegHdr->freeoffset = newFree;
 
 	newSpace = (char *) Segments[shmem_segment].ShmemBase + newStart;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 193efeb9022..86ffe020c01 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -4133,13 +4133,6 @@ PostgresSingleUserMain(int argc, char *argv[],
 	 */
 	process_shmem_requests();
 
-	/*
-	 * Now that loadable modules have had their chance to request additional
-	 * shared memory, determine the value of any runtime-computed GUCs that
-	 * depend on the amount of shared memory required.
-	 */
-	InitializeShmemGUCs();
-
 	/*
 	 * Now that modules have been loaded, we can process any custom resource
 	 * managers specified in the wal_consistency_checking GUC.
@@ -4152,6 +4145,13 @@ PostgresSingleUserMain(int argc, char *argv[],
 	 */
 	CreateSharedMemoryAndSemaphores();
 
+	/*
+	 * Now that loadable modules have had their chance to request additional
+	 * shared memory, determine the value of any runtime-computed GUCs that
+	 * depend on the amount of shared memory required.
+	 */
+	InitializeShmemGUCs();
+
 	/*
 	 * Estimate number of openable files.  This must happen after setting up
 	 * semaphores, because on some platforms semaphores count as open files.
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index a222747b803..3f37b294af6 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -319,7 +319,7 @@ extern void EvictRelUnpinnedBuffers(Relation rel,
 
 /* in buf_init.c */
 extern void BufferManagerShmemInit(void);
-extern Size BufferManagerShmemSize(int);
+extern Size BufferManagerShmemSize(void);
 
 /* in localbuf.c */
 extern void AtProcExit_LocalBuffers(void);
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index 6ebda479ced..3baf418b3d1 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -77,7 +77,7 @@ extern void check_on_shmem_exit_lists_are_empty(void);
 /* ipci.c */
 extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook;
 
-extern Size CalculateShmemSize(int *num_semaphores, int shmem_segment);
+extern Size CalculateShmemSize(int *num_semaphores);
 extern void CreateSharedMemoryAndSemaphores(void);
 #ifdef EXEC_BACKEND
 extern void AttachSharedMemoryStructs(void);
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index a7b275b4db9..a1fa6b43fe3 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -27,6 +27,18 @@
 #include "storage/dsm_impl.h"
 #include "storage/spin.h"
 
+typedef struct AnonymousMapping
+{
+	int shmem_segment;			/* TODO: Do we really need it? */
+	Size shmem_req_size;		/* Required size of the segment */
+	Size shmem_size; 			/* Size of the actually used memory */
+	Size shmem_reserved; 		/* Size of the reserved mapping */
+	Pointer shmem; 				/* Pointer to the start of the mapped memory */
+	Pointer seg_addr; 			/* SysV shared memory for the header */
+	unsigned long seg_id; 		/* IPC key */
+	int segment_fd; 			/* fd for the backing anon file */
+} AnonymousMapping;
+
 typedef struct PGShmemHeader	/* standard header for all Postgres shmem */
 {
 	int32		magic;			/* magic # to identify Postgres segments */
@@ -55,6 +67,8 @@ typedef struct ShmemSegment
 #define ANON_MAPPINGS 6
 
 extern PGDLLIMPORT ShmemSegment Segments[ANON_MAPPINGS];
+extern PGDLLIMPORT AnonymousMapping Mappings[ANON_MAPPINGS];
+
 
 /* GUC variables */
 extern PGDLLIMPORT int shared_memory_type;
@@ -101,10 +115,11 @@ extern void PGSharedMemoryReAttach(void);
 extern void PGSharedMemoryNoReAttach(void);
 #endif
 
-extern PGShmemHeader *PGSharedMemoryCreate(Size size,
+extern PGShmemHeader *PGSharedMemoryCreate(AnonymousMapping *mapping,
 										   PGShmemHeader **shim);
 extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2);
 extern void PGSharedMemoryDetach(void);
+extern const char *MappingName(int shmem_segment);
 extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags,
 							int *memfd_flags);
 void PrepareHugePages(void);
-- 
2.34.1

