diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 4f3c5c9..cf465ce 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -399,26 +399,155 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
 		 */
 		Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid));
 
-		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+		/*
+		 * If we get the lock then clear the advertised Xid, else set
+		 * the flag (which indicates that advertised Xid needs to be clear
+		 * for this proc) and push this proc to pendingClearXidList.
+		 * Except one proc, all other proc's will wait for their Xid to be
+		 * cleared. The only allowed proc will attempt the lock acquiration,
+		 * after acquring the lock, pop all of the requests off the list
+		 * using compare-and-swap, servicing each one before moving to next
+		 * proc, and clearing their Xids.  After servicing all the requests
+		 * on pendingClearXidList, release the lock and once again go through
+		 * the saved pendingClearXidList and wake all the processes waiting
+		 * for their Xid to be cleared.  To set the appropriate value for
+		 * ShmemVariableCache->latestCompletedXid, we need to advertise
+		 * latestXid incase proc needs to be pushed to pendingClearXidList.
+		 */
+		if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
+		{
+			pgxact->xid = InvalidTransactionId;
+			proc->lxid = InvalidLocalTransactionId;
+			pgxact->xmin = InvalidTransactionId;
+			/* must be cleared with xid/xmin: */
+			pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
+			pgxact->delayChkpt = false;		/* be sure this is cleared in abort */
+			proc->recoveryConflictPending = false;
+
+			/* Clear the subtransaction-XID cache too while holding the lock */
+			pgxact->nxids = 0;
+			pgxact->overflowed = false;
+
+			/* Also advance global latestCompletedXid while holding the lock */
+			if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid,
+									  latestXid))
+				ShmemVariableCache->latestCompletedXid = latestXid;
 
-		pgxact->xid = InvalidTransactionId;
-		proc->lxid = InvalidLocalTransactionId;
-		pgxact->xmin = InvalidTransactionId;
-		/* must be cleared with xid/xmin: */
-		pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
-		pgxact->delayChkpt = false;		/* be sure this is cleared in abort */
-		proc->recoveryConflictPending = false;
+			LWLockRelease(ProcArrayLock);
+		}
+		else
+		{
+			/* use volatile pointer to prevent code rearrangement */
+			volatile PROC_HDR *procglobal = ProcGlobal;
+			PGPROC_LIST	*nonempty_pending_clear_xid_list = NULL;
+			PGPROC_LIST	*pendingClearXidElem, *wake_pendingClearXidElem;
+			PGPROC		*proc_to_clear;
+			PGXACT		*pgxact_to_clear;
+			int			extraWaits = 0;
 
-		/* Clear the subtransaction-XID cache too while holding the lock */
-		pgxact->nxids = 0;
-		pgxact->overflowed = false;
+			proc->clearXid = true;
 
-		/* Also advance global latestCompletedXid while holding the lock */
-		if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid,
-								  latestXid))
-			ShmemVariableCache->latestCompletedXid = latestXid;
+			/*
+			 * Add the proc to pending pendingClearXidList list and advertise
+			 * the latestXid, so that latestCompletedXid can be updated by the
+			 * process which clears current process xid.
+			 */
+			proc->backendLatestXid = latestXid;
+			while (true)
+			{
+				proc->pendingClearXIDLinks.next = procglobal->pendingClearXidList;
+				pg_read_barrier();
+				nonempty_pending_clear_xid_list = proc->pendingClearXIDLinks.next;
+				if (pg_atomic_compare_exchange_u64((volatile pg_atomic_uint64*) &procglobal->pendingClearXidList,
+												   (uint64*)&proc->pendingClearXIDLinks.next,
+												   (uint64)&proc->pendingClearXIDLinks))
+					break;
+			}
 
