*** a/contrib/pgrowlocks/pgrowlocks.c
--- b/contrib/pgrowlocks/pgrowlocks.c
***************
*** 138,151 **** pgrowlocks(PG_FUNCTION_ARGS)
  		infomask = tuple->t_data->t_infomask;
  
  		/*
! 		 * a tuple is locked if HTSU returns BeingUpdated, and if it returns
! 		 * MayBeUpdated but the Xmax is valid and pointing at us.
  		 */
! 		if (htsu == HeapTupleBeingUpdated ||
! 			(htsu == HeapTupleMayBeUpdated &&
! 			 !(infomask & HEAP_XMAX_INVALID) &&
! 			 !(infomask & HEAP_XMAX_IS_MULTI) &&
! 			 (xmax == GetCurrentTransactionIdIfAny())))
  		{
  			char	  **values;
  
--- 138,146 ----
  		infomask = tuple->t_data->t_infomask;
  
  		/*
! 		 * A tuple is locked if HTSU returns BeingUpdated.
  		 */
! 		if (htsu == HeapTupleBeingUpdated)
  		{
  			char	  **values;
  
*** a/src/backend/access/heap/heapam.c
--- b/src/backend/access/heap/heapam.c
***************
*** 2596,2601 **** l1:
--- 2596,2623 ----
  		TransactionId xwait;
  		uint16		infomask;
  
+ 		/*
+ 		 * If any subtransaction of the current top transaction already holds
+ 		 * a lock on this tuple, (and no one else does,) we must skip sleeping
+ 		 * on the xwait; that would lead to us sleeping on our own transaction,
+ 		 * which is unlikely to end up well.
+ 		 *
+ 		 * Note we don't need to do anything about this when the xwait is a
+ 		 * multixact, because that code is already prepared to ignore
+ 		 * subtransactions of the current top transaction.
+ 		 *
+ 		 * This must be done before acquiring our tuple lock, to avoid
+ 		 * deadlocks with other transaction that are already waiting on the
+ 		 * lock we hold.
+ 		 */
+ 		if (!(tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) &&
+ 			TransactionIdIsCurrentTransactionId(
+ 												HeapTupleHeaderGetRawXmax(tp.t_data)))
+ 		{
+ 			Assert(HEAP_XMAX_IS_LOCKED_ONLY(tp.t_data->t_infomask));
+ 		}
+ 		else
+ 		{
  		/* must copy state data before unlocking buffer */
  		xwait = HeapTupleHeaderGetRawXmax(tp.t_data);
  		infomask = tp.t_data->t_infomask;
***************
*** 2630,2638 **** l1:
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
! 			 * If xwait had just locked the tuple then some other xact could
! 			 * update this tuple before we get to this point.  Check for xmax
! 			 * change, and start over if so.
  			 */
  			if (!(tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  				!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
--- 2652,2660 ----
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
! 			 * If xwait had just locked the tuple then some other xact
! 			 * could update this tuple before we get to this point.  Check
! 			 * for xmax change, and start over if so.
  			 */
  			if (!(tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  				!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
***************
*** 2640,2652 **** l1:
  				goto l1;
  
  			/*
! 			 * You might think the multixact is necessarily done here, but not
! 			 * so: it could have surviving members, namely our own xact or
! 			 * other subxacts of this backend.	It is legal for us to delete
! 			 * the tuple in either case, however (the latter case is
! 			 * essentially a situation of upgrading our former shared lock to
! 			 * exclusive).	We don't bother changing the on-disk hint bits
! 			 * since we are about to overwrite the xmax altogether.
  			 */
  		}
  		else
--- 2662,2674 ----
  				goto l1;
  
  			/*
! 			 * You might think the multixact is necessarily done here, but
! 			 * not so: it could have surviving members, namely our own xact
! 			 * or other subxacts of this backend.	It is legal for us to
! 			 * delete the tuple in either case, however (the latter case is
! 			 * essentially a situation of upgrading our former shared lock
! 			 * to exclusive).	We don't bother changing the on-disk hint
! 			 * bits since we are about to overwrite the xmax altogether.
  			 */
  		}
  		else
***************
*** 2656,2664 **** l1:
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
! 			 * xwait is done, but if xwait had just locked the tuple then some
! 			 * other xact could update this tuple before we get to this point.
! 			 * Check for xmax change, and start over if so.
  			 */
  			if ((tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  				!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
--- 2678,2686 ----
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
! 			 * xwait is done, but if xwait had just locked the tuple then
! 			 * some other xact could update this tuple before we get to
! 			 * this point.  Check for xmax change, and start over if so.
  			 */
  			if ((tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  				!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
***************
*** 2668,2673 **** l1:
--- 2690,2696 ----
  			/* Otherwise check if it committed or aborted */
  			UpdateXmaxHintBits(tp.t_data, buffer, xwait);
  		}
+ 		}
  
  		/*
  		 * We may overwrite if previous xmax aborted, or if it committed but
***************
*** 3070,3077 **** l2:
  	}
  	else if (result == HeapTupleBeingUpdated && wait)
  	{
- 		TransactionId xwait;
- 		uint16		infomask;
  		bool		can_continue = false;
  
  		checked_lockers = true;
--- 3093,3098 ----
***************
*** 3089,3094 **** l2:
--- 3110,3143 ----
  		 * heap_update directly.
  		 */
  
+ 		/*
+ 		 * If any subtransaction of the current top transaction already holds
+ 		 * a lock on this tuple, (and no one else does,) we must skip sleeping
+ 		 * on the xwait; that would lead to us sleeping on our own transaction,
+ 		 * which is unlikely to end up well.
+ 		 *
+ 		 * Note we don't need to do anything about this when the xwait is a
+ 		 * multixact, because that code is already prepared to ignore
+ 		 * subtransactions of the current top transaction.
+ 		 *
+ 		 * This must be done before acquiring our tuple lock, to avoid
+ 		 * deadlocks with other transaction that are already waiting on the
+ 		 * lock we hold.
+ 		 */
+ 		if (!(oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) &&
+ 			TransactionIdIsCurrentTransactionId(
+ 												HeapTupleHeaderGetRawXmax(oldtup.t_data)))
+ 		{
+ 			Assert(HEAP_XMAX_IS_LOCKED_ONLY(oldtup.t_data->t_infomask));
+ 
+ 			can_continue = true;
+ 			locker_remains = true;
+ 		}
+ 		else
+ 		{
+ 		TransactionId xwait;
+ 		uint16		infomask;
+ 
  		/* must copy state data before unlocking buffer */
  		xwait = HeapTupleHeaderGetRawXmax(oldtup.t_data);
  		infomask = oldtup.t_data->t_infomask;
***************
*** 3192,3198 **** l2:
  				 */
  				if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 									HeapTupleHeaderGetRawXmax(oldtup.t_data),
  										 xwait))
  					goto l2;
  
--- 3241,3247 ----
  				 */
  				if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 										 HeapTupleHeaderGetRawXmax(oldtup.t_data),
  										 xwait))
  					goto l2;
  
***************
*** 3212,3218 **** l2:
  				 */
  				if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 									HeapTupleHeaderGetRawXmax(oldtup.t_data),
  										 xwait))
  					goto l2;
  
--- 3261,3267 ----
  				 */
  				if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 										 HeapTupleHeaderGetRawXmax(oldtup.t_data),
  										 xwait))
  					goto l2;
  
