v3-0002-wait_event_arg-provide-quick-and-dump-demo-of-mul.patch
text/x-patch
Filename: v3-0002-wait_event_arg-provide-quick-and-dump-demo-of-mul.patch
Type: text/x-patch
Part: 0
From 2605d6260ae63adbb3713fe25ac14b59948de680 Mon Sep 17 00:00:00 2001
From: Jakub Wartak <jakub.wartak@enterprisedb.com>
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