-		LWLockRelease(ProcArrayLock);
+			/*
+			 * only first process which has seen the pending clear xid list as
+			 * empty will group clear all the xid's on pending list, all other
+			 * processes will wait for their xid to be cleared.
+			 */
+			if (nonempty_pending_clear_xid_list)
+			{
+				for (;;)
+				{
+					PGSemaphoreLock(&proc->sem);
+					if (!proc->clearXid)
+					{
+						/* logic similar to lwlock.c is used for any absorbed wakeups. */
+						while (extraWaits-- > 0)
+							PGSemaphoreUnlock(&proc->sem);
+						return;
+					}
+					extraWaits++;
+				}
+			}
+
+			LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+			while (true)
+			{
+				pendingClearXidElem = procglobal->pendingClearXidList;
+				if (pg_atomic_compare_exchange_u64((volatile pg_atomic_uint64*) &procglobal->pendingClearXidList,
+													(uint64*)&pendingClearXidElem,
+													(uint64)NULL))
+					break;
+			}
+
+			/* save the list of procs whose xid needs to be cleared to wake them up. */
+			wake_pendingClearXidElem = pendingClearXidElem;
+
+			while (pendingClearXidElem)
+			{
+				proc_to_clear = (PGPROC *) (((char *) pendingClearXidElem) -
+											offsetof(PGPROC, pendingClearXIDLinks));
+
+				pgxact_to_clear = &allPgXact[proc_to_clear->pgprocno];
+
+				pgxact_to_clear->xid = InvalidTransactionId;
+				proc_to_clear->lxid = InvalidLocalTransactionId;
+				pgxact_to_clear->xmin = InvalidTransactionId;
+				/* must be cleared with xid/xmin: */
+				pgxact_to_clear->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
+				pgxact_to_clear->delayChkpt = false;		/* be sure this is cleared in abort */
+				proc_to_clear->recoveryConflictPending = false;
+
+				/* Clear the subtransaction-XID cache too while holding the lock */
+				pgxact_to_clear->nxids = 0;
+				pgxact_to_clear->overflowed = false;
+
+
+				/* Also advance global latestCompletedXid while holding the lock */
+				if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid,
+											proc_to_clear->backendLatestXid))
+					ShmemVariableCache->latestCompletedXid = proc_to_clear->backendLatestXid;
+
+				/*
+				 * move to next proc in list.
+				 */
+				pendingClearXidElem = pendingClearXidElem->next;
+			}
+
+			LWLockRelease(ProcArrayLock);
+
+			while (wake_pendingClearXidElem)
+			{
+				proc_to_clear = (PGPROC *) (((char *) wake_pendingClearXidElem) -
+											offsetof(PGPROC, pendingClearXIDLinks));
+
+				wake_pendingClearXidElem = wake_pendingClearXidElem->next;
+
+				/* Mark that Xid has cleared for this proc */
+				proc_to_clear->clearXid = false;
+
+				pg_write_barrier();
+
+				if (proc_to_clear != MyProc)
+					PGSemaphoreUnlock(&proc_to_clear->sem);
+			}
+		}
 	}
 	else
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 455ad26..9fb62a6 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -261,6 +261,8 @@ InitProcGlobal(void)
 			SHMQueueInit(&(procs[i].myProcLocks[j]));
 	}
 
+	ProcGlobal->pendingClearXidList = NULL;
+
 	/*
 	 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
 	 * processes and prepared transactions.
@@ -385,6 +387,11 @@ InitProcess(void)
 	MyProc->syncRepState = SYNC_REP_NOT_WAITING;
 	SHMQueueElemInit(&(MyProc->syncRepLinks));
 
+	/* Initialize fields for clearing XID */
+	MyProc->clearXid = false;
+	MyProc->backendLatestXid = InvalidTransactionId;
+	MyProc->pendingClearXIDLinks.next = NULL;
+
 	/*
 	 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
 	 * on it.  That allows us to repoint the process latch, which so far
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index e807a2e..8685636 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -59,6 +59,17 @@ struct XidCache
 #define		FP_LOCK_SLOTS_PER_BACKEND 16
 
 /*
+ * List to link PGPROC structures for the cases when they
+ * can't be linked via SHM_QUEUE like when we want to operate
+ * the list using atomic operations.  Currently this is used
+ * to link PGPROC's for clearing their XID information.
+ */
+typedef struct PGPROC_LIST
+{
+	struct PGPROC_LIST *next;
+} PGPROC_LIST;
+
+/*
  * Each backend has a PGPROC struct in shared memory.  There is also a list of
  * currently-unused PGPROC structs that will be reallocated to new backends.
  *
@@ -134,6 +145,15 @@ struct PGPROC
 
 	struct XidCache subxids;	/* cache for subtransaction XIDs */
 
+	/*
+	 * Info to allow us to advertise that we want backend
+	 * holding the ProcArrayLock can clear our xid.
+	 */
+	bool			clearXid;
+	TransactionId	backendLatestXid;
+	PGPROC_LIST		pendingClearXIDLinks;	/* list link if process is in
+											 * pendingClearXIDList */
+
 	/* Per-backend LWLock.  Protects fields below. */
 	LWLock	   *backendLock;	/* protects the fields below */
 
@@ -195,6 +215,8 @@ typedef struct PROC_HDR
 	PGPROC	   *autovacFreeProcs;
 	/* Head of list of bgworker free PGPROC structures */
 	PGPROC	   *bgworkerFreeProcs;
+	/* list of PGPROC structures that need to have their XIDs cleared */
+	PGPROC_LIST	*pendingClearXidList;
 	/* WALWriter process's latch */
 	Latch	   *walwriterLatch;
 	/* Checkpointer process's latch */
