diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 5453549..270af0a 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -482,6 +482,7 @@ static inline bool
 LWLockAcquireCommon(LWLock *l, LWLockMode mode, uint64 *valptr, uint64 val)
 {
 	volatile LWLock *lock = l;
+	volatile uint64 *valp = valptr;
 	PGPROC	   *proc = MyProc;
 	bool		retry = false;
 	bool		result = true;
@@ -637,8 +638,8 @@ LWLockAcquireCommon(LWLock *l, LWLockMode mode, uint64 *valptr, uint64 val)
 	}
 
 	/* If there's a variable associated with this lock, initialize it */
-	if (valptr)
-		*valptr = val;
+	if (valp)
+		*valp = val;
 
 	/* We are done updating shared state of the lock itself. */
 	SpinLockRelease(&lock->mutex);
@@ -1111,6 +1112,7 @@ LWLockRelease(LWLock *l)
 {
 	volatile LWLock *lock = l;
 	PGPROC	   *head;
+	PGPROC	   *tail = NULL;
 	PGPROC	   *proc;
 	int			i;
 
@@ -1145,63 +1147,70 @@ LWLockRelease(LWLock *l)
 
 	/*
 	 * See if I need to awaken any waiters.  If I released a non-last shared
-	 * hold, there cannot be anything to do.  Also, do not awaken any waiters
-	 * if someone has already awakened waiters that haven't yet acquired the
-	 * lock.
+	 * hold, there cannot be anything to do.
 	 */
 	head = lock->head;
-	if (head != NULL)
+	if (head != NULL && lock->exclusive == 0 && lock->shared == 0)
 	{
-		if (lock->exclusive == 0 && lock->shared == 0 && lock->releaseOK)
-		{
-			/*
-			 * Remove the to-be-awakened PGPROCs from the queue.
-			 */
-			bool		releaseOK = true;
-
-			proc = head;
+		proc = head;
 
-			/*
-			 * First wake up any backends that want to be woken up without
-			 * acquiring the lock.
-			 */
-			while (proc->lwWaitMode == LW_WAIT_UNTIL_FREE && proc->lwWaitLink)
-				proc = proc->lwWaitLink;
+		/*
+		 * First wake up any backends that want to be woken up without
+		 * acquiring the lock. They are woken up regardless of releaseOK.
+		 */
+		while (proc && proc->lwWaitMode == LW_WAIT_UNTIL_FREE)
+		{
+			tail = proc;
+			proc = proc->lwWaitLink;
+		}
 
-			/*
-			 * If the front waiter wants exclusive lock, awaken him only.
-			 * Otherwise awaken as many waiters as want shared access.
-			 */
-			if (proc->lwWaitMode != LW_EXCLUSIVE)
+		/*
+		 * If the front waiter (after any LW_WAIT_UNTIL_FREE waiters) wants
+		 * exclusive lock, awaken him only. Otherwise awaken as many waiters
+		 * as want shared access. But do not awaken any waiters if someone has
+		 * already awakened waiters that haven't yet acquired the lock.
+		 */
+		if (proc && lock->releaseOK)
+		{
+			if (proc->lwWaitMode == LW_EXCLUSIVE)
+				tail = proc;
+			else
 			{
-				while (proc->lwWaitLink != NULL &&
-					   proc->lwWaitLink->lwWaitMode != LW_EXCLUSIVE)
+				while (proc && proc->lwWaitMode != LW_EXCLUSIVE)
 				{
-					if (proc->lwWaitMode != LW_WAIT_UNTIL_FREE)
-						releaseOK = false;
+					tail = proc;
 					proc = proc->lwWaitLink;
 				}
 			}
-			/* proc is now the last PGPROC to be released */
-			lock->head = proc->lwWaitLink;
-			proc->lwWaitLink = NULL;
+		}
+		/*
+		 * 'tail' is now the last PGPROC to be released. Unlink the
+		 * to-be-awakened PGPROCs from the queue.
+		 */
+		if (tail)
+		{
+			lock->head = tail->lwWaitLink;
+			tail->lwWaitLink = NULL;
 
 			/*
 			 * Prevent additional wakeups until retryer gets to run. Backends
 			 * that are just waiting for the lock to become free don't retry
 			 * automatically.
 			 */
-			if (proc->lwWaitMode != LW_WAIT_UNTIL_FREE)
-				releaseOK = false;
-
-			lock->releaseOK = releaseOK;
+			if (tail->lwWaitMode != LW_WAIT_UNTIL_FREE)
+				lock->releaseOK = false;
 		}
 		else
 		{
-			/* lock is still held, can't awaken anything */
+			/* didn't wake up anyone after all */
 			head = NULL;
 		}
 	}
+	else
+	{
+		/* lock is still held, can't awaken anything */
+		head = NULL;
+	}
 
 	/* We are done updating shared state of the lock itself. */
 	SpinLockRelease(&lock->mutex);
