From 6818a30ee7849e48aae7e43ec2d8e8ddde774838 Mon Sep 17 00:00:00 2001 From: Jakub Wartak Date: Mon, 1 Dec 2025 13:28:54 +0100 Subject: [PATCH v3 2/4] wait_event_arg: provide quick and dumb demo of multixact passthrough to LWLockReportWaitStart() XXX: This needs review if such alternation of function arguments are acceptable or not. --- contrib/amcheck/verify_heapam.c | 2 +- contrib/pgrowlocks/pgrowlocks.c | 2 +- src/backend/access/heap/heapam.c | 94 ++++++++++++--------- src/backend/access/heap/heapam_visibility.c | 22 ++--- src/backend/access/transam/multixact.c | 47 ++++++----- src/backend/storage/lmgr/lwlock.c | 19 +++-- src/backend/utils/adt/multixactfuncs.c | 4 +- src/include/access/htup.h | 2 +- src/include/access/htup_details.h | 2 +- src/include/access/multixact.h | 13 +-- src/include/storage/lwlock.h | 1 + src/test/modules/test_slru/test_multixact.c | 4 +- 12 files changed, 120 insertions(+), 92 deletions(-) diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index 30c2f58317..152da73221 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 f88269332b..d4b8b15530 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 ad9d6338ec..dd1303fc98 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -84,17 +84,18 @@ 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, uint16 prior_infomask, TransactionId prior_raw_xmax, const ItemPointerData *prior_ctid, TransactionId xid, - LockTupleMode mode); + LockTupleMode mode, + RelFileNumber r); 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, @@ -3068,7 +3069,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(); @@ -3618,7 +3620,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; @@ -3761,7 +3763,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 @@ -3793,7 +3796,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 { @@ -3878,7 +3881,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)); @@ -4709,7 +4713,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++) { @@ -4827,7 +4832,7 @@ l3: res = heap_lock_updated_tuple(relation, infomask, xwait, &t_ctid, GetCurrentTransactionId(), - mode); + mode, relation->rd_locator.relNumber); if (res != TM_Ok) { result = res; @@ -5076,7 +5081,7 @@ l3: res = heap_lock_updated_tuple(relation, infomask, xwait, &t_ctid, GetCurrentTransactionId(), - mode); + mode, relation->rd_locator.relNumber); if (res != TM_Ok) { result = res; @@ -5193,7 +5198,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(); @@ -5360,7 +5366,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, @@ -5455,7 +5461,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 @@ -5470,8 +5476,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) { @@ -5494,8 +5500,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)) { @@ -5576,8 +5582,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)) @@ -5601,8 +5607,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 { @@ -5863,7 +5869,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, @@ -5978,7 +5985,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, @@ -6080,7 +6088,8 @@ heap_lock_updated_tuple(Relation rel, uint16 prior_infomask, TransactionId prior_raw_xmax, const ItemPointerData *prior_ctid, - TransactionId xid, LockTupleMode mode) + TransactionId xid, LockTupleMode mode, + RelFileNumber r) { INJECTION_POINT("heap_lock_updated_tuple", NULL); @@ -6104,7 +6113,7 @@ heap_lock_updated_tuple(Relation rel, MultiXactIdSetOldestMember(); prior_xmax = (prior_infomask & HEAP_XMAX_IS_MULTI) ? - MultiXactIdGetUpdateXid(prior_raw_xmax, prior_infomask) : prior_raw_xmax; + MultiXactIdGetUpdateXid(prior_raw_xmax, prior_infomask, rel->rd_locator.relNumber) : prior_raw_xmax; return heap_lock_updated_tuple_rec(rel, prior_xmax, prior_ctid, xid, mode); } @@ -6748,7 +6757,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; @@ -6803,7 +6812,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), @@ -6841,7 +6850,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 */ @@ -7042,7 +7051,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; } @@ -7173,7 +7183,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) { @@ -7239,7 +7249,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; @@ -7489,7 +7499,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; @@ -7503,7 +7513,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++) { @@ -7569,7 +7579,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; @@ -7582,7 +7592,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) { @@ -7621,10 +7631,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); } /* @@ -7649,7 +7659,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; @@ -7750,7 +7760,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) { @@ -7970,7 +7980,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 05e70b7d92..c17d95e5ae 100644 --- a/src/backend/access/heap/heapam_visibility.c +++ b/src/backend/access/heap/heapam_visibility.c @@ -242,7 +242,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)); @@ -297,7 +297,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)); @@ -488,7 +488,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)); @@ -568,7 +568,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)) @@ -708,7 +708,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)); @@ -781,7 +781,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)); @@ -897,7 +897,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)); @@ -960,7 +960,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)); @@ -1183,7 +1183,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)); @@ -1378,7 +1378,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)); @@ -1527,7 +1527,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 3f423636b4..b2a04e34b2 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -264,7 +264,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 */ @@ -299,7 +301,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]; @@ -323,7 +326,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)); @@ -351,7 +354,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; @@ -374,7 +378,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) { @@ -389,7 +393,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); @@ -440,7 +444,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); @@ -474,7 +478,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) { @@ -655,7 +659,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; @@ -735,7 +739,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(); @@ -757,7 +761,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; @@ -791,7 +796,7 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, * multixid. */ lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno); - LWLockAcquire(lock, LW_EXCLUSIVE); + LWLockAcquireExt(lock, LW_EXCLUSIVE, r); /* * Note: we pass the MultiXactId to SimpleLruReadPage as the "transaction" @@ -880,7 +885,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); @@ -1113,7 +1118,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; @@ -1205,7 +1211,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, /* Acquire the bank lock for the page we need. */ lock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno); - LWLockAcquire(lock, LW_EXCLUSIVE); + LWLockAcquireExt(lock, LW_EXCLUSIVE, r); /* read this multi's offset */ slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, multi); @@ -1243,7 +1249,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, if (newlock != lock) { LWLockRelease(lock); - LWLockAcquire(newlock, LW_EXCLUSIVE); + LWLockAcquireExt(newlock, LW_EXCLUSIVE, r); lock = newlock; } slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, tmpMXact); @@ -1307,7 +1313,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, { if (lock) LWLockRelease(lock); - LWLockAcquire(newlock, LW_EXCLUSIVE); + LWLockAcquireExt(newlock, LW_EXCLUSIVE, r); lock = newlock; } @@ -2467,7 +2473,8 @@ find_multixact_start(MultiXactId multi, MultiXactOffset *result) */ void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset, - MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset) + MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset, + RelFileNumber r) { MultiXactId nextMultiXactId; @@ -2522,7 +2529,7 @@ MultiXactMemberFreezeThreshold(void) uint64 members; /* Read the current offsets and multixact usage. */ - GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset); + GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset, 0); members = nextOffset - oldestOffset; /* If member space utilization is low, no special action is required. */ @@ -2914,7 +2921,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(NextMultiXactId(xlrec->mid), diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index fb548c9a9a..653b8b89b5 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); } /* @@ -1177,6 +1177,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; @@ -1289,7 +1296,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); @@ -1454,7 +1461,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); @@ -1672,7 +1679,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 9fe2ebafa7..a9573f13fc 100644 --- a/src/backend/utils/adt/multixactfuncs.c +++ b/src/backend/utils/adt/multixactfuncs.c @@ -58,7 +58,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS) multi = palloc_object(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) @@ -114,7 +114,7 @@ pg_get_multixact_stats(PG_FUNCTION_ARGS) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("return type must be a row type"))); - GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset); + GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset, 0); members = nextOffset - oldestOffset; membersBytes = MultiXactOffsetStorageSize(nextOffset, oldestOffset); diff --git a/src/include/access/htup.h b/src/include/access/htup.h index cfc4e1cbc5..82150103ce 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 d406825ff2..a4f917140a 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 26f6bd2890..0df9479d6d 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -97,21 +97,24 @@ 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 void GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *nextOffset, MultiXactId *oldestMultiXactId, - MultiXactOffset *oldestOffset); + MultiXactOffset *oldestOffset, + RelFileNumber r); extern bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2); extern bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2); diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h index 600512be70..9944fbc117 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 e6de33c424..bc499047eb 100644 --- a/src/test/modules/test_slru/test_multixact.c +++ b/src/test/modules/test_slru/test_multixact.c @@ -31,7 +31,7 @@ test_create_multixact(PG_FUNCTION_ARGS) MultiXactIdSetOldestMember(); id = MultiXactIdCreate(GetCurrentTransactionId(), MultiXactStatusUpdate, - GetCurrentTransactionId(), MultiXactStatusForShare); + GetCurrentTransactionId(), MultiXactStatusForShare, 0); PG_RETURN_TRANSACTIONID(id); } @@ -47,7 +47,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