From fc52f52b32c24b0ba8facfdc5f6b2824a51ab558 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 13 Feb 2026 14:23:35 +0200 Subject: [PATCH v12a 1/4] 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/include/storage/proc.h | 7 ++++--- 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 +++++++++++++++++++++++++-- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 3f89450c216..4a1fafb9038 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -488,11 +488,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; diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index b9b678f3722..0b5ad4dc79c 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2637,8 +2637,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 695e187ba11..74574e1eaf9 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -278,7 +278,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 @@ -294,7 +293,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; @@ -565,8 +563,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 @@ -800,8 +796,6 @@ AutoVacLauncherShutdown(void) { ereport(DEBUG1, (errmsg_internal("autovacuum launcher shutting down"))); - AutoVacuumShmem->av_launcherpid = 0; - proc_exit(0); /* done */ } @@ -1532,6 +1526,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; @@ -1550,8 +1546,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 { @@ -3394,7 +3396,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 3c982c6ffac..e4075265495 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" @@ -349,12 +350,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. @@ -1126,7 +1121,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) { @@ -1267,8 +1262,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); @@ -1549,7 +1543,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 9cd86ad7022..2c3b4f831aa 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -206,12 +206,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 daf70d9ce2a..2c241cb0244 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -212,8 +212,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); @@ -712,6 +713,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. */ @@ -1056,6 +1065,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; -- 2.53.0.1.gb2826b52eb