***************
*** 3222,3227 **** l2:
--- 3271,3277 ----
  					can_continue = true;
  			}
  		}
+ 		}
  
  		result = can_continue ? HeapTupleMayBeUpdated : HeapTupleUpdated;
  	}
***************
*** 3945,3951 **** l3:
  		TransactionId xwait;
  		uint16		infomask;
  		uint16		infomask2;
! 		bool		require_sleep;
  		ItemPointerData t_ctid;
  
  		/* must copy state data before unlocking buffer */
--- 3995,4001 ----
  		TransactionId xwait;
  		uint16		infomask;
  		uint16		infomask2;
! 		bool		require_sleep = true;
  		ItemPointerData t_ctid;
  
  		/* must copy state data before unlocking buffer */
***************
*** 3998,4003 **** l3:
--- 4048,4072 ----
  			pfree(members);
  		}
  
+ 		if (!(infomask & HEAP_XMAX_IS_MULTI) &&
+ 			HEAP_XMAX_IS_LOCKED_ONLY(infomask) &&
+ 			TransactionIdIsCurrentTransactionId(xwait))
+ 		{
+ 			/*
+ 			 * If we already hold a lock on this tuple, (and no one else does,)
+ 			 * no matter what the strength, we can fall through to either
+ 			 * create a new MultiXact including the previous lock and ours, or
+ 			 * just keep the old lock.
+ 			 */
+ 			LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
+ 			/* If xmax changed while we weren't looking, start over */
+ 			if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
+ 				!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
+ 									 xwait))
+ 				goto l3;
+ 		}
+ 		else
+ 		{
  		/*
  		 * Acquire tuple lock to establish our priority for the tuple.
  		 * LockTuple will release us when we are next-in-line for the tuple.
***************
*** 4014,4021 **** l3:
  				if (!ConditionalLockTupleTuplock(relation, tid, mode))
  					ereport(ERROR,
  							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			}
  			else
  				LockTupleTuplock(relation, tid, mode);
--- 4083,4090 ----
  				if (!ConditionalLockTupleTuplock(relation, tid, mode))
  					ereport(ERROR,
  							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							 errmsg("could not obtain lock on row in relation \"%s\"",
! 									RelationGetRelationName(relation))));
  			}
  			else
  				LockTupleTuplock(relation, tid, mode);
***************
*** 4144,4150 **** l3:
  				 * been the case, HeapTupleSatisfiesUpdate would have returned
  				 * MayBeUpdated and we wouldn't be here.
  				 */
! 				nmembers = GetMultiXactIdMembers(xwait, &members, false);
  
  				if (nmembers <= 0)
  				{
--- 4213,4220 ----
  				 * been the case, HeapTupleSatisfiesUpdate would have returned
  				 * MayBeUpdated and we wouldn't be here.
  				 */
! 				nmembers =
! 					GetMultiXactIdMembers(xwait, &members, false);
  
  				if (nmembers <= 0)
  				{
***************
*** 4175,4181 **** l3:
  						 */
  						LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
  						if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
! 							!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
  												 xwait))
  						{
  							pfree(members);
--- 4245,4252 ----
  						 */
  						LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
  						if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
! 							!TransactionIdEquals(
! 												 HeapTupleHeaderGetRawXmax(tuple->t_data),
  												 xwait))
  						{
  							pfree(members);
***************
*** 4195,4201 **** l3:
  				/* if the xmax changed in the meantime, start over */
  				if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 									HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  				/* otherwise, we're good */
--- 4266,4272 ----
  				/* if the xmax changed in the meantime, start over */
  				if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 										 HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  				/* otherwise, we're good */
***************
*** 4259,4265 **** l3:
  				 */
  				if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 									HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  
--- 4330,4336 ----
  				 */
  				if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 										 HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  
***************
*** 4314,4320 **** l3:
  				 */
  				if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 									HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  
--- 4385,4391 ----
  				 */
  				if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
  					!TransactionIdEquals(
! 										 HeapTupleHeaderGetRawXmax(tuple->t_data),
  										 xwait))
  					goto l3;
  
***************
*** 4327,4332 **** l3:
--- 4398,4404 ----
  				UpdateXmaxHintBits(tuple->t_data, *buffer, xwait);
  			}
  		}
