Change ProcSendSignal() to take pgprocno.
authorThomas Munro <tmunro@postgresql.org>
Wed, 15 Dec 2021 23:40:15 +0000 (12:40 +1300)
committerThomas Munro <tmunro@postgresql.org>
Thu, 16 Dec 2021 02:56:03 +0000 (15:56 +1300)
Instead of referring to target backends by pid, use pgprocno.  This
means that we don't have to scan the ProcArray and we can drop some
special case code for dealing with the startup process.

Discussion: https://postgr.es/m/CA%2BhUKGLYRyDaneEwz5Uya_OgFLMx5BgJfkQSD%3Dq9HmwsfRRb-w%40mail.gmail.com
Reviewed-by: Soumyadeep Chakraborty <soumyadeep2007@gmail.com>
Reviewed-by: Ashwin Agrawal <ashwinstar@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
src/backend/access/transam/xlog.c
src/backend/storage/buffer/buf_init.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/lmgr/predicate.c
src/backend/storage/lmgr/proc.c
src/include/storage/buf_internals.h
src/include/storage/predicate_internals.h
src/include/storage/proc.h

index 72aeb42961f1171e67ae7173caefb8769848f5ea..1e1fbe957faf3a5772c8844de1a14fa6edb915e6 100644 (file)
@@ -7519,9 +7519,6 @@ StartupXLOG(void)
        /* Also ensure XLogReceiptTime has a sane value */
        XLogReceiptTime = GetCurrentTimestamp();
 
-       /* Allow ProcSendSignal() to find us, for buffer pin wakeups. */
-       PublishStartupProcessInformation();
-
        /*
         * Let postmaster know we've started redo now, so that it can launch
         * the archiver if necessary.
index a299be1043059858d6981b5aa4530a81d4af5683..b9a83c0e9b99f0c5c272e287f1b1e5294687ff80 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "storage/buf_internals.h"
 #include "storage/bufmgr.h"
+#include "storage/proc.h"
 
 BufferDescPadded *BufferDescriptors;
 char      *BufferBlocks;
@@ -118,7 +119,7 @@ InitBufferPool(void)
            CLEAR_BUFFERTAG(buf->tag);
 
            pg_atomic_init_u32(&buf->state, 0);
-           buf->wait_backend_pid = 0;
+           buf->wait_backend_pgprocno = INVALID_PGPROCNO;
 
            buf->buf_id = i;
 
index 16de918e2e1fb9f37ba55f38e149c6f5a1f924ba..b4532948d3f2b19f68d82fb750b21f2efe873907 100644 (file)
@@ -1899,11 +1899,11 @@ UnpinBuffer(BufferDesc *buf, bool fixOwner)
                BUF_STATE_GET_REFCOUNT(buf_state) == 1)
            {
                /* we just released the last pin other than the waiter's */
-               int         wait_backend_pid = buf->wait_backend_pid;
+               int         wait_backend_pgprocno = buf->wait_backend_pgprocno;
 
                buf_state &= ~BM_PIN_COUNT_WAITER;
                UnlockBufHdr(buf, buf_state);
-               ProcSendSignal(wait_backend_pid);
+               ProcSendSignal(wait_backend_pgprocno);
            }
            else
                UnlockBufHdr(buf, buf_state);
@@ -3980,7 +3980,7 @@ UnlockBuffers(void)
         * got a cancel/die interrupt before getting the signal.
         */
        if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
-           buf->wait_backend_pid == MyProcPid)
+           buf->wait_backend_pgprocno == MyProc->pgprocno)
            buf_state &= ~BM_PIN_COUNT_WAITER;
 
        UnlockBufHdr(buf, buf_state);
@@ -4116,7 +4116,7 @@ LockBufferForCleanup(Buffer buffer)
            LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
            elog(ERROR, "multiple backends attempting to wait for pincount 1");
        }
-       bufHdr->wait_backend_pid = MyProcPid;
+       bufHdr->wait_backend_pgprocno = MyProc->pgprocno;
        PinCountWaitBuf = bufHdr;
        buf_state |= BM_PIN_COUNT_WAITER;
        UnlockBufHdr(bufHdr, buf_state);
@@ -4187,7 +4187,7 @@ LockBufferForCleanup(Buffer buffer)
         */
        buf_state = LockBufHdr(bufHdr);
        if ((buf_state & BM_PIN_COUNT_WAITER) != 0 &&
-           bufHdr->wait_backend_pid == MyProcPid)
+           bufHdr->wait_backend_pgprocno == MyProc->pgprocno)
            buf_state &= ~BM_PIN_COUNT_WAITER;
        UnlockBufHdr(bufHdr, buf_state);
 
