]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Refactor shmem initialization code in predicate.c
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 5 Apr 2026 23:13:01 +0000 (02:13 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 5 Apr 2026 23:13:01 +0000 (02:13 +0300)
This is in preparation to convert it to use the new shmem allocation
functions, making the next commit that does that smaller. This inlines
SerialInit() to the caller, and moves all the initialization steps
within PredicateLockShmemInit() to happen after all the
ShmemInit{Struct|Hash}() calls.

Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://www.postgresql.org/message-id/CAExHW5vM1bneLYfg0wGeAa=52UiJ3z4vKd3AJ72X8Fw6k3KKrg@mail.gmail.com

src/backend/storage/lmgr/predicate.c

index e003fa5b107536f630cc4b1f58998411773d0711..b509fbb275939ba5150aee77b46a8968d2c7b268 100644 (file)
@@ -444,7 +444,6 @@ static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact);
 
 static bool SerialPagePrecedesLogically(int64 page1, int64 page2);
 static int     serial_errdetail_for_io_error(const void *opaque_data);
-static void SerialInit(void);
 static void SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo);
 static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid);
 static void SerialSetActiveSerXmin(TransactionId xid);
@@ -809,48 +808,6 @@ SerialPagePrecedesLogicallyUnitTests(void)
 }
 #endif
 
-/*
- * Initialize for the tracking of old serializable committed xids.
- */
-static void
-SerialInit(void)
-{
-       bool            found;
-
-       /*
-        * Set up SLRU management of the pg_serial data.
-        */
-       SerialSlruCtl->PagePrecedes = SerialPagePrecedesLogically;
-       SerialSlruCtl->errdetail_for_io_error = serial_errdetail_for_io_error;
-       SimpleLruInit(SerialSlruCtl, "serializable",
-                                 serializable_buffers, 0, "pg_serial",
-                                 LWTRANCHE_SERIAL_BUFFER, LWTRANCHE_SERIAL_SLRU,
-                                 SYNC_HANDLER_NONE, false);
-#ifdef USE_ASSERT_CHECKING
-       SerialPagePrecedesLogicallyUnitTests();
-#endif
-       SlruPagePrecedesUnitTests(SerialSlruCtl, SERIAL_ENTRIESPERPAGE);
-
-       /*
-        * Create or attach to the SerialControl structure.
-        */
-       serialControl = (SerialControl)
-               ShmemInitStruct("SerialControlData", sizeof(SerialControlData), &found);
-
-       Assert(found == IsUnderPostmaster);
-       if (!found)
-       {
-               /*
-                * Set control information to reflect empty SLRU.
-                */
-               LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
-               serialControl->headPage = -1;
-               serialControl->headXid = InvalidTransactionId;
-               serialControl->tailXid = InvalidTransactionId;
-               LWLockRelease(SerialControlLock);
-       }
-}
-
 /*
  * GUC check_hook for serializable_buffers
  */
@@ -1187,19 +1144,6 @@ PredicateLockShmemInit(void)
                                                                                        HASH_ELEM | HASH_BLOBS |
                                                                                        HASH_PARTITION | HASH_FIXED_SIZE);
 
-       /*
-        * Reserve a dummy entry in the hash table; we use it to make sure there's
-        * always one entry available when we need to split or combine a page,
-        * because running out of space there could mean aborting a
-        * non-serializable transaction.
-        */
-       if (!IsUnderPostmaster)
-       {
-               (void) hash_search(PredicateLockTargetHash, &ScratchTargetTag,
-                                                  HASH_ENTER, &found);
-               Assert(!found);
-       }
-
        /* Pre-calculate the hash and partition lock of the scratch entry */
        ScratchTargetTagHash = PredicateLockTargetTagHashCode(&ScratchTargetTag);
        ScratchPartitionLock = PredicateLockHashPartitionLock(ScratchTargetTagHash);
@@ -1243,49 +1187,6 @@ PredicateLockShmemInit(void)
                                                           requestSize,
                                                           &found);
        Assert(found == IsUnderPostmaster);
