diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c new file mode 100644 index 9f55adc..c4d5efa *** a/src/backend/access/transam/twophase.c --- b/src/backend/access/transam/twophase.c *************** MarkAsPreparing(TransactionId xid, const *** 403,409 **** TwoPhaseState->freeGXacts = gxact->next; proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; /* Initialize the PGPROC entry */ MemSet(proc, 0, sizeof(PGPROC)); --- 403,409 ---- TwoPhaseState->freeGXacts = gxact->next; proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; /* Initialize the PGPROC entry */ MemSet(proc, 0, sizeof(PGPROC)); *************** GXactLoadSubxactData(GlobalTransaction g *** 467,473 **** TransactionId *children) { PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; /* We need no extra lock since the GXACT isn't valid yet */ if (nsubxacts > PGPROC_MAX_CACHED_SUBXIDS) --- 467,473 ---- TransactionId *children) { PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; /* We need no extra lock since the GXACT isn't valid yet */ if (nsubxacts > PGPROC_MAX_CACHED_SUBXIDS) *************** pg_prepared_xact(PG_FUNCTION_ARGS) *** 725,731 **** { GlobalTransaction gxact = &status->array[status->currIdx++]; PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; Datum values[5]; bool nulls[5]; HeapTuple tuple; --- 725,731 ---- { GlobalTransaction gxact = &status->array[status->currIdx++]; PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; Datum values[5]; bool nulls[5]; HeapTuple tuple; *************** TwoPhaseGetGXact(TransactionId xid) *** 780,786 **** for (i = 0; i < TwoPhaseState->numPrepXacts; i++) { GlobalTransaction gxact = TwoPhaseState->prepXacts[i]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; if (pgxact->xid == xid) { --- 780,786 ---- for (i = 0; i < TwoPhaseState->numPrepXacts; i++) { GlobalTransaction gxact = TwoPhaseState->prepXacts[i]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; if (pgxact->xid == xid) { *************** void *** 947,953 **** StartPrepare(GlobalTransaction gxact) { PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; TransactionId xid = pgxact->xid; TwoPhaseFileHeader hdr; TransactionId *children; --- 947,953 ---- StartPrepare(GlobalTransaction gxact) { PGPROC *proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; TransactionId xid = pgxact->xid; TwoPhaseFileHeader hdr; TransactionId *children; *************** FinishPreparedTransaction(const char *gi *** 1343,1349 **** */ gxact = LockGXact(gid, GetUserId()); proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; xid = pgxact->xid; /* --- 1343,1349 ---- */ gxact = LockGXact(gid, GetUserId()); proc = &ProcGlobal->allProcs[gxact->pgprocno]; ! pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; xid = pgxact->xid; /* *************** CheckPointTwoPhase(XLogRecPtr redo_horiz *** 1623,1629 **** for (i = 0; i < TwoPhaseState->numPrepXacts; i++) { GlobalTransaction gxact = TwoPhaseState->prepXacts[i]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno]; if (gxact->valid && !gxact->ondisk && --- 1623,1629 ---- for (i = 0; i < TwoPhaseState->numPrepXacts; i++) { GlobalTransaction gxact = TwoPhaseState->prepXacts[i]; ! PGXACT *pgxact = &ProcGlobal->allPgXact[gxact->pgprocno].xact; if (gxact->valid && !gxact->ondisk && diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c new file mode 100644 index e5d487d..4af233e *** a/src/backend/storage/ipc/procarray.c --- b/src/backend/storage/ipc/procarray.c *************** typedef struct ProcArrayStruct *** 97,103 **** static ProcArrayStruct *procArray; static PGPROC *allProcs; ! static PGXACT *allPgXact; /* * Bookkeeping for tracking emulated transactions in recovery --- 97,103 ---- static ProcArrayStruct *procArray; static PGPROC *allProcs; ! static PGXACTPadded *allPgXact; /* * Bookkeeping for tracking emulated transactions in recovery *************** ProcArrayRemove(PGPROC *proc, Transactio *** 350,356 **** if (TransactionIdIsValid(latestXid)) { ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); /* Advance global latestCompletedXid while holding the lock */ if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid, --- 350,356 ---- if (TransactionIdIsValid(latestXid)) { ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xact.xid)); /* Advance global latestCompletedXid while holding the lock */ if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid, *************** ProcArrayRemove(PGPROC *proc, Transactio *** 360,366 **** else { /* Shouldn't be trying to remove a live transaction here */ ! Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); } for (index = 0; index < arrayP->numProcs; index++) --- 360,366 ---- else { /* Shouldn't be trying to remove a live transaction here */ ! Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xact.xid)); } for (index = 0; index < arrayP->numProcs; index++) *************** ProcArrayRemove(PGPROC *proc, Transactio *** 400,406 **** void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) { ! PGXACT *pgxact = &allPgXact[proc->pgprocno]; if (TransactionIdIsValid(latestXid)) { --- 400,406 ---- void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) { ! PGXACT *pgxact = &allPgXact[proc->pgprocno].xact; if (TransactionIdIsValid(latestXid)) { *************** ProcArrayEndTransaction(PGPROC *proc, Tr *** 410,416 **** * else is taking a snapshot. See discussion in * src/backend/access/transam/README. */ ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); /* * If we can immediately acquire ProcArrayLock, we clear our own XID --- 410,416 ---- * else is taking a snapshot. See discussion in * src/backend/access/transam/README. */ ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xact.xid)); /* * If we can immediately acquire ProcArrayLock, we clear our own XID *************** ProcArrayEndTransaction(PGPROC *proc, Tr *** 432,438 **** * anyone else's calculation of a snapshot. We might change their * estimate of global xmin, but that's OK. */ ! Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); proc->lxid = InvalidLocalTransactionId; pgxact->xmin = InvalidTransactionId; --- 432,438 ---- * anyone else's calculation of a snapshot. We might change their * estimate of global xmin, but that's OK. */ ! Assert(!TransactionIdIsValid(allPgXact[proc->pgprocno].xact.xid)); proc->lxid = InvalidLocalTransactionId; pgxact->xmin = InvalidTransactionId; *************** ProcArrayGroupClearXid(PGPROC *proc, Tra *** 494,500 **** int extraWaits = -1; /* We should definitely have an XID to clear. */ ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); /* Add ourselves to the list of processes needing a group XID clear. */ proc->procArrayGroupMember = true; --- 494,500 ---- int extraWaits = -1; /* We should definitely have an XID to clear. */ ! Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xact.xid)); /* Add ourselves to the list of processes needing a group XID clear. */ proc->procArrayGroupMember = true; *************** ProcArrayGroupClearXid(PGPROC *proc, Tra *** 560,566 **** while (nextidx != INVALID_PGPROCNO) { PGPROC *proc = &allProcs[nextidx]; ! PGXACT *pgxact = &allPgXact[nextidx]; ProcArrayEndTransactionInternal(proc, pgxact, proc->procArrayGroupMemberXid); --- 560,566 ---- while (nextidx != INVALID_PGPROCNO) { PGPROC *proc = &allProcs[nextidx]; ! PGXACT *pgxact = &allPgXact[nextidx].xact; ProcArrayEndTransactionInternal(proc, pgxact, proc->procArrayGroupMemberXid); *************** ProcArrayGroupClearXid(PGPROC *proc, Tra *** 606,612 **** void ProcArrayClearTransaction(PGPROC *proc) { ! PGXACT *pgxact = &allPgXact[proc->pgprocno]; /* * We can skip locking ProcArrayLock here, because this action does not --- 606,612 ---- void ProcArrayClearTransaction(PGPROC *proc) { ! PGXACT *pgxact = &allPgXact[proc->pgprocno].xact; /* * We can skip locking ProcArrayLock here, because this action does not *************** TransactionIdIsInProgress(TransactionId *** 1078,1084 **** { int pgprocno = arrayP->pgprocnos[i]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId pxid; /* Ignore my own proc --- dealt with it above */ --- 1078,1084 ---- { int pgprocno = arrayP->pgprocnos[i]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId pxid; /* Ignore my own proc --- dealt with it above */ *************** TransactionIdIsActive(TransactionId xid) *** 1234,1240 **** { int pgprocno = arrayP->pgprocnos[i]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId pxid; /* Fetch xid just once - see GetNewTransactionId */ --- 1234,1240 ---- { int pgprocno = arrayP->pgprocnos[i]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId pxid; /* Fetch xid just once - see GetNewTransactionId */ *************** GetOldestXmin(Relation rel, bool ignoreV *** 1344,1350 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; /* * Backend is doing logical decoding which manages xmin separately, --- 1344,1350 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; /* * Backend is doing logical decoding which manages xmin separately, *************** GetSnapshotData(Snapshot snapshot) *** 1583,1589 **** for (index = 0; index < numProcs; index++) { int pgprocno = pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* --- 1583,1589 ---- for (index = 0; index < numProcs; index++) { int pgprocno = pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId xid; /* *************** ProcArrayInstallImportedXmin(Transaction *** 1811,1817 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Ignore procs running LAZY VACUUM */ --- 1811,1817 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId xid; /* Ignore procs running LAZY VACUUM */ *************** ProcArrayInstallRestoredXmin(Transaction *** 1878,1884 **** /* Get lock so source xact can't end while we're doing this */ LWLockAcquire(ProcArrayLock, LW_SHARED); ! pgxact = &allPgXact[proc->pgprocno]; /* * Be certain that the referenced PGPROC has an advertised xmin which is --- 1878,1884 ---- /* Get lock so source xact can't end while we're doing this */ LWLockAcquire(ProcArrayLock, LW_SHARED); ! pgxact = &allPgXact[proc->pgprocno].xact; /* * Be certain that the referenced PGPROC has an advertised xmin which is *************** GetRunningTransactionData(void) *** 1989,1995 **** for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ --- 1989,1995 ---- for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ *************** GetRunningTransactionData(void) *** 2021,2027 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; int nxids; /* --- 2021,2027 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; int nxids; /* *************** GetOldestActiveTransactionId(void) *** 2111,2117 **** for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ --- 2111,2117 ---- for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ *************** GetOldestSafeDecodingTransactionId(void) *** 2202,2208 **** for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ --- 2202,2208 ---- for (index = 0; index < arrayP->numProcs; index++) { int pgprocno = arrayP->pgprocnos[index]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; TransactionId xid; /* Fetch xid just once - see GetNewTransactionId */ *************** GetVirtualXIDsDelayingChkpt(int *nvxids) *** 2257,2263 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; if (pgxact->delayChkpt) { --- 2257,2263 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; if (pgxact->delayChkpt) { *************** HaveVirtualXIDsDelayingChkpt(VirtualTran *** 2297,2303 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; VirtualTransactionId vxid; GET_VXID_FROM_PGPROC(vxid, *proc); --- 2297,2303 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; VirtualTransactionId vxid; GET_VXID_FROM_PGPROC(vxid, *proc); *************** BackendXidGetPid(TransactionId xid) *** 2407,2413 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; if (pgxact->xid == xid) { --- 2407,2413 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; if (pgxact->xid == xid) { *************** GetCurrentVirtualXIDs(TransactionId limi *** 2479,2485 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; if (proc == MyProc) continue; --- 2479,2485 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; if (proc == MyProc) continue; *************** GetConflictingVirtualXIDs(TransactionId *** 2576,2582 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; /* Exclude prepared transactions */ if (proc->pid == 0) --- 2576,2582 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; /* Exclude prepared transactions */ if (proc->pid == 0) *************** MinimumActiveBackends(int min) *** 2690,2696 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; /* * Since we're not holding a lock, need to be prepared to deal with --- 2690,2696 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; /* * Since we're not holding a lock, need to be prepared to deal with *************** CountOtherDBBackends(Oid databaseId, int *** 2867,2873 **** { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno]; if (proc->databaseId != databaseId) continue; --- 2867,2873 ---- { int pgprocno = arrayP->pgprocnos[index]; volatile PGPROC *proc = &allProcs[pgprocno]; ! volatile PGXACT *pgxact = &allPgXact[pgprocno].xact; if (proc->databaseId != databaseId) continue; diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c new file mode 100644 index 44a9f2c..9a1d106 *** a/src/backend/storage/ipc/sinvaladt.c --- b/src/backend/storage/ipc/sinvaladt.c *************** BackendIdGetTransactionIds(int backendID *** 418,424 **** if (proc != NULL) { ! PGXACT *xact = &ProcGlobal->allPgXact[proc->pgprocno]; *xid = xact->xid; *xmin = xact->xmin; --- 418,424 ---- if (proc != NULL) { ! PGXACT *xact = &ProcGlobal->allPgXact[proc->pgprocno].xact; *xid = xact->xid; *xmin = xact->xmin; diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c new file mode 100644 index 3f3e24f..1f5528e *** a/src/backend/storage/lmgr/deadlock.c --- b/src/backend/storage/lmgr/deadlock.c *************** FindLockCycleRecurseMember(PGPROC *check *** 573,579 **** PGPROC *leader; proc = proclock->tag.myProc; ! pgxact = &ProcGlobal->allPgXact[proc->pgprocno]; leader = proc->lockGroupLeader == NULL ? proc : proc->lockGroupLeader; /* A proc never blocks itself or any other lock group member */ --- 573,579 ---- PGPROC *leader; proc = proclock->tag.myProc; ! pgxact = &ProcGlobal->allPgXact[proc->pgprocno].xact; leader = proc->lockGroupLeader == NULL ? proc : proc->lockGroupLeader; /* A proc never blocks itself or any other lock group member */ diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c new file mode 100644 index dba3809..714b6bf *** a/src/backend/storage/lmgr/lock.c --- b/src/backend/storage/lmgr/lock.c *************** GetRunningTransactionLocks(int *nlocks) *** 3806,3812 **** proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION) { PGPROC *proc = proclock->tag.myProc; ! PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno]; LOCK *lock = proclock->tag.myLock; TransactionId xid = pgxact->xid; --- 3806,3812 ---- proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION) { PGPROC *proc = proclock->tag.myProc; ! PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno].xact; LOCK *lock = proclock->tag.myLock; TransactionId xid = pgxact->xid; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c new file mode 100644 index 9a758bd..a555b2a *** a/src/backend/storage/lmgr/proc.c --- b/src/backend/storage/lmgr/proc.c *************** void *** 160,166 **** InitProcGlobal(void) { PGPROC *procs; ! PGXACT *pgxacts; int i, j; bool found; --- 160,166 ---- InitProcGlobal(void) { PGPROC *procs; ! PGXACTPadded *pgxacts; int i, j; bool found; *************** InitProcGlobal(void) *** 211,218 **** * multiprocessor system. There is one PGXACT structure for every PGPROC * structure. */ ! pgxacts = (PGXACT *) ShmemAlloc(TotalProcs * sizeof(PGXACT)); ! MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACT)); ProcGlobal->allPgXact = pgxacts; for (i = 0; i < TotalProcs; i++) --- 211,218 ---- * multiprocessor system. There is one PGXACT structure for every PGPROC * structure. */ ! pgxacts = (PGXACTPadded *) ShmemAlloc(TotalProcs * sizeof(PGXACTPadded)); ! MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACTPadded)); ProcGlobal->allPgXact = pgxacts; for (i = 0; i < TotalProcs; i++) *************** InitProcess(void) *** 339,345 **** (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("sorry, too many clients already"))); } ! MyPgXact = &ProcGlobal->allPgXact[MyProc->pgprocno]; /* * Cross-check that the PGPROC is of the type we expect; if this were not --- 339,345 ---- (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("sorry, too many clients already"))); } ! MyPgXact = &ProcGlobal->allPgXact[MyProc->pgprocno].xact; /* * Cross-check that the PGPROC is of the type we expect; if this were not *************** InitAuxiliaryProcess(void) *** 526,532 **** ((volatile PGPROC *) auxproc)->pid = MyProcPid; MyProc = auxproc; ! MyPgXact = &ProcGlobal->allPgXact[auxproc->pgprocno]; SpinLockRelease(ProcStructLock); --- 526,532 ---- ((volatile PGPROC *) auxproc)->pid = MyProcPid; MyProc = auxproc; ! MyPgXact = &ProcGlobal->allPgXact[auxproc->pgprocno].xact; SpinLockRelease(ProcStructLock); *************** ProcSleep(LOCALLOCK *locallock, LockMeth *** 1241,1247 **** if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel) { PGPROC *autovac = GetBlockingAutoVacuumPgproc(); ! PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno]; LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); --- 1241,1247 ---- if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel) { PGPROC *autovac = GetBlockingAutoVacuumPgproc(); ! PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno].xact; LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h new file mode 100644 index f576f05..0686426 *** a/src/include/storage/proc.h --- b/src/include/storage/proc.h *************** typedef struct PGXACT *** 209,214 **** --- 209,225 ---- } PGXACT; /* + * Cacheline aligned PGXACT which allows us to put each PGXACT to individual + * cacheline. Assuming PGXACTs are under intensive write, cacheline alignment + * reduce cache misses during GetSnapshotData(). + */ + typedef union PGXACTPadded + { + PGXACT xact; + char pad[PG_CACHE_LINE_SIZE]; + } PGXACTPadded; + + /* * There is one ProcGlobal struct for the whole database cluster. */ typedef struct PROC_HDR *************** typedef struct PROC_HDR *** 216,222 **** /* Array of PGPROC structures (not including dummies for prepared txns) */ PGPROC *allProcs; /* Array of PGXACT structures (not including dummies for prepared txns) */ ! PGXACT *allPgXact; /* Length of allProcs array */ uint32 allProcCount; /* Head of list of free PGPROC structures */ --- 227,233 ---- /* Array of PGPROC structures (not including dummies for prepared txns) */ PGPROC *allProcs; /* Array of PGXACT structures (not including dummies for prepared txns) */ ! PGXACTPadded *allPgXact; /* Length of allProcs array */ uint32 allProcCount; /* Head of list of free PGPROC structures */