From 69d903367cdea188bf865f4edd72a186cda9e689 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sun, 3 Dec 2023 16:09:42 +0200 Subject: [PATCH] Refactor CreateSharedMemoryAndSemaphores For clarity, have separate functions for *creating* the shared memory and semaphores at postmaster or single-user backend startup, and for *attaching* to existing shared memory structures in EXEC_BACKEND case. CreateSharedMemoryAndSemaphores() is now called only at postmaster startup, and a new AttachSharedMemoryStructs() function is called at backend startup in EXEC_BACKEND mode. Reviewed-by: Tristan Partin, Andres Freund Discussion: https://www.postgresql.org/message-id/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef@iki.fi --- src/backend/postmaster/postmaster.c | 20 +-- src/backend/replication/walreceiver.c | 3 +- src/backend/storage/ipc/ipci.c | 178 +++++++++++++++----------- src/backend/storage/lmgr/proc.c | 2 +- src/include/storage/ipc.h | 3 + 5 files changed, 117 insertions(+), 89 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index ccc12f91a1..39fdcff3e2 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4917,11 +4917,11 @@ SubPostmasterMain(int argc, char *argv[]) /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + /* Need a PGPROC to run AttachSharedMemoryStructs */ InitProcess(); /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); + AttachSharedMemoryStructs(); /* And run the backend */ BackendRun(&port); /* does not return */ @@ -4935,11 +4935,11 @@ SubPostmasterMain(int argc, char *argv[]) /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + /* Need a PGPROC to run AttachSharedMemoryStructs */ InitAuxiliaryProcess(); /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); + AttachSharedMemoryStructs(); auxtype = atoi(argv[3]); AuxiliaryProcessMain(auxtype); /* does not return */ @@ -4949,11 +4949,11 @@ SubPostmasterMain(int argc, char *argv[]) /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + /* Need a PGPROC to run AttachSharedMemoryStructs */ InitProcess(); /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); + AttachSharedMemoryStructs(); AutoVacLauncherMain(argc - 2, argv + 2); /* does not return */ } @@ -4962,11 +4962,11 @@ SubPostmasterMain(int argc, char *argv[]) /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + /* Need a PGPROC to run AttachSharedMemoryStructs */ InitProcess(); /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); + AttachSharedMemoryStructs(); AutoVacWorkerMain(argc - 2, argv + 2); /* does not return */ } @@ -4980,11 +4980,11 @@ SubPostmasterMain(int argc, char *argv[]) /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + /* Need a PGPROC to run AttachSharedMemoryStructs */ InitProcess(); /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); + AttachSharedMemoryStructs(); /* Fetch MyBgworkerEntry from shared memory */ shmem_slot = atoi(argv[1] + 15); diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 2398167f49..26ded928a7 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -193,7 +193,7 @@ WalReceiverMain(void) TimeLineID startpointTLI; TimeLineID primaryTLI; bool first_stream; - WalRcvData *walrcv = WalRcv; + WalRcvData *walrcv; TimestampTz now; char *err; char *sender_host = NULL; @@ -203,6 +203,7 @@ WalReceiverMain(void) * WalRcv should be set up already (if we are a backend, we inherit this * by fork() or EXEC_BACKEND mechanism from the postmaster). */ + walrcv = WalRcv; Assert(walrcv != NULL); /* diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index a3d8eacb8d..2225a4a6e6 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -58,6 +58,8 @@ shmem_startup_hook_type shmem_startup_hook = NULL; static Size total_addin_request = 0; +static void CreateOrAttachShmemStructs(void); + /* * RequestAddinShmemSpace * Request that extra shmem space be allocated for use by @@ -156,9 +158,106 @@ CalculateShmemSize(int *num_semaphores) return size; } +#ifdef EXEC_BACKEND +/* + * AttachSharedMemoryStructs + * Initialize a postmaster child process's access to shared memory + * structures. + * + * In !EXEC_BACKEND mode, we inherit everything through the fork, and this + * isn't needed. + */ +void +AttachSharedMemoryStructs(void) +{ + /* InitProcess must've been called already */ + Assert(MyProc != NULL); + Assert(IsUnderPostmaster); + + CreateOrAttachShmemStructs(); + + /* + * Now give loadable modules a chance to set up their shmem allocations + */ + if (shmem_startup_hook) + shmem_startup_hook(); +} +#endif + /* * CreateSharedMemoryAndSemaphores * Creates and initializes shared memory and semaphores. + */ +void +CreateSharedMemoryAndSemaphores(void) +{ + PGShmemHeader *shim; + PGShmemHeader *seghdr; + Size size; + int numSemas; + + Assert(!IsUnderPostmaster); + + /* Compute the size of the shared-memory block */ + size = CalculateShmemSize(&numSemas); + elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size); + + /* + * Create the shmem segment + */ + seghdr = PGSharedMemoryCreate(size, &shim); + + /* + * Make sure that huge pages are never reported as "unknown" while the + * server is running. + */ + Assert(strcmp("unknown", + GetConfigOption("huge_pages_status", false, false)) != 0); + + InitShmemAccess(seghdr); + + /* + * Create semaphores + */ + PGReserveSemaphores(numSemas); + + /* + * If spinlocks are disabled, initialize emulation layer (which depends on + * semaphores, so the order is important here). + */ +#ifndef HAVE_SPINLOCKS + SpinlockSemaInit(); +#endif + + /* + * Set up shared memory allocation mechanism + */ + InitShmemAllocation(); + + /* Initialize subsystems */ + CreateOrAttachShmemStructs(); + +#ifdef EXEC_BACKEND + + /* + * Alloc the win32 shared backend array + */ + ShmemBackendArrayAllocation(); +#endif + + /* Initialize dynamic shared memory facilities. */ + dsm_postmaster_startup(shim); + + /* + * Now give loadable modules a chance to set up their shmem allocations + */ + if (shmem_startup_hook) + shmem_startup_hook(); +} + +/* + * Initialize various subsystems, setting up their data structures in + * shared memory. * * This is called by the postmaster or by a standalone backend. * It is also called by a backend forked from the postmaster in the @@ -171,65 +270,9 @@ CalculateShmemSize(int *num_semaphores) * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case. * This is a bit code-wasteful and could be cleaned up.) */ -void -CreateSharedMemoryAndSemaphores(void) +static void +CreateOrAttachShmemStructs(void) { - PGShmemHeader *shim = NULL; - - if (!IsUnderPostmaster) - { - PGShmemHeader *seghdr; - Size size; - int numSemas; - - /* Compute the size of the shared-memory block */ - size = CalculateShmemSize(&numSemas); - elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size); - - /* - * Create the shmem segment - */ - seghdr = PGSharedMemoryCreate(size, &shim); - - /* - * Make sure that huge pages are never reported as "unknown" while the - * server is running. - */ - Assert(strcmp("unknown", - GetConfigOption("huge_pages_status", false, false)) != 0); - - InitShmemAccess(seghdr); - - /* - * Create semaphores - */ - PGReserveSemaphores(numSemas); - - /* - * If spinlocks are disabled, initialize emulation layer (which - * depends on semaphores, so the order is important here). - */ -#ifndef HAVE_SPINLOCKS - SpinlockSemaInit(); -#endif - } - else - { - /* - * We are reattaching to an existing shared memory segment. This - * should only be reached in the EXEC_BACKEND case. - */ -#ifndef EXEC_BACKEND - elog(PANIC, "should be attached to shared memory already"); -#endif - } - - /* - * Set up shared memory allocation mechanism - */ - if (!IsUnderPostmaster) - InitShmemAllocation(); - /* * Now initialize LWLocks, which do shared memory allocation and are * needed for InitShmemIndex. @@ -302,25 +345,6 @@ CreateSharedMemoryAndSemaphores(void) AsyncShmemInit(); StatsShmemInit(); WaitEventExtensionShmemInit(); - -#ifdef EXEC_BACKEND - - /* - * Alloc the win32 shared backend array - */ - if (!IsUnderPostmaster) - ShmemBackendArrayAllocation(); -#endif - - /* Initialize dynamic shared memory facilities. */ - if (!IsUnderPostmaster) - dsm_postmaster_startup(shim); - - /* - * Now give loadable modules a chance to set up their shmem allocations - */ - if (shmem_startup_hook) - shmem_startup_hook(); } /* diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 01f7019b10..6648c6e5e7 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -468,7 +468,7 @@ InitProcess(void) * * This is separate from InitProcess because we can't acquire LWLocks until * we've created a PGPROC, but in the EXEC_BACKEND case ProcArrayAdd won't - * work until after we've done CreateSharedMemoryAndSemaphores. + * work until after we've done AttachSharedMemoryStructs. */ void InitProcessPhase2(void) diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 888c08b306..e282dcad96 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -79,6 +79,9 @@ extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook; extern Size CalculateShmemSize(int *num_semaphores); extern void CreateSharedMemoryAndSemaphores(void); +#ifdef EXEC_BACKEND +extern void AttachSharedMemoryStructs(void); +#endif extern void InitializeShmemGUCs(void); #endif /* IPC_H */