From 1dd76ab9bfadd070958a7c077ebffb5dde0afbdc Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 27 Oct 2022 12:40:12 +1300 Subject: [PATCH v4 4/6] Use SetLatches() for SERIALIZABLE DEFERRABLE wakeups. Don't issue SetLatch()'s system call while holding a highly contended LWLock. Collect them in a LatchGroup to be set after the lock is released. Once woken, other backends will immediately try to acquire that lock anyway so it's better to wake after releasing. Take this opportunity to retire the confusingly named ProcSendSignal() and replace it with something that gives the latch pointer we need. There was only one other caller, in bufmgr.c, which is easily changed. Discussion: https://postgr.es/m/CA%2BhUKGKmO7ze0Z6WXKdrLxmvYa%3DzVGGXOO30MMktufofVwEm1A%40mail.gmail.com --- src/backend/storage/buffer/bufmgr.c | 2 +- src/backend/storage/ipc/procsignal.c | 2 -- src/backend/storage/lmgr/predicate.c | 5 ++++- src/backend/storage/lmgr/proc.c | 12 ------------ src/include/storage/proc.h | 4 +++- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index a7e3b9bb1d..de5908876d 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2449,7 +2449,7 @@ UnpinBuffer(BufferDesc *buf) buf_state &= ~BM_PIN_COUNT_WAITER; UnlockBufHdr(buf, buf_state); - ProcSendSignal(wait_backend_pgprocno); + SetLatch(GetProcLatchByNumber(wait_backend_pgprocno)); } else UnlockBufHdr(buf, buf_state); diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c85cb5cc18..ec4c3888b0 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -255,8 +255,6 @@ CleanupProcSignalState(int status, Datum arg) * * On success (a signal was sent), zero is returned. * On error, -1 is returned, and errno is set (typically to ESRCH or EPERM). - * - * Not to be confused with ProcSendSignal */ int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId) diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 1af41213b4..4d95ca94df 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -3249,6 +3249,7 @@ ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe) bool needToClear; SERIALIZABLEXACT *roXact; dlist_mutable_iter iter; + LatchGroup wakeups = {0}; /* * We can't trust XactReadOnly here, because a transaction which started @@ -3553,7 +3554,7 @@ ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe) */ if (SxactIsDeferrableWaiting(roXact) && (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact))) - ProcSendSignal(roXact->pgprocno); + AddLatch(&wakeups, GetProcLatchByNumber(roXact->pgprocno)); } } @@ -3583,6 +3584,8 @@ ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe) LWLockRelease(SerializableXactHashLock); + SetLatches(&wakeups); + LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE); /* Add this to the list of transactions to check for later cleanup. */ diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 5b663a2997..a71b34ba0b 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -1802,18 +1802,6 @@ ProcWaitForSignal(uint32 wait_event_info) CHECK_FOR_INTERRUPTS(); } -/* - * ProcSendSignal - set the latch of a backend identified by pgprocno - */ -void -ProcSendSignal(int pgprocno) -{ - if (pgprocno < 0 || pgprocno >= ProcGlobal->allProcCount) - elog(ERROR, "pgprocno out of range"); - - SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch); -} - /* * BecomeLockGroupLeader - designate process as lock group leader * diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index ef74f32693..56a31d2a89 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -413,6 +413,9 @@ extern PGDLLIMPORT PGPROC *PreparedXactProcs; /* Accessor for PGPROC given a pgprocno. */ #define GetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)]) +/* Accessor for procLatch given a pgprocno. */ +#define GetProcLatchByNumber(n) (&(GetPGProcByNumber(n))->procLatch) + /* * We set aside some extra PGPROC structures for auxiliary processes, * ie things that aren't full-fledged backends but need shmem access. @@ -456,7 +459,6 @@ extern bool IsWaitingForLock(void); extern void LockErrorCleanup(void); extern void ProcWaitForSignal(uint32 wait_event_info); -extern void ProcSendSignal(int pgprocno); extern PGPROC *AuxiliaryPidGetProc(int pid); -- 2.41.0