index 56267bdc3ce325b20756ac1328396faf9c79fa48..4f4d5b0d20ffe87ab9ad22a871241d2131a5bb19 100644 (file)
@@ -1277,6 +1277,7 @@ InitPredicateLocks(void)
        PredXact->OldCommittedSxact->xmin = InvalidTransactionId;
        PredXact->OldCommittedSxact->flags = SXACT_FLAG_COMMITTED;
        PredXact->OldCommittedSxact->pid = 0;
+       PredXact->OldCommittedSxact->pgprocno = INVALID_PGPROCNO;
    }
    /* This never changes, so let's keep a local copy. */
    OldCommittedSxact = PredXact->OldCommittedSxact;
@@ -1876,6 +1877,7 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
    sxact->finishedBefore = InvalidTransactionId;
    sxact->xmin = snapshot->xmin;
    sxact->pid = MyProcPid;
+   sxact->pgprocno = MyProc->pgprocno;
    SHMQueueInit(&(sxact->predicateLocks));
    SHMQueueElemInit(&(sxact->finishedLink));
    sxact->flags = 0;
@@ -3669,7 +3671,7 @@ ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
             */
            if (SxactIsDeferrableWaiting(roXact) &&
                (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
-               ProcSendSignal(roXact->pid);
+               ProcSendSignal(roXact->pgprocno);
 
            possibleUnsafeConflict = nextConflict;
        }
@@ -5006,6 +5008,7 @@ PostPrepare_PredicateLocks(TransactionId xid)
    Assert(SxactIsPrepared(MySerializableXact));
 
    MySerializableXact->pid = 0;
+   MySerializableXact->pgprocno = INVALID_PGPROCNO;
 
    hash_destroy(LocalPredicateLockHash);
    LocalPredicateLockHash = NULL;
@@ -5081,6 +5084,7 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info,
        sxact->vxid.backendId = InvalidBackendId;
        sxact->vxid.localTransactionId = (LocalTransactionId) xid;
        sxact->pid = 0;
+       sxact->pgprocno = INVALID_PGPROCNO;
 
        /* a prepared xact hasn't committed yet */
        sxact->prepareSeqNo = RecoverySerCommitSeqNo;
index b7d9da0aa9f7f51b4d17e95893cc5380fa6dee3e..d1d3cd0dc885baa27ec752df63af190ee3c15fa2 100644 (file)
@@ -177,8 +177,6 @@ InitProcGlobal(void)
    ProcGlobal->autovacFreeProcs = NULL;
    ProcGlobal->bgworkerFreeProcs = NULL;
    ProcGlobal->walsenderFreeProcs = NULL;
-   ProcGlobal->startupProc = NULL;
-   ProcGlobal->startupProcPid = 0;
    ProcGlobal->startupBufferPinWaitBufId = -1;
    ProcGlobal->walwriterLatch = NULL;
    ProcGlobal->checkpointerLatch = NULL;
@@ -624,21 +622,6 @@ InitAuxiliaryProcess(void)
    on_shmem_exit(AuxiliaryProcKill, Int32GetDatum(proctype));
 }
 
-/*
- * Record the PID and PGPROC structures for the Startup process, for use in
- * ProcSendSignal().  See comments there for further explanation.
- */
-void
-PublishStartupProcessInformation(void)
-{
-   SpinLockAcquire(ProcStructLock);
-
-   ProcGlobal->startupProc = MyProc;
-   ProcGlobal->startupProcPid = MyProcPid;
-
-   SpinLockRelease(ProcStructLock);
-}
-
 /*
  * Used from bufmgr to share the value of the buffer that Startup waits on,
  * or to reset the value to "not waiting" (-1). This allows processing
@@ -1903,38 +1886,15 @@ ProcWaitForSignal(uint32 wait_event_info)
 }
 
 /*
- * ProcSendSignal - send a signal to a backend identified by PID
+ * ProcSendSignal - set the latch of a backend identified by pgprocno
  */
 void
