From 2605d6260ae63adbb3713fe25ac14b59948de680 Mon Sep 17 00:00:00 2001 From: Jakub Wartak Date: Mon, 1 Dec 2025 13:28:54 +0100 Subject: [PATCH v3 2/2] wait_event_arg: provide quick and dump demo of multixact passthrough to LWLockReportWaitStart() --- contrib/amcheck/verify_heapam.c | 2 +- contrib/pgrowlocks/pgrowlocks.c | 2 +- src/backend/access/heap/heapam.c | 82 +++++++++++---------- src/backend/access/heap/heapam_visibility.c | 22 +++--- src/backend/access/transam/multixact.c | 42 ++++++----- src/backend/storage/lmgr/lwlock.c | 19 +++-- src/backend/utils/adt/multixactfuncs.c | 2 +- src/include/access/htup.h | 2 +- src/include/access/htup_details.h | 2 +- src/include/access/multixact.h | 10 ++- src/include/storage/lwlock.h | 1 + src/test/modules/test_slru/test_multixact.c | 4 +- 12 files changed, 107 insertions(+), 83 deletions(-) diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index 4963e9245cb..27917e694f8 100644 --- a/contrib/amcheck/verify_heapam.c +++ b/contrib/amcheck/verify_heapam.c @@ -1397,7 +1397,7 @@ check_tuple_visibility(HeapCheckContext *ctx, bool *xmin_commit_status_ok, * We already checked above that this multixact is within limits for * this table. Now check the update xid from this multixact. */ - xmax = HeapTupleGetUpdateXid(tuphdr); + xmax = HeapTupleGetUpdateXid(tuphdr, 0); /* DEMO: we do not care */ switch (get_xid_status(xmax, ctx, &xmax_status)) { case XID_INVALID: diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c index f88269332b6..d4b8b15530f 100644 --- a/contrib/pgrowlocks/pgrowlocks.c +++ b/contrib/pgrowlocks/pgrowlocks.c @@ -157,7 +157,7 @@ pgrowlocks(PG_FUNCTION_ARGS) allow_old = HEAP_LOCKED_UPGRADED(infomask); nmembers = GetMultiXactIdMembers(xmax, &members, allow_old, - false); + false, rel->rd_locator.relNumber); if (nmembers == -1) { values[Atnum_xids] = "{0}"; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4d382a04338..06083ee2252 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -84,14 +84,14 @@ static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask, uint16 old_infomask2, TransactionId add_to_xmax, LockTupleMode mode, bool is_update, TransactionId *result_xmax, uint16 *result_infomask, - uint16 *result_infomask2); + uint16 *result_infomask2, RelFileNumber r); static TM_Result heap_lock_updated_tuple(Relation rel, HeapTuple tuple, const ItemPointerData *ctid, TransactionId xid, LockTupleMode mode); static void GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask, - uint16 *new_infomask2); + uint16 *new_infomask2, RelFileNumber r); static TransactionId MultiXactIdGetUpdateXid(TransactionId xmax, - uint16 t_infomask); + uint16 t_infomask, RelFileNumber r); static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, LockTupleMode lockmode, bool *current_is_member); static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, @@ -3065,7 +3065,8 @@ l1: compute_new_xmax_infomask(HeapTupleHeaderGetRawXmax(tp.t_data), tp.t_data->t_infomask, tp.t_data->t_infomask2, xid, LockTupleExclusive, true, - &new_xmax, &new_infomask, &new_infomask2); + &new_xmax, &new_infomask, &new_infomask2, + relation->rd_locator.relNumber); START_CRIT_SECTION(); @@ -3615,7 +3616,7 @@ l2: * subxact aborts. */ if (!HEAP_XMAX_IS_LOCKED_ONLY(oldtup.t_data->t_infomask)) - update_xact = HeapTupleGetUpdateXid(oldtup.t_data); + update_xact = HeapTupleGetUpdateXid(oldtup.t_data, relation->rd_locator.relNumber); else update_xact = InvalidTransactionId; @@ -3758,7 +3759,8 @@ l2: oldtup.t_data->t_infomask2, xid, *lockmode, true, &xmax_old_tuple, &infomask_old_tuple, - &infomask2_old_tuple); + &infomask2_old_tuple, + relation->rd_locator.relNumber); /* * And also prepare an Xmax value for the new copy of the tuple. If there @@ -3790,7 +3792,7 @@ l2: if (oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) { GetMultiXactIdHintBits(xmax_new_tuple, &infomask_new_tuple, - &infomask2_new_tuple); + &infomask2_new_tuple, relation->rd_locator.relNumber); } else { @@ -3875,7 +3877,8 @@ l2: oldtup.t_data->t_infomask2, xid, *lockmode, false, &xmax_lock_old_tuple, &infomask_lock_old_tuple, - &infomask2_lock_old_tuple); + &infomask2_lock_old_tuple, + relation->rd_locator.relNumber); Assert(HEAP_XMAX_IS_LOCKED_ONLY(infomask_lock_old_tuple)); @@ -4706,7 +4709,8 @@ l3: */ nmembers = GetMultiXactIdMembers(xwait, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(infomask), + relation->rd_locator.relNumber); for (i = 0; i < nmembers; i++) { @@ -5186,7 +5190,8 @@ failed: */ compute_new_xmax_infomask(xmax, old_infomask, tuple->t_data->t_infomask2, GetCurrentTransactionId(), mode, false, - &xid, &new_infomask, &new_infomask2); + &xid, &new_infomask, &new_infomask2, + relation->rd_locator.relNumber); START_CRIT_SECTION(); @@ -5353,7 +5358,7 @@ compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask, uint16 old_infomask2, TransactionId add_to_xmax, LockTupleMode mode, bool is_update, TransactionId *result_xmax, uint16 *result_infomask, - uint16 *result_infomask2) + uint16 *result_infomask2, RelFileNumber r) { TransactionId new_xmax; uint16 new_infomask, @@ -5448,7 +5453,7 @@ l5: { if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) || !TransactionIdDidCommit(MultiXactIdGetUpdateXid(xmax, - old_infomask))) + old_infomask, 11))) { /* * Reset these bits and restart; otherwise fall through to @@ -5463,8 +5468,8 @@ l5: new_status = get_mxact_status_for_lock(mode, is_update); new_xmax = MultiXactIdExpand((MultiXactId) xmax, add_to_xmax, - new_status); - GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2); + new_status, r); + GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r); } else if (old_infomask & HEAP_XMAX_COMMITTED) { @@ -5487,8 +5492,8 @@ l5: * updater to be identical to the current one, so we need not check * for that case as we do in the block above. */ - new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status); - GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2); + new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status, r); + GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r); } else if (TransactionIdIsInProgress(xmax)) { @@ -5569,8 +5574,8 @@ l5: /* otherwise, just fall back to creating a new multixact */ new_status = get_mxact_status_for_lock(mode, is_update); new_xmax = MultiXactIdCreate(xmax, old_status, - add_to_xmax, new_status); - GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2); + add_to_xmax, new_status, r); + GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r); } else if (!HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) && TransactionIdDidCommit(xmax)) @@ -5594,8 +5599,8 @@ l5: * updater to be identical to the current one, so we need not check * for that case as we do in the block above. */ - new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status); - GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2); + new_xmax = MultiXactIdCreate(xmax, status, add_to_xmax, new_status, r); + GetMultiXactIdHintBits(new_xmax, &new_infomask, &new_infomask2, r); } else { @@ -5856,7 +5861,8 @@ l4: Assert(!HEAP_LOCKED_UPGRADED(mytup.t_data->t_infomask)); nmembers = GetMultiXactIdMembers(rawxmax, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(old_infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(old_infomask), + rel->rd_locator.relNumber); for (i = 0; i < nmembers; i++) { result = test_lockmode_for_conflict(members[i].status, @@ -5971,7 +5977,8 @@ l4: /* compute the new Xmax and infomask values for the tuple ... */ compute_new_xmax_infomask(xmax, old_infomask, mytup.t_data->t_infomask2, xid, mode, false, - &new_xmax, &new_infomask, &new_infomask2); + &new_xmax, &new_infomask, &new_infomask2, + rel->rd_locator.relNumber); if (PageIsAllVisible(BufferGetPage(buf)) && visibilitymap_clear(rel, block, vmbuffer, @@ -6729,7 +6736,7 @@ heap_inplace_unlock(Relation relation, static TransactionId FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, const struct VacuumCutoffs *cutoffs, uint16 *flags, - HeapPageFreeze *pagefrz) + HeapPageFreeze *pagefrz, RelFileNumber r) { TransactionId newxmax; MultiXactMember *members; @@ -6784,7 +6791,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, } /* replace multi with single XID for its updater? */ - update_xact = MultiXactIdGetUpdateXid(multi, t_infomask); + update_xact = MultiXactIdGetUpdateXid(multi, t_infomask, 0); if (TransactionIdPrecedes(update_xact, cutoffs->relfrozenxid)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -6822,7 +6829,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, */ nmembers = GetMultiXactIdMembers(multi, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(t_infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(t_infomask), r); if (nmembers <= 0) { /* Nothing worth keeping */ @@ -7023,7 +7030,8 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, * Create a new multixact with the surviving members of the previous * one, to set as new Xmax in the tuple */ - newxmax = MultiXactIdCreateFromMembers(nnewmembers, newmembers); + /* XXX/DEMO no need to extend wiat info in freeze scenario? */ + newxmax = MultiXactIdCreateFromMembers(nnewmembers, newmembers, 0); *flags |= FRM_RETURN_IS_MULTI; } @@ -7154,7 +7162,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * FreezeLimit/MultiXactCutoff postcondition must never be violated. */ newxmax = FreezeMultiXactId(xid, tuple->t_infomask, cutoffs, - &flags, pagefrz); + &flags, pagefrz, 0); if (flags & FRM_NOOP) { @@ -7220,7 +7228,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, */ frz->t_infomask &= ~HEAP_XMAX_BITS; frz->t_infomask2 &= ~HEAP_KEYS_UPDATED; - GetMultiXactIdHintBits(newxmax, &newbits, &newbits2); + GetMultiXactIdHintBits(newxmax, &newbits, &newbits2, 0); /* DEMO: shortcut */ frz->t_infomask |= newbits; frz->t_infomask2 |= newbits2; frz->xmax = newxmax; @@ -7470,7 +7478,7 @@ heap_freeze_tuple(HeapTupleHeader tuple, */ static void GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask, - uint16 *new_infomask2) + uint16 *new_infomask2, RelFileNumber r) { int nmembers; MultiXactMember *members; @@ -7484,7 +7492,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask, * We only use this in multis we just created, so they cannot be values * pre-pg_upgrade. */ - nmembers = GetMultiXactIdMembers(multi, &members, false, false); + nmembers = GetMultiXactIdMembers(multi, &members, false, false, 0); for (i = 0; i < nmembers; i++) { @@ -7550,7 +7558,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask, * necessary. */ static TransactionId -MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask) +MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask, RelFileNumber r) { TransactionId update_xact = InvalidTransactionId; MultiXactMember *members; @@ -7563,7 +7571,7 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask) * Since we know the LOCK_ONLY bit is not set, this cannot be a multi from * pre-pg_upgrade. */ - nmembers = GetMultiXactIdMembers(xmax, &members, false, false); + nmembers = GetMultiXactIdMembers(xmax, &members, false, false, r); if (nmembers > 0) { @@ -7602,10 +7610,10 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask) * checking the hint bits. */ TransactionId -HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup) +HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup, uint32_t r) { return MultiXactIdGetUpdateXid(HeapTupleHeaderGetRawXmax(tup), - tup->t_infomask); + tup->t_infomask, r); } /* @@ -7630,7 +7638,7 @@ DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, return false; nmembers = GetMultiXactIdMembers(multi, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(infomask), 4); /* DEMO: shortcut */ if (nmembers >= 0) { int i; @@ -7731,7 +7739,7 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status, /* for pre-pg_upgrade tuples, no need to sleep at all */ nmembers = HEAP_LOCKED_UPGRADED(infomask) ? -1 : GetMultiXactIdMembers(multi, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(infomask), 5); /* DEMO */ if (nmembers >= 0) { @@ -7951,7 +7959,7 @@ heap_tuple_should_freeze(HeapTupleHeader tuple, /* need to check whether any member of the mxact is old */ nmembers = GetMultiXactIdMembers(multi, &members, false, - HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)); + HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask), 3); /* DEMO: shortcut */ for (int i = 0; i < nmembers; i++) { diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c index 05f6946fe60..d1759b9fc24 100644 --- a/src/backend/access/heap/heapam_visibility.c +++ b/src/backend/access/heap/heapam_visibility.c @@ -230,7 +230,7 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer) { TransactionId xmax; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -285,7 +285,7 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer) if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) return true; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -550,7 +550,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, { TransactionId xmax; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -630,7 +630,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, return TM_Ok; } - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); if (!TransactionIdIsValid(xmax)) { if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false)) @@ -807,7 +807,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, { TransactionId xmax; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -880,7 +880,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) return true; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -1033,7 +1033,7 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, { TransactionId xmax; - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -1096,7 +1096,7 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, /* already checked above */ Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)); - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -1354,7 +1354,7 @@ HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *de if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { - TransactionId xmax = HeapTupleGetUpdateXid(tuple); + TransactionId xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); /* already checked above */ Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)); @@ -1549,7 +1549,7 @@ HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple) return false; /* ... but if it's a multi, then perhaps the updating Xid aborted. */ - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, 12); /* DEMO */ /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); @@ -1698,7 +1698,7 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, */ else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { - xmax = HeapTupleGetUpdateXid(tuple); + xmax = HeapTupleGetUpdateXid(tuple, htup->t_tableOid); } /* check if it's one of our txids, toplevel is also in there */ diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 9d5f130af7e..b149e4481e7 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -384,7 +384,9 @@ static MemoryContext MXactContext = NULL; /* internal MultiXactId management */ static void MultiXactIdSetOldestVisible(void); static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, - int nmembers, MultiXactMember *members); + int nmembers, MultiXactMember *members, + RelFileNumber r); + static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset); /* MultiXact cache management */ @@ -423,7 +425,8 @@ static void WriteMTruncateXlogRec(Oid oldestMultiDB, */ MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, - TransactionId xid2, MultiXactStatus status2) + TransactionId xid2, MultiXactStatus status2, + RelFileNumber r) { MultiXactId newMulti; MultiXactMember members[2]; @@ -447,7 +450,7 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, members[1].xid = xid2; members[1].status = status2; - newMulti = MultiXactIdCreateFromMembers(2, members); + newMulti = MultiXactIdCreateFromMembers(2, members, r); debug_elog3(DEBUG2, "Create: %s", mxid_to_string(newMulti, 2, members)); @@ -475,7 +478,8 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, * passed in. */ MultiXactId -MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) +MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status, + RelFileNumber r) { MultiXactId newMulti; MultiXactMember *members; @@ -498,7 +502,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) * caller of this function does a check that the multixact is no longer * running. */ - nmembers = GetMultiXactIdMembers(multi, &members, false, false); + nmembers = GetMultiXactIdMembers(multi, &members, false, false, r); if (nmembers < 0) { @@ -513,7 +517,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) */ member.xid = xid; member.status = status; - newMulti = MultiXactIdCreateFromMembers(1, &member); + newMulti = MultiXactIdCreateFromMembers(1, &member, r); debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u", multi, newMulti); @@ -565,7 +569,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) newMembers[j].xid = xid; newMembers[j++].status = status; - newMulti = MultiXactIdCreateFromMembers(j, newMembers); + newMulti = MultiXactIdCreateFromMembers(j, newMembers, r); pfree(members); pfree(newMembers); @@ -599,7 +603,7 @@ MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly) * "false" here means we assume our callers have checked that the given * multi cannot possibly come from a pg_upgraded database. */ - nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly); + nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly, 0); if (nmembers <= 0) { @@ -803,7 +807,7 @@ ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next) * NB: the passed members[] array will be sorted in-place. */ MultiXactId -MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) +MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members, RelFileNumber r) { MultiXactId multi; MultiXactOffset offset; @@ -883,7 +887,7 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) (void) XLogInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_CREATE_ID); /* Now enter the information into the OFFSETs and MEMBERs logs */ - RecordNewMultiXact(multi, offset, nmembers, members); + RecordNewMultiXact(multi, offset, nmembers, members, r); /* Done with critical section */ END_CRIT_SECTION(); @@ -905,7 +909,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) */ static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, - int nmembers, MultiXactMember *members) + int nmembers, MultiXactMember *members, + RelFileNumber r) { int64 pageno; int64 prev_pageno; @@ -920,7 +925,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, entryno = MultiXactIdToOffsetEntry(multi); lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno); - LWLockAcquire(lock, LW_EXCLUSIVE); + LWLockAcquireExt(lock, LW_EXCLUSIVE, r); /* * Note: we pass the MultiXactId to SimpleLruReadPage as the "transaction" @@ -977,7 +982,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, if (prevlock != NULL) LWLockRelease(prevlock); - LWLockAcquire(lock, LW_EXCLUSIVE); + LWLockAcquireExt(lock, LW_EXCLUSIVE, r); prevlock = lock; } slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, multi); @@ -1288,7 +1293,8 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset) */ int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, - bool from_pgupgrade, bool isLockOnly) + bool from_pgupgrade, bool isLockOnly, + RelFileNumber r) { int64 pageno; int64 prev_pageno; @@ -1415,7 +1421,7 @@ retry: /* Acquire the bank lock for the page we need. */ lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno); - LWLockAcquire(lock, LW_EXCLUSIVE); + LWLockAcquireExt(lock, LW_EXCLUSIVE, r); slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, multi); offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno]; @@ -1461,7 +1467,7 @@ retry: if (newlock != lock) { LWLockRelease(lock); - LWLockAcquire(newlock, LW_EXCLUSIVE); + LWLockAcquireExt(newlock, LW_EXCLUSIVE, r); lock = newlock; } slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, tmpMXact); @@ -1526,7 +1532,7 @@ retry: { if (lock) LWLockRelease(lock); - LWLockAcquire(newlock, LW_EXCLUSIVE); + LWLockAcquireExt(newlock, LW_EXCLUSIVE, r); lock = newlock; } @@ -3357,7 +3363,7 @@ multixact_redo(XLogReaderState *record) /* Store the data back into the SLRU files */ RecordNewMultiXact(xlrec->mid, xlrec->moff, xlrec->nmembers, - xlrec->members); + xlrec->members, 0); /* Make sure nextMXact/nextOffset are beyond what this record has */ MultiXactAdvanceNextMXact(xlrec->mid + 1, diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index e703d6ae807..bd08af8a6c4 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -204,7 +204,7 @@ static int LocalLWLockCounter; #define MAX_NAMED_TRANCHES 256 static void InitializeLWLocks(void); -static inline void LWLockReportWaitStart(LWLock *lock); +static inline void LWLockReportWaitStart(LWLock *lock, uint32 additional_info); static inline void LWLockReportWaitEnd(void); static const char *GetLWTrancheName(uint16 trancheId); @@ -716,9 +716,9 @@ LWLockInitialize(LWLock *lock, int tranche_id) * event based on tranche and lock id. */ static inline void -LWLockReportWaitStart(LWLock *lock) +LWLockReportWaitStart(LWLock *lock, uint32 additional_info) { - pgstat_report_wait_start(PG_WAIT_LWLOCK | ((uint64_t) lock->tranche << 32)); + pgstat_report_wait_start(PG_WAIT_LWLOCK | ((uint64_t) lock->tranche << 32) | additional_info); } /* @@ -1173,6 +1173,13 @@ LWLockDequeueSelf(LWLock *lock) */ bool LWLockAcquire(LWLock *lock, LWLockMode mode) +{ + return LWLockAcquireExt(lock, mode, 0); +} + +/* XXX/DEMO just for demo purposes */ +bool +LWLockAcquireExt(LWLock *lock, LWLockMode mode, uint32 additional_info) { PGPROC *proc = MyProc; bool result = true; @@ -1285,7 +1292,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode) lwstats->block_count++; #endif - LWLockReportWaitStart(lock); + LWLockReportWaitStart(lock, additional_info); if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED()) TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode); @@ -1450,7 +1457,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode) lwstats->block_count++; #endif - LWLockReportWaitStart(lock); + LWLockReportWaitStart(lock, 0); if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED()) TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode); @@ -1668,7 +1675,7 @@ LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, lwstats->block_count++; #endif - LWLockReportWaitStart(lock); + LWLockReportWaitStart(lock, 0); if (TRACE_POSTGRESQL_LWLOCK_WAIT_START_ENABLED()) TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE); diff --git a/src/backend/utils/adt/multixactfuncs.c b/src/backend/utils/adt/multixactfuncs.c index e74ea938348..045591c9cbb 100644 --- a/src/backend/utils/adt/multixactfuncs.c +++ b/src/backend/utils/adt/multixactfuncs.c @@ -53,7 +53,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS) multi = palloc(sizeof(mxact)); /* no need to allow for old values here */ multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false, - false); + false, 0); multi->iter = 0; if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) diff --git a/src/include/access/htup.h b/src/include/access/htup.h index f6b766697e2..82b1bc0c205 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -84,6 +84,6 @@ extern void HeapTupleHeaderAdjustCmax(const HeapTupleHeaderData *tup, CommandId *cmax, bool *iscombo); /* Prototype for HeapTupleHeader accessors in heapam.c */ -extern TransactionId HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup); +extern TransactionId HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup, uint32_t r); #endif /* HTUP_H */ diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index f3593acc8c2..4c50a514141 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -404,7 +404,7 @@ HeapTupleHeaderGetUpdateXid(const HeapTupleHeaderData *tup) if (!((tup)->t_infomask & HEAP_XMAX_INVALID) && ((tup)->t_infomask & HEAP_XMAX_IS_MULTI) && !((tup)->t_infomask & HEAP_XMAX_LOCK_ONLY)) - return HeapTupleGetUpdateXid(tup); + return HeapTupleGetUpdateXid(tup, 13); else return HeapTupleHeaderGetRawXmax(tup); } diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 82e4bb90dd5..643b17b6025 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -99,18 +99,20 @@ typedef struct xl_multixact_truncate extern MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, - MultiXactStatus status2); + MultiXactStatus status2, RelFileNumber r); extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, - MultiXactStatus status); + MultiXactStatus status, RelFileNumber r); extern MultiXactId MultiXactIdCreateFromMembers(int nmembers, - MultiXactMember *members); + MultiXactMember *members, + RelFileNumber r); extern MultiXactId ReadNextMultiXactId(void); extern void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next); extern bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly); extern void MultiXactIdSetOldestMember(void); extern int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, - bool from_pgupgrade, bool isLockOnly); + bool from_pgupgrade, bool isLockOnly, + RelFileNumber r); extern bool GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *members, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset); diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h index 54e72cd8860..594753fcf25 100644 --- a/src/include/storage/lwlock.h +++ b/src/include/storage/lwlock.h @@ -122,6 +122,7 @@ extern PGDLLIMPORT bool Trace_lwlocks; #endif extern bool LWLockAcquire(LWLock *lock, LWLockMode mode); +extern bool LWLockAcquireExt(LWLock *lock, LWLockMode mode, uint32 additional_info); extern bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode); extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode); extern void LWLockRelease(LWLock *lock); diff --git a/src/test/modules/test_slru/test_multixact.c b/src/test/modules/test_slru/test_multixact.c index 6c9b0420717..099465c5f59 100644 --- a/src/test/modules/test_slru/test_multixact.c +++ b/src/test/modules/test_slru/test_multixact.c @@ -32,7 +32,7 @@ test_create_multixact(PG_FUNCTION_ARGS) MultiXactIdSetOldestMember(); id = MultiXactIdCreate(GetCurrentTransactionId(), MultiXactStatusUpdate, - GetCurrentTransactionId(), MultiXactStatusForShare); + GetCurrentTransactionId(), MultiXactStatusForShare, 0); PG_RETURN_TRANSACTIONID(id); } @@ -50,7 +50,7 @@ test_read_multixact(PG_FUNCTION_ARGS) /* discard caches */ AtEOXact_MultiXact(); - if (GetMultiXactIdMembers(id, &members, false, false) == -1) + if (GetMultiXactIdMembers(id, &members, false, false, 0) == -1) elog(ERROR, "MultiXactId not found"); PG_RETURN_VOID(); -- 2.43.0