From 11635c3f6fe1961dddc1155dfc4de145fa007c88 Mon Sep 17 00:00:00 2001
From: Neil Conway <neilc@samurai.com>
Date: Fri, 4 Feb 2005 02:04:53 +0000
Subject: [PATCH] Refactor some duplicated code in lock.c: create
 UnGrantLock(), move code from LockRelease() and LockReleaseAll() into it.
 From Heikki Linnakangas.

---
 src/backend/storage/lmgr/lock.c | 121 +++++++++++++++++---------------
 1 file changed, 65 insertions(+), 56 deletions(-)

diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 7bb89e5a103..76b2ff9b480 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.145 2004/12/31 22:01:05 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.146 2005/02/04 02:04:53 neilc Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -166,6 +166,8 @@ static int WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
 		   ResourceOwner owner);
 static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
 				 int *myHolding);
+static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
+						PROCLOCK *proclock, LockMethod lockMethodTable);
 
 
 /*
@@ -957,6 +959,65 @@ GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 	Assert(lock->nGranted <= lock->nRequested);
 }
 
+/*
+ * UnGrantLock -- opposite of GrantLock. 
+ *
+ * Updates the lock and proclock data structures to show that the lock
+ * is no longer held nor requested by the current holder.
+ *
+ * Returns true if there were any waiters waiting on the lock that
+ * should now be woken up with ProcLockWakeup.
+ */
+static bool
+UnGrantLock(LOCK *lock, LOCKMODE lockmode,
+			PROCLOCK *proclock, LockMethod lockMethodTable)
+{
+	bool wakeupNeeded = false;
+
+	Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
+	Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
+	Assert(lock->nGranted <= lock->nRequested);
+
+	/*
+	 * fix the general lock stats
+	 */
+	lock->nRequested--;
+	lock->requested[lockmode]--;
+	lock->nGranted--;
+	lock->granted[lockmode]--;
+
+	if (lock->granted[lockmode] == 0)
+	{
+		/* change the conflict mask.  No more of this lock type. */
+		lock->grantMask &= LOCKBIT_OFF(lockmode);
+	}
+
+	LOCK_PRINT("UnGrantLock: updated", lock, lockmode);
+	Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
+	Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
+	Assert(lock->nGranted <= lock->nRequested);
+
+	/*
+	 * We need only run ProcLockWakeup if the released lock conflicts with
+	 * at least one of the lock types requested by waiter(s).  Otherwise
+	 * whatever conflict made them wait must still exist.  NOTE: before
+	 * MVCC, we could skip wakeup if lock->granted[lockmode] was still
+	 * positive. But that's not true anymore, because the remaining
+	 * granted locks might belong to some waiter, who could now be
+	 * awakened because he doesn't conflict with his own locks.
+	 */
+	if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
+		wakeupNeeded = true;
+
+	/*
+	 * Now fix the per-proclock state.
+	 */
+	proclock->holdMask &= LOCKBIT_OFF(lockmode);
+	PROCLOCK_PRINT("UnGrantLock: updated", proclock);
+
+	return wakeupNeeded;
+}
+
 /*
  * GrantLockLocal -- update the locallock data structures to show
  *		the lock request has been granted.
@@ -1265,46 +1326,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
 		RemoveLocalLock(locallock);
 		return FALSE;
 	}
-	Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
-	Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
-	Assert(lock->nGranted <= lock->nRequested);
-
-	/*
-	 * fix the general lock stats
-	 */
-	lock->nRequested--;
-	lock->requested[lockmode]--;
-	lock->nGranted--;
-	lock->granted[lockmode]--;
-
-	if (lock->granted[lockmode] == 0)
-	{
-		/* change the conflict mask.  No more of this lock type. */
-		lock->grantMask &= LOCKBIT_OFF(lockmode);
-	}
-
-	LOCK_PRINT("LockRelease: updated", lock, lockmode);
-	Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
-	Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
-	Assert(lock->nGranted <= lock->nRequested);
-
-	/*
-	 * We need only run ProcLockWakeup if the released lock conflicts with
-	 * at least one of the lock types requested by waiter(s).  Otherwise
-	 * whatever conflict made them wait must still exist.  NOTE: before
-	 * MVCC, we could skip wakeup if lock->granted[lockmode] was still
-	 * positive. But that's not true anymore, because the remaining
-	 * granted locks might belong to some waiter, who could now be
-	 * awakened because he doesn't conflict with his own locks.
-	 */
-	if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
-		wakeupNeeded = true;
 
-	/*
-	 * Now fix the per-proclock state.
-	 */
-	proclock->holdMask &= LOCKBIT_OFF(lockmode);
-	PROCLOCK_PRINT("LockRelease: updated", proclock);
+	wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
 
 	/*
 	 * If this was my last hold on this lock, delete my entry in the
@@ -1483,22 +1506,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
 			for (i = 1; i <= numLockModes; i++)
 			{
 				if (proclock->holdMask & LOCKBIT_ON(i))
-				{
-					lock->requested[i]--;
-					lock->granted[i]--;
-					Assert(lock->requested[i] >= 0 && lock->granted[i] >= 0);
-					if (lock->granted[i] == 0)
-						lock->grantMask &= LOCKBIT_OFF(i);
-					lock->nRequested--;
-					lock->nGranted--;
-
-					/*
-					 * Read comments in LockRelease
-					 */
-					if (!wakeupNeeded &&
-						lockMethodTable->conflictTab[i] & lock->waitMask)
-						wakeupNeeded = true;
-				}
+					wakeupNeeded |= UnGrantLock(lock, i, proclock,
+												lockMethodTable);
 			}
 		}
 		Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
-- 
GitLab