Hi All, PFA two patches for $subject.
0001: Adds assertions to InitShmemAccess() and InitShmemAllocation which indicate the conditions, EXEC_BACKEND and IsUnderPostmaster, these functions are expected to be called. I found these annotations to be useful when modifying these functions to handle multiple Shmem segments required by buffer pool resizing project [1]. 0002: We use two different methods to pass ShmemIndex and ShmemLock respectively to new backends even though both the structures are allocated before creating named structures in the shared memory. This patch consistently uses the same method - passing via PGShmemHeader. Further the patch gets rid of InitShmemAllocation and moves that code inside InitShmemAccess() itself. Maybe that's overkill but at least we would be able to call InitShmemAllocation() from InitShmemAccess() and declare first as static within shmem.c. That way we avoid a minor risk of InitShmemAllocation() being called twice. We may achieve consistency by passing ShmemIndex through BackendParameter, but I haven't tried that. [1] https://www.postgresql.org/message-id/cnthxg2eekacrejyeonuhiaezc7vd7o2uowlsbenxqfkjwgvwj%40qgzu6eoqrglb -- Best Wishes, Ashutosh Bapat
From e5866917ec0236d6a74710c8762fecf54dbee52c Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Thu, 29 Jan 2026 11:16:45 +0530 Subject: [PATCH v20260129 1/2] Clarify Shmem access by Postmaster and standalone backends InitShmemAccess is called by a standbalone backend or the Postmaster. It is also called by other backends in EXEC_BACKEND case. InitShmemAllocation() is called only by the Postmaster. Add Asserts to document this fact. The code which creates ShmemIndex is already called only for the Postmaster or a standalone backend and is adequately documented. Rest of the code may be called by any backend. Author: Ashutosh Bapat <[email protected]> --- src/backend/storage/ipc/shmem.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 1b536363152..b997a043145 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -99,10 +99,19 @@ Datum pg_numa_available(PG_FUNCTION_ARGS); /* * InitShmemAccess() --- set up basic pointers to shared memory. + * + * In EXEC_BACKEND case, this function is called by the Postmaster as well as + * every backend to setup the shared memory access. In non-EXEC_BACKEND case, it + * is called only by a standalone backend or the Postmaster, who passes the + * setup to the child backends via fork(). */ void InitShmemAccess(PGShmemHeader *seghdr) { +#ifndef EXEC_BACKEND + Assert(!IsUnderPostmaster); +#endif + ShmemSegHdr = seghdr; ShmemBase = seghdr; ShmemEnd = (char *) ShmemBase + seghdr->totalsize; @@ -119,6 +128,7 @@ InitShmemAllocation(void) PGShmemHeader *shmhdr = ShmemSegHdr; char *aligned; + Assert(!IsUnderPostmaster); Assert(shmhdr != NULL); /* base-commit: 20a8f783e15c503125c2ed0ae890510879f62801 -- 2.34.1
From c9d9d267d40234f92b821a48bd43aaab4ad0ca2d Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Thu, 29 Jan 2026 13:58:38 +0530 Subject: [PATCH v20260129 2/2] Move shmem allocation lock into shared memory header The pointer to the shared memory index table is in the shared memory header. In EXEC_BACKEND case, the backends retrieve it from there during shmem access initialization. Shared memory lock is allocated even before that but is passed to the backends via BackendParameters. There is no explanation as to why this asymmetry exists. This commit makes the handling of shmem index and shmem lock consistent by moving the shmem allocation lock pointer into the shared memory header, so that backends can retrieve it from there. Author: Ashutosh Bapat <[email protected]> --- src/backend/postmaster/launch_backend.c | 5 -- src/backend/storage/ipc/ipci.c | 5 -- src/backend/storage/ipc/shmem.c | 67 ++++++++++++++----------- src/include/storage/pg_shmem.h | 2 + 4 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c index cea229ad6a4..6d857c30659 100644 --- a/src/backend/postmaster/launch_backend.c +++ b/src/backend/postmaster/launch_backend.c @@ -96,7 +96,6 @@ typedef struct HANDLE UsedShmemSegID; #endif void *UsedShmemSegAddr; - slock_t *ShmemLock; #ifdef USE_INJECTION_POINTS struct InjectionPointsCtl *ActiveInjectionPoints; #endif @@ -724,8 +723,6 @@ save_backend_variables(BackendParameters *param, param->UsedShmemSegID = UsedShmemSegID; param->UsedShmemSegAddr = UsedShmemSegAddr; - param->ShmemLock = ShmemLock; - #ifdef USE_INJECTION_POINTS param->ActiveInjectionPoints = ActiveInjectionPoints; #endif @@ -986,8 +983,6 @@ restore_backend_variables(BackendParameters *param) UsedShmemSegID = param->UsedShmemSegID; UsedShmemSegAddr = param->UsedShmemSegAddr; - ShmemLock = param->ShmemLock; - #ifdef USE_INJECTION_POINTS ActiveInjectionPoints = param->ActiveInjectionPoints; #endif diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 2a3dfedf7e9..a2ed8742c91 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -214,11 +214,6 @@ CreateSharedMemoryAndSemaphores(void) InitShmemAccess(seghdr); - /* - * Set up shared memory allocation mechanism - */ - InitShmemAllocation(); - /* Initialize subsystems */ CreateOrAttachShmemStructs(); diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index b997a043145..37a2555577b 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -104,6 +104,10 @@ Datum pg_numa_available(PG_FUNCTION_ARGS); * every backend to setup the shared memory access. In non-EXEC_BACKEND case, it * is called only by a standalone backend or the Postmaster, who passes the * setup to the child backends via fork(). + * + * Postmaster creates the lock used for shared memory allocations and saves it + * in the shared memory header, from where backends retrieve it in EXEC_BACKEND + * build. */ void InitShmemAccess(PGShmemHeader *seghdr) @@ -115,42 +119,45 @@ InitShmemAccess(PGShmemHeader *seghdr) ShmemSegHdr = seghdr; ShmemBase = seghdr; ShmemEnd = (char *) ShmemBase + seghdr->totalsize; -} - -/* - * InitShmemAllocation() --- set up shared-memory space allocation. - * - * This should be called only in the postmaster or a standalone backend. - */ -void -InitShmemAllocation(void) -{ - PGShmemHeader *shmhdr = ShmemSegHdr; - char *aligned; - - Assert(!IsUnderPostmaster); - Assert(shmhdr != NULL); /* - * Initialize the spinlock used by ShmemAlloc. We must use - * ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet. + * Postmaster create the shared memory lock after setting up access to the + * shared memory but backends setup shmem lock from the shared memory + * header */ - ShmemLock = (slock_t *) ShmemAllocUnlocked(sizeof(slock_t)); + if (IsUnderPostmaster) + { + Assert(seghdr->shmem_lock); + ShmemLock = seghdr->shmem_lock; - SpinLockInit(ShmemLock); + /* ShmemIndex will be setup later. */ + } + else + { + char *aligned; - /* - * Allocations after this point should go through ShmemAlloc, which - * expects to allocate everything on cache line boundaries. Make sure the - * first allocation begins on a cache line boundary. - */ - aligned = (char *) - (CACHELINEALIGN((((char *) shmhdr) + shmhdr->freeoffset))); - shmhdr->freeoffset = aligned - (char *) shmhdr; + /* + * Initialize the spinlock used by ShmemAlloc. We must use + * ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet. + */ + ShmemLock = (slock_t *) ShmemAllocUnlocked(sizeof(slock_t)); + seghdr->shmem_lock = ShmemLock; - /* ShmemIndex can't be set up yet (need LWLocks first) */ - shmhdr->index = NULL; - ShmemIndex = (HTAB *) NULL; + SpinLockInit(ShmemLock); + + /* + * Allocations after this point should go through ShmemAlloc, which + * expects to allocate everything on cache line boundaries. Make sure + * the first allocation begins on a cache line boundary. + */ + aligned = (char *) + (CACHELINEALIGN((((char *) seghdr) + seghdr->freeoffset))); + seghdr->freeoffset = aligned - (char *) seghdr; + + /* ShmemIndex can't be set up yet (need LWLocks first) */ + seghdr->index = NULL; + ShmemIndex = (HTAB *) NULL; + } } /* diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index 3aeada554b2..ec1818b9aec 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -25,6 +25,7 @@ #define PG_SHMEM_H #include "storage/dsm_impl.h" +#include "storage/s_lock.h" typedef struct PGShmemHeader /* standard header for all Postgres shmem */ { @@ -35,6 +36,7 @@ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ Size freeoffset; /* offset to first free space */ dsm_handle dsm_control; /* ID of dynamic shared memory control seg */ void *index; /* pointer to ShmemIndex table */ + slock_t *shmem_lock; /* spinlock for shmem allocation */ #ifndef WIN32 /* Windows doesn't have useful inode#s */ dev_t device; /* device data directory is on */ ino_t inode; /* inode number of data directory */ -- 2.34.1
