Refactor some duplicated code in lock.c: create UnGrantLock(), move code
authorNeil Conway
Fri, 4 Feb 2005 02:04:53 +0000 (02:04 +0000)
committerNeil Conway
Fri, 4 Feb 2005 02:04:53 +0000 (02:04 +0000)
from LockRelease() and LockReleaseAll() into it. From Heikki Linnakangas.

src/backend/storage/lmgr/lock.c

index 7bb89e5a10321fe6accadd1b5342fddbc54b1c9d..76b2ff9b480451ef5ad04ff2d2b456c865734ae5 100644 (file)
@@ -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));