-       if (!found)
-       {
-               int                     i;
-
-               /* clean everything, both the header and the element */
-               memset(PredXact, 0, requestSize);
-
-               dlist_init(&PredXact->availableList);
-               dlist_init(&PredXact->activeList);
-               PredXact->SxactGlobalXmin = InvalidTransactionId;
-               PredXact->SxactGlobalXminCount = 0;
-               PredXact->WritableSxactCount = 0;
-               PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1;
-               PredXact->CanPartialClearThrough = 0;
-               PredXact->HavePartialClearedThrough = 0;
-               PredXact->element
-                       = (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize);
-               /* Add all elements to available list, clean. */
-               for (i = 0; i < max_serializable_xacts; i++)
-               {
-                       LWLockInitialize(&PredXact->element[i].perXactPredicateListLock,
-                                                        LWTRANCHE_PER_XACT_PREDICATE_LIST);
-                       dlist_push_tail(&PredXact->availableList, &PredXact->element[i].xactLink);
-               }
-               PredXact->OldCommittedSxact = CreatePredXact();
-               SetInvalidVirtualTransactionId(PredXact->OldCommittedSxact->vxid);
-               PredXact->OldCommittedSxact->prepareSeqNo = 0;
-               PredXact->OldCommittedSxact->commitSeqNo = 0;
-               PredXact->OldCommittedSxact->SeqNo.lastCommitBeforeSnapshot = 0;
-               dlist_init(&PredXact->OldCommittedSxact->outConflicts);
-               dlist_init(&PredXact->OldCommittedSxact->inConflicts);
-               dlist_init(&PredXact->OldCommittedSxact->predicateLocks);
-               dlist_node_init(&PredXact->OldCommittedSxact->finishedLink);
-               dlist_init(&PredXact->OldCommittedSxact->possibleUnsafeConflicts);
-               PredXact->OldCommittedSxact->topXid = InvalidTransactionId;
-               PredXact->OldCommittedSxact->finishedBefore = InvalidTransactionId;
-               PredXact->OldCommittedSxact->xmin = InvalidTransactionId;
-               PredXact->OldCommittedSxact->flags = SXACT_FLAG_COMMITTED;
-               PredXact->OldCommittedSxact->pid = 0;
-               PredXact->OldCommittedSxact->pgprocno = INVALID_PROC_NUMBER;
-       }
-       /* This never changes, so let's keep a local copy. */
-       OldCommittedSxact = PredXact->OldCommittedSxact;
 
        /*
         * Allocate hash table for SERIALIZABLEXID structs.  This stores per-xid
@@ -1321,23 +1222,6 @@ PredicateLockShmemInit(void)
                                                                         requestSize,
                                                                         &found);
        Assert(found == IsUnderPostmaster);
-       if (!found)
-       {
-               int                     i;
-
-               /* clean everything, including the elements */
-               memset(RWConflictPool, 0, requestSize);
-
-               dlist_init(&RWConflictPool->availableList);
-               RWConflictPool->element = (RWConflict) ((char *) RWConflictPool +
-                                                                                               RWConflictPoolHeaderDataSize);
-               /* Add all elements to available list, clean. */
-               for (i = 0; i < max_rw_conflicts; i++)
-               {
-                       dlist_push_tail(&RWConflictPool->availableList,
-                                                       &RWConflictPool->element[i].outLink);
-               }
-       }
 
        /*
         * Create or attach to the header for the list of finished serializable
@@ -1348,14 +1232,109 @@ PredicateLockShmemInit(void)
                                                sizeof(dlist_head),
                                                &found);
        Assert(found == IsUnderPostmaster);
-       if (!found)
-               dlist_init(FinishedSerializableTransactions);
 
        /*
         * Initialize the SLRU storage for old committed serializable
         * transactions.
         */
