From: Heikki Linnakangas Date: Sun, 5 Apr 2026 23:13:01 +0000 (+0300) Subject: Refactor shmem initialization code in predicate.c X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4c9eca5afea0e8623e39f6a778412d4da687f659;p=thirdparty%2Fpostgresql.git Refactor shmem initialization code in predicate.c 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 Reviewed-by: Matthias van de Meent Reviewed-by: Daniel Gustafsson Discussion: https://www.postgresql.org/message-id/CAExHW5vM1bneLYfg0wGeAa=52UiJ3z4vKd3AJ72X8Fw6k3KKrg@mail.gmail.com --- diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index e003fa5b107..b509fbb2759 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -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); } /*