From 1c48b2d24460b288fe2c30d42d2cb00ecb5b2a59 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 26 Mar 2026 13:27:59 +0200
Subject: [PATCH v1 5/5] Move ShmemIndexLock into ShmemAllocator

This makes the lock available even before LWLockShmemInit() has been
called, removing the need to pass MainLWLockArray to child backends
via BackendParameters in EXEC_BACKEND mode.
---
 src/backend/postmaster/launch_backend.c       |  3 ---
 src/backend/storage/ipc/shmem.c               | 25 ++++++++++---------
 .../utils/activity/wait_event_names.txt       |  2 +-
 src/include/storage/lwlocklist.h              |  3 ++-
 4 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c
index 8aaf427df48..434e0643022 100644
--- a/src/backend/postmaster/launch_backend.c
+++ b/src/backend/postmaster/launch_backend.c
@@ -99,7 +99,6 @@ typedef struct
 #ifdef USE_INJECTION_POINTS
 	struct InjectionPointsCtl *ActiveInjectionPoints;
 #endif
-	LWLockPadded *MainLWLockArray;
 	PROC_HDR   *ProcGlobal;
 	PGPROC	   *AuxiliaryProcs;
 	PGPROC	   *PreparedXactProcs;
@@ -725,7 +724,6 @@ save_backend_variables(BackendParameters *param,
 	param->ActiveInjectionPoints = ActiveInjectionPoints;
 #endif
 
-	param->MainLWLockArray = MainLWLockArray;
 	param->ProcGlobal = ProcGlobal;
 	param->AuxiliaryProcs = AuxiliaryProcs;
 	param->PreparedXactProcs = PreparedXactProcs;
@@ -980,7 +978,6 @@ restore_backend_variables(BackendParameters *param)
 	ActiveInjectionPoints = param->ActiveInjectionPoints;
 #endif
 
-	MainLWLockArray = param->MainLWLockArray;
 	ProcGlobal = param->ProcGlobal;
 	AuxiliaryProcs = param->AuxiliaryProcs;
 	PreparedXactProcs = param->PreparedXactProcs;
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 339fbba3404..ec21eb4a191 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -90,12 +90,16 @@
 typedef struct ShmemAllocatorData
 {
 	Size		free_offset;	/* offset to first free space from ShmemBase */
-	HASHHDR    *index;			/* location of ShmemIndex */
 
-	/* protects shared memory and LWLock allocation */
+	/* protects 'free_offset' */
 	slock_t		shmem_lock;
+
+	HASHHDR    *index;			/* location of ShmemIndex */
+	LWLock		index_lock;
 } ShmemAllocatorData;
 
+#define ShmemIndexLock (&ShmemAllocator->index_lock)
+
 static void *ShmemAllocRaw(Size size, Size *allocated_size);
 
 /* shared memory global variables */
@@ -163,6 +167,8 @@ InitShmemAllocator(PGShmemHeader *seghdr)
 	{
 		SpinLockInit(&ShmemAllocator->shmem_lock);
 		ShmemAllocator->free_offset = offset;
+
+		LWLockInitialize(&ShmemAllocator->index_lock, LWTRANCHE_SHMEM_INDEX);
 	}
 
 	ShmemSegHdr = seghdr;
@@ -379,8 +385,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 
 	Assert(ShmemIndex != NULL);
 
-	if (IsUnderPostmaster)
-		LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
+	LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
 
 	/* look it up in the shmem index */
 	result = (ShmemIndexEnt *)
@@ -388,8 +393,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 
 	if (!result)
 	{
-		if (IsUnderPostmaster)
-			LWLockRelease(ShmemIndexLock);
+		LWLockRelease(ShmemIndexLock);
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("could not create ShmemIndex entry for data structure \"%s\"",
@@ -405,8 +409,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 		 */
 		if (result->size != size)
 		{
-			if (IsUnderPostmaster)
-				LWLockRelease(ShmemIndexLock);
+			LWLockRelease(ShmemIndexLock);
 			ereport(ERROR,
 					(errmsg("ShmemIndex entry size is wrong for data structure"
 							" \"%s\": expected %zu, actual %zu",
@@ -424,8 +427,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 		{
 			/* out of memory; remove the failed ShmemIndex entry */
 			hash_search(ShmemIndex, name, HASH_REMOVE, NULL);
-			if (IsUnderPostmaster)
-				LWLockRelease(ShmemIndexLock);
+			LWLockRelease(ShmemIndexLock);
 			ereport(ERROR,
 					(errcode(ERRCODE_OUT_OF_MEMORY),
 					 errmsg("not enough shared memory for data structure"
@@ -437,8 +439,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 		result->location = structPtr;
 	}
 
-	if (IsUnderPostmaster)
-		LWLockRelease(ShmemIndexLock);
+	LWLockRelease(ShmemIndexLock);
 
 	Assert(ShmemAddrIsValid(structPtr));
 
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 4aa864fe3c3..6be80d2daad 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -321,7 +321,6 @@ ABI_compatibility:
 
 Section: ClassName - WaitEventLWLock
 
-ShmemIndex	"Waiting to find or allocate space in shared memory."
 OidGen	"Waiting to allocate a new OID."
 XidGen	"Waiting to allocate a new transaction ID."
 ProcArray	"Waiting to access the shared per-process data structures (typically, to get a snapshot or report a session's transaction ID)."
@@ -412,6 +411,7 @@ SubtransSLRU	"Waiting to access the sub-transaction SLRU cache."
 XactSLRU	"Waiting to access the transaction status SLRU cache."
 ParallelVacuumDSA	"Waiting for parallel vacuum dynamic shared memory allocation."
 AioUringCompletion	"Waiting for another process to complete IO via io_uring."
+ShmemIndex	"Waiting to find or allocate space in shared memory."
 
 # No "ABI_compatibility" region here as WaitEventLWLock has its own C code.
 
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index e94ebce95b9..59ee097977d 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -32,7 +32,7 @@
  */
 
 /* 0 is available; was formerly BufFreelistLock */
-PG_LWLOCK(1, ShmemIndex)
+/* 1 was ShmemIndex */
 PG_LWLOCK(2, OidGen)
 PG_LWLOCK(3, XidGen)
 PG_LWLOCK(4, ProcArray)
@@ -137,3 +137,4 @@ PG_LWLOCKTRANCHE(SUBTRANS_SLRU, SubtransSLRU)
 PG_LWLOCKTRANCHE(XACT_SLRU, XactSLRU)
 PG_LWLOCKTRANCHE(PARALLEL_VACUUM_DSA, ParallelVacuumDSA)
 PG_LWLOCKTRANCHE(AIO_URING_COMPLETION, AioUringCompletion)
+PG_LWLOCKTRANCHE(SHMEM_INDEX, ShmemIndex)
-- 
2.47.3

