From c18137939a0d2561fedc247a3f3135355923ffa8 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 13 Feb 2026 14:23:35 +0200 Subject: [PATCH 4/5] Refactor how some aux processes advertise their ProcNumber This moves the responsibility of setting the ProcGlobal->walrewriterProc and checkpointerProc fields to InitAuxiliaryProcess. Also switch to the same pattern to advertise the autovacuum launcher's ProcNumber, replacing the ad hoc av_launcherpid field in shared memory. This can easily be extended to other aux processes in the future, if other processes need to find them. Switch to pg_atomic_uint32 for the fields. Seems easier to reason about than volatile pointers. There was some precedence for that, as were already using pg_atomic_uint32 for the procArrayGroupFirst and clogGroupFirst fields, which also store ProcNumbers. TODO: could also replace WalRecv->procno with this --- src/backend/access/transam/xlog.c | 3 +-- src/backend/postmaster/autovacuum.c | 19 +++++++++-------- src/backend/postmaster/checkpointer.c | 14 ++++--------- src/backend/postmaster/walwriter.c | 6 ------ src/backend/storage/lmgr/proc.c | 30 +++++++++++++++++++++++++-- src/include/storage/proc.h | 7 ++++--- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 13ec6225b85..8e2e4659974 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2653,8 +2653,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN) if (wakeup) { - volatile PROC_HDR *procglobal = ProcGlobal; - ProcNumber walwriterProc = procglobal->walwriterProc; + ProcNumber walwriterProc = pg_atomic_read_u32(&ProcGlobal->walwriterProc); if (walwriterProc != INVALID_PROC_NUMBER) SetLatch(&GetPGProcByNumber(walwriterProc)->procLatch); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 89c2b4f9500..0a730fb5b45 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -277,7 +277,6 @@ typedef struct AutoVacuumWorkItem * struct and the array of WorkerInfo structs. This struct keeps: * * av_signal set by other processes to indicate various conditions - * av_launcherpid the PID of the autovacuum launcher * av_freeWorkers the WorkerInfo freelist * av_runningWorkers the WorkerInfo non-free queue * av_startingWorker pointer to WorkerInfo currently being started (cleared by @@ -293,7 +292,6 @@ typedef struct AutoVacuumWorkItem typedef struct { sig_atomic_t av_signal[AutoVacNumSignals]; - pid_t av_launcherpid; dclist_head av_freeWorkers; dlist_head av_runningWorkers; WorkerInfo av_startingWorker; @@ -563,8 +561,6 @@ AutoVacLauncherMain(const void *startup_data, size_t startup_data_len) proc_exit(0); /* done */ } - AutoVacuumShmem->av_launcherpid = MyProcPid; - /* * Create the initial database list. The invariant we want this list to * keep is that it's ordered by decreasing next_worker. As soon as an @@ -798,8 +794,6 @@ AutoVacLauncherShutdown(void) { ereport(DEBUG1, (errmsg_internal("autovacuum launcher shutting down"))); - AutoVacuumShmem->av_launcherpid = 0; - proc_exit(0); /* done */ } @@ -1529,6 +1523,8 @@ AutoVacWorkerMain(const void *startup_data, size_t startup_data_len) */ if (AutoVacuumShmem->av_startingWorker != NULL) { + ProcNumber launcherProc; + MyWorkerInfo = AutoVacuumShmem->av_startingWorker; dbid = MyWorkerInfo->wi_dboid; MyWorkerInfo->wi_proc = MyProc; @@ -1547,8 +1543,14 @@ AutoVacWorkerMain(const void *startup_data, size_t startup_data_len) on_shmem_exit(FreeWorkerInfo, 0); /* wake up the launcher */ - if (AutoVacuumShmem->av_launcherpid != 0) - kill(AutoVacuumShmem->av_launcherpid, SIGUSR2); + launcherProc = pg_atomic_read_u32(&ProcGlobal->avLauncherProc); + if (launcherProc != INVALID_PROC_NUMBER) + { + int pid = GetPGProcByNumber(launcherProc)->pid; + + if (pid != 0) + kill(pid, SIGUSR2); + } } else { @@ -3391,7 +3393,6 @@ AutoVacuumShmemInit(void) Assert(!found); - AutoVacuumShmem->av_launcherpid = 0; dclist_init(&AutoVacuumShmem->av_freeWorkers); dlist_init(&AutoVacuumShmem->av_runningWorkers); AutoVacuumShmem->av_startingWorker = NULL; diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 03aefa5b670..978a7d0e649 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -47,6 +47,7 @@ #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" +#include "port/atomics.h" #include "postmaster/auxprocess.h" #include "postmaster/bgwriter.h" #include "postmaster/interrupt.h" @@ -343,12 +344,6 @@ CheckpointerMain(const void *startup_data, size_t startup_data_len) */ UpdateSharedMemoryConfig(); - /* - * Advertise our proc number that backends can use to wake us up while - * we're sleeping. - */ - ProcGlobal->checkpointerProc = MyProcNumber; - /* * Loop until we've been asked to write the shutdown checkpoint or * terminate. @@ -1120,7 +1115,7 @@ RequestCheckpoint(int flags) for (ntries = 0;; ntries++) { volatile PROC_HDR *procglobal = ProcGlobal; - ProcNumber checkpointerProc = procglobal->checkpointerProc; + ProcNumber checkpointerProc = pg_atomic_read_u32(&procglobal->checkpointerProc); if (checkpointerProc == INVALID_PROC_NUMBER) { @@ -1261,8 +1256,7 @@ ForwardSyncRequest(const FileTag *ftag, SyncRequestType type) /* ... but not till after we release the lock */ if (too_full) { - volatile PROC_HDR *procglobal = ProcGlobal; - ProcNumber checkpointerProc = procglobal->checkpointerProc; + ProcNumber checkpointerProc = pg_atomic_read_u32(&ProcGlobal->checkpointerProc); if (checkpointerProc != INVALID_PROC_NUMBER) SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch); @@ -1543,7 +1537,7 @@ void WakeupCheckpointer(void) { volatile PROC_HDR *procglobal = ProcGlobal; - ProcNumber checkpointerProc = procglobal->checkpointerProc; + ProcNumber checkpointerProc = pg_atomic_read_u32(&procglobal->checkpointerProc); if (checkpointerProc != INVALID_PROC_NUMBER) SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch); diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 8ca7b07e947..1851417ad1b 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -200,12 +200,6 @@ WalWriterMain(const void *startup_data, size_t startup_data_len) hibernating = false; SetWalWriterSleeping(false); - /* - * Advertise our proc number that backends can use to wake us up while - * we're sleeping. - */ - ProcGlobal->walwriterProc = MyProcNumber; - /* * Loop forever */ diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index fd8318bdf3d..ba7eaed1a13 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -211,8 +211,9 @@ InitProcGlobal(void) dlist_init(&ProcGlobal->bgworkerFreeProcs); dlist_init(&ProcGlobal->walsenderFreeProcs); ProcGlobal->startupBufferPinWaitBufId = -1; - ProcGlobal->walwriterProc = INVALID_PROC_NUMBER; - ProcGlobal->checkpointerProc = INVALID_PROC_NUMBER; + pg_atomic_init_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER); + pg_atomic_init_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER); + pg_atomic_init_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER); pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER); pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); @@ -709,6 +710,14 @@ InitAuxiliaryProcess(void) */ PGSemaphoreReset(MyProc->sem); + /* Some aux processes are also advertised in ProcGlobal */ + if (MyBackendType == B_AUTOVAC_LAUNCHER) + pg_atomic_write_u32(&ProcGlobal->avLauncherProc, MyProcNumber); + if (MyBackendType == B_WAL_WRITER) + pg_atomic_write_u32(&ProcGlobal->walwriterProc, MyProcNumber); + if (MyBackendType == B_CHECKPOINTER) + pg_atomic_write_u32(&ProcGlobal->checkpointerProc, MyProcNumber); + /* * Arrange to clean up at process exit. */ @@ -1053,6 +1062,23 @@ AuxiliaryProcKill(int code, Datum arg) SwitchBackToLocalLatch(); pgstat_reset_wait_event_storage(); + /* If this was one of aux processes advertised in ProcGlobal, clear it */ + if (MyBackendType == B_AUTOVAC_LAUNCHER) + { + Assert(pg_atomic_read_u32(&ProcGlobal->avLauncherProc) == MyProcNumber); + pg_atomic_write_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER); + } + if (MyBackendType == B_WAL_WRITER) + { + Assert(pg_atomic_read_u32(&ProcGlobal->walwriterProc) == MyProcNumber); + pg_atomic_write_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER); + } + if (MyBackendType == B_CHECKPOINTER) + { + Assert(pg_atomic_read_u32(&ProcGlobal->checkpointerProc) == MyProcNumber); + pg_atomic_write_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER); + } + proc = MyProc; MyProc = NULL; MyProcNumber = INVALID_PROC_NUMBER; diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 23e5cd98161..1f1ab7d02ca 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -445,11 +445,12 @@ typedef struct PROC_HDR pg_atomic_uint32 clogGroupFirst; /* - * Current slot numbers of some auxiliary processes. There can be only one + * Current proc numbers of some auxiliary processes. There can be only one * of each of these running at a time. */ - ProcNumber walwriterProc; - ProcNumber checkpointerProc; + pg_atomic_uint32 avLauncherProc; + pg_atomic_uint32 walwriterProc; + pg_atomic_uint32 checkpointerProc; /* Current shared estimate of appropriate spins_per_delay value */ int spins_per_delay; -- 2.47.3