-       SerialInit();
+       SerialSlruCtl->PagePrecedes = SerialPagePrecedesLogically;
+       SerialSlruCtl->errdetail_for_io_error = serial_errdetail_for_io_error;
+       SimpleLruInit(SerialSlruCtl, "serializable",
+                                 serializable_buffers, 0, "pg_serial",
+                                 LWTRANCHE_SERIAL_BUFFER, LWTRANCHE_SERIAL_SLRU,
+                                 SYNC_HANDLER_NONE, false);
+#ifdef USE_ASSERT_CHECKING
+       SerialPagePrecedesLogicallyUnitTests();
+#endif
+       SlruPagePrecedesUnitTests(SerialSlruCtl, SERIAL_ENTRIESPERPAGE);
+
+       /*
+        * Create or attach to the SerialControl structure.
+        */
+       serialControl = (SerialControl)
+               ShmemInitStruct("SerialControlData", sizeof(SerialControlData), &found);
+       Assert(found == IsUnderPostmaster);
+
+       /*
+        * If we just attached to existing shared memory (EXEC_BACKEND), we're all
+        * done.  Otherwise, during postmaster startup, proceed to initialize all
+        * the shared memory areas that we allocated.
+        */
+       if (IsUnderPostmaster)
+       {
+               /* This never changes, so let's keep a local copy. */
+               OldCommittedSxact = PredXact->OldCommittedSxact;
+               return;
+       }
+
+       /*
+        * Reserve a dummy entry in the hash table; we use it to make sure there's
+        * always one entry available when we need to split or combine a page,
+        * because running out of space there could mean aborting a
+        * non-serializable transaction.
+        */
+       (void) hash_search(PredicateLockTargetHash, &ScratchTargetTag,
+                                          HASH_ENTER, &found);
+       Assert(!found);
+
+       /* Initialize PredXact list */
+       dlist_init(&PredXact->availableList);
+       dlist_init(&PredXact->activeList);
+       PredXact->SxactGlobalXmin = InvalidTransactionId;
+       PredXact->SxactGlobalXminCount = 0;
+       PredXact->WritableSxactCount = 0;
+       PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1;
+       PredXact->CanPartialClearThrough = 0;
+       PredXact->HavePartialClearedThrough = 0;
+       PredXact->element
+               = (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize);
+       /* Add all elements to available list, clean. */
+       for (int i = 0; i < max_serializable_xacts; i++)
+       {
+               LWLockInitialize(&PredXact->element[i].perXactPredicateListLock,
+                                                LWTRANCHE_PER_XACT_PREDICATE_LIST);
+               dlist_push_tail(&PredXact->availableList, &PredXact->element[i].xactLink);
+       }
+       PredXact->OldCommittedSxact = CreatePredXact();
+       SetInvalidVirtualTransactionId(PredXact->OldCommittedSxact->vxid);
+       PredXact->OldCommittedSxact->prepareSeqNo = 0;
+       PredXact->OldCommittedSxact->commitSeqNo = 0;
+       PredXact->OldCommittedSxact->SeqNo.lastCommitBeforeSnapshot = 0;
+       dlist_init(&PredXact->OldCommittedSxact->outConflicts);
+       dlist_init(&PredXact->OldCommittedSxact->inConflicts);
+       dlist_init(&PredXact->OldCommittedSxact->predicateLocks);
+       dlist_node_init(&PredXact->OldCommittedSxact->finishedLink);
+       dlist_init(&PredXact->OldCommittedSxact->possibleUnsafeConflicts);
+       PredXact->OldCommittedSxact->topXid = InvalidTransactionId;
+       PredXact->OldCommittedSxact->finishedBefore = InvalidTransactionId;
+       PredXact->OldCommittedSxact->xmin = InvalidTransactionId;
+       PredXact->OldCommittedSxact->flags = SXACT_FLAG_COMMITTED;
+       PredXact->OldCommittedSxact->pid = 0;
+       PredXact->OldCommittedSxact->pgprocno = INVALID_PROC_NUMBER;
+
+       /* This never changes, so let's keep a local copy. */
+       OldCommittedSxact = PredXact->OldCommittedSxact;
+
+       /* Initialize the rw-conflict pool */
+       dlist_init(&RWConflictPool->availableList);
+       RWConflictPool->element = (RWConflict) ((char *) RWConflictPool +
+                                                                                       RWConflictPoolHeaderDataSize);
+       /* Add all elements to available list, clean. */
+       for (int i = 0; i < max_rw_conflicts; i++)
+       {
+               dlist_push_tail(&RWConflictPool->availableList,
+                                               &RWConflictPool->element[i].outLink);
+       }
+
+       /* Initialize the list of finished serializable transactions */
+       dlist_init(FinishedSerializableTransactions);
+
+       /* Initialize SerialControl to reflect empty SLRU. */
+       LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
+       serialControl->headPage = -1;
+       serialControl->headXid = InvalidTransactionId;
+       serialControl->tailXid = InvalidTransactionId;
+       LWLockRelease(SerialControlLock);
 }
 
 /*