+ 		}
  
  		/* By here, we're certain that we hold buffer exclusive lock again */
  
***************
*** 4365,4401 **** failed:
  	old_infomask = tuple->t_data->t_infomask;
  
  	/*
- 	 * We might already hold the desired lock (or stronger), possibly under a
- 	 * different subtransaction of the current top transaction.  If so, there
- 	 * is no need to change state or issue a WAL record.  We already handled
- 	 * the case where this is true for xmax being a MultiXactId, so now check
- 	 * for cases where it is a plain TransactionId.
- 	 *
- 	 * Note in particular that this covers the case where we already hold
- 	 * exclusive lock on the tuple and the caller only wants key share or
- 	 * share lock. It would certainly not do to give up the exclusive lock.
- 	 */
- 	if (!(old_infomask & (HEAP_XMAX_INVALID |
- 						  HEAP_XMAX_COMMITTED |
- 						  HEAP_XMAX_IS_MULTI)) &&
- 		(mode == LockTupleKeyShare ?
- 		 (HEAP_XMAX_IS_KEYSHR_LOCKED(old_infomask) ||
- 		  HEAP_XMAX_IS_SHR_LOCKED(old_infomask) ||
- 		  HEAP_XMAX_IS_EXCL_LOCKED(old_infomask)) :
- 		 mode == LockTupleShare ?
- 		 (HEAP_XMAX_IS_SHR_LOCKED(old_infomask) ||
- 		  HEAP_XMAX_IS_EXCL_LOCKED(old_infomask)) :
- 		 (HEAP_XMAX_IS_EXCL_LOCKED(old_infomask))) &&
- 		TransactionIdIsCurrentTransactionId(xmax))
- 	{
- 		LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
- 		/* Probably can't hold tuple lock here, but may as well check */
- 		if (have_tuple_lock)
- 			UnlockTupleTuplock(relation, tid, mode);
- 		return HeapTupleMayBeUpdated;
- 	}
- 
- 	/*
  	 * If this is the first possibly-multixact-able operation in the current
  	 * transaction, set my per-backend OldestMemberMXactId setting. We can be
  	 * certain that the transaction will never become a member of any older
--- 4437,4442 ----
***************
*** 4622,4630 **** l5:
  		 */
  		if (!MultiXactIdIsRunning(xmax))
  		{
! 			if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) ||
! 				TransactionIdDidAbort(MultiXactIdGetUpdateXid(xmax,
! 															  old_infomask)))
  			{
  				/*
  				 * Reset these bits and restart; otherwise fall through to
--- 4663,4671 ----
  		 */
  		if (!MultiXactIdIsRunning(xmax))
  		{
! 			if ((HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) ||
! 				 !TransactionIdDidCommit(MultiXactIdGetUpdateXid(xmax,
! 																 old_infomask))))
  			{
  				/*
  				 * Reset these bits and restart; otherwise fall through to
*** a/src/backend/access/transam/multixact.c
--- b/src/backend/access/transam/multixact.c
***************
*** 1275,1313 **** retry:
  }
  
  /*
-  * MultiXactHasRunningRemoteMembers
-  * 		Does the given multixact have still-live members from
-  * 		transactions other than our own?
-  */
- bool
- MultiXactHasRunningRemoteMembers(MultiXactId multi)
- {
- 	MultiXactMember *members;
- 	int			nmembers;
- 	int			i;
- 
- 	nmembers = GetMultiXactIdMembers(multi, &members, true);
- 	if (nmembers <= 0)
- 		return false;
- 
- 	for (i = 0; i < nmembers; i++)
- 	{
- 		/* not interested in our own members */
- 		if (TransactionIdIsCurrentTransactionId(members[i].xid))
- 			continue;
- 
- 		if (TransactionIdIsInProgress(members[i].xid))
- 		{
- 			pfree(members);
- 			return true;
- 		}
- 	}
- 
- 	pfree(members);
- 	return false;
- }
- 
- /*
   * mxactMemberComparator
   *		qsort comparison function for MultiXactMember
   *
--- 1275,1280 ----
*** a/src/backend/utils/time/tqual.c
--- b/src/backend/utils/time/tqual.c
***************
*** 701,720 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
  
  				if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  				{
! 					if (MultiXactHasRunningRemoteMembers(xmax))
  						return HeapTupleBeingUpdated;
  					else
  						return HeapTupleMayBeUpdated;
  				}
  
! 				/* if locker is gone, all's well */
  				if (!TransactionIdIsInProgress(xmax))
  					return HeapTupleMayBeUpdated;
! 
! 				if (!TransactionIdIsCurrentTransactionId(xmax))
! 					return HeapTupleBeingUpdated;
! 				else
! 					return HeapTupleMayBeUpdated;
  			}
  
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
--- 701,720 ----
  
  				if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  				{
! 					if (MultiXactIdIsRunning(xmax))
  						return HeapTupleBeingUpdated;
  					else
  						return HeapTupleMayBeUpdated;
  				}
  
! 				/*
! 				 * If the locker is gone, then there is nothing of interest
! 				 * left in this Xmax; otherwise, report the tuple as
! 				 * locked/updated.
! 				 */
  				if (!TransactionIdIsInProgress(xmax))
  					return HeapTupleMayBeUpdated;
! 				return HeapTupleBeingUpdated;
  			}
  
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
***************
*** 726,735 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
  				/* not LOCKED_ONLY, so it has to have an xmax */
  				Assert(TransactionIdIsValid(xmax));
  