-ProcSendSignal(int pid)
+ProcSendSignal(int pgprocno)
 {
-   PGPROC     *proc = NULL;
+   if (pgprocno < 0 || pgprocno >= ProcGlobal->allProcCount)
+       elog(ERROR, "pgprocno out of range");
 
-   if (RecoveryInProgress())
-   {
-       SpinLockAcquire(ProcStructLock);
-
-       /*
-        * Check to see whether it is the Startup process we wish to signal.
-        * This call is made by the buffer manager when it wishes to wake up a
-        * process that has been waiting for a pin in so it can obtain a
-        * cleanup lock using LockBufferForCleanup(). Startup is not a normal
-        * backend, so BackendPidGetProc() will not return any pid at all. So
-        * we remember the information for this special case.
-        */
-       if (pid == ProcGlobal->startupProcPid)
-           proc = ProcGlobal->startupProc;
-
-       SpinLockRelease(ProcStructLock);
-   }
-
-   if (proc == NULL)
-       proc = BackendPidGetProc(pid);
-
-   if (proc != NULL)
-   {
-       SetLatch(&proc->procLatch);
-   }
+   SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch);
 }
 
 /*
index 33fcaf5c9a871272e0e231d564fb7fdac5e64f48..7c6653311a580def15e90c23cc83cf3d225f7394 100644 (file)
@@ -136,7 +136,7 @@ typedef struct buftag
  * BufferDesc -- shared descriptor/state data for a single shared buffer.
  *
  * Note: Buffer header lock (BM_LOCKED flag) must be held to examine or change
- * the tag, state or wait_backend_pid fields.  In general, buffer header lock
+ * tag, state or wait_backend_pgprocno fields.  In general, buffer header lock
  * is a spinlock which is combined with flags, refcount and usagecount into
  * single atomic variable.  This layout allow us to do some operations in a
  * single atomic operation, without actually acquiring and releasing spinlock;
@@ -161,8 +161,8 @@ typedef struct buftag
  *
  * We can't physically remove items from a disk page if another backend has
  * the buffer pinned.  Hence, a backend may need to wait for all other pins
- * to go away.  This is signaled by storing its own PID into
- * wait_backend_pid and setting flag bit BM_PIN_COUNT_WAITER.  At present,
+ * to go away.  This is signaled by storing its own pgprocno into
+ * wait_backend_pgprocno and setting flag bit BM_PIN_COUNT_WAITER.  At present,
  * there can be only one such waiter per buffer.
  *
  * We use this same struct for local buffer headers, but the locks are not
@@ -187,7 +187,7 @@ typedef struct BufferDesc
    /* state of the tag, containing flags, refcount and usagecount */
    pg_atomic_uint32 state;
 
-   int         wait_backend_pid;   /* backend PID of pin-count waiter */
+   int         wait_backend_pgprocno;  /* backend of pin-count waiter */
    int         freeNext;       /* link in freelist chain */
    LWLock      content_lock;   /* to lock access to buffer contents */
 } BufferDesc;
index 104f560d380a03905162f7409bfb286e8564b43e..f154b3c3b85478eb694f4d46e5043d4afa0dc41c 100644 (file)
@@ -113,6 +113,7 @@ typedef struct SERIALIZABLEXACT
    TransactionId xmin;         /* the transaction's snapshot xmin */
    uint32      flags;          /* OR'd combination of values defined below */
    int         pid;            /* pid of associated process */
+   int         pgprocno;       /* pgprocno of associated process */
 } SERIALIZABLEXACT;
 
 #define SXACT_FLAG_COMMITTED           0x00000001  /* already committed */
index cfabfdbedf18207e7fac6317c27a874975f2165b..44b477f49d7d1f30b99eef50e646ac03b9402956 100644 (file)
@@ -359,9 +359,6 @@ typedef struct PROC_HDR
    Latch      *checkpointerLatch;
    /* Current shared estimate of appropriate spins_per_delay value */
    int         spins_per_delay;
-   /* The proc of the Startup process, since not in ProcArray */
-   PGPROC     *startupProc;
-   int         startupProcPid;
    /* Buffer id of the buffer that Startup process waits for pin on, or -1 */
    int         startupBufferPinWaitBufId;
 } PROC_HDR;
@@ -402,7 +399,6 @@ extern void InitProcess(void);
 extern void InitProcessPhase2(void);
 extern void InitAuxiliaryProcess(void);
 
-extern void PublishStartupProcessInformation(void);
 extern void SetStartupBufferPinWaitBufId(int bufid);
 extern int GetStartupBufferPinWaitBufId(void);
 
@@ -418,7 +414,7 @@ extern bool IsWaitingForLock(void);
 extern void LockErrorCleanup(void);
 
 extern void ProcWaitForSignal(uint32 wait_event_info);
-extern void ProcSendSignal(int pid);
+extern void ProcSendSignal(int pgprocno);
 
 extern PGPROC *AuxiliaryPidGetProc(int pid);