! 				/* updating subtransaction must have aborted */
  				if (!TransactionIdIsCurrentTransactionId(xmax))
  				{
! 					if (MultiXactHasRunningRemoteMembers(HeapTupleHeaderGetRawXmax(tuple)))
  						return HeapTupleBeingUpdated;
  					return HeapTupleMayBeUpdated;
  				}
--- 726,735 ----
  				/* not LOCKED_ONLY, so it has to have an xmax */
  				Assert(TransactionIdIsValid(xmax));
  
! 				/* deleting subtransaction must have aborted */
  				if (!TransactionIdIsCurrentTransactionId(xmax))
  				{
! 					if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
  						return HeapTupleBeingUpdated;
  					return HeapTupleMayBeUpdated;
  				}
***************
*** 846,852 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
  	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
  	{
  		if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
! 			return HeapTupleMayBeUpdated;
  		if (HeapTupleHeaderGetCmax(tuple) >= curcid)
  			return HeapTupleSelfUpdated;		/* updated after scan started */
  		else
--- 846,852 ----
  	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
  	{
  		if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
! 			return HeapTupleBeingUpdated;
  		if (HeapTupleHeaderGetCmax(tuple) >= curcid)
  			return HeapTupleSelfUpdated;		/* updated after scan started */
  		else
*** a/src/include/access/multixact.h
--- b/src/include/access/multixact.h
***************
*** 89,95 **** extern bool MultiXactIdIsRunning(MultiXactId multi);
  extern void MultiXactIdSetOldestMember(void);
  extern int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **xids,
  					  bool allow_old);
- extern bool MultiXactHasRunningRemoteMembers(MultiXactId multi);
  extern bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2);
  extern bool MultiXactIdPrecedesOrEquals(MultiXactId multi1,
  							MultiXactId multi2);
--- 89,94 ----
