Hi,

There's two almost identical pieces of code in LockRelease and LockReleaseAll that do the opposite of GrantLock.

Here's a small patch that replaces those pieces with a static UnGrantLock function.

This is preparation for the two-phase commit patch, since that introduces more calls to UnGrantLock.

- Heikki
Index: lock.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.145
diff -c -r1.145 lock.c
*** lock.c      31 Dec 2004 22:01:05 -0000      1.145
--- lock.c      2 Feb 2005 19:40:26 -0000
***************
*** 166,171 ****
--- 166,172 ----
                   ResourceOwner owner);
  static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
                                 int *myHolding);
+ static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, 
LockMethod lockMethodTable);
  
  
  /*
***************
*** 958,963 ****
--- 959,1020 ----
  }
  
  /*
+  * 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 was 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,1310 ****
                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);
  
        /*
         * If this was my last hold on this lock, delete my entry in the
--- 1322,1329 ----
                RemoveLocalLock(locallock);
                return FALSE;
        }
  
!       wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
  
        /*
         * If this was my last hold on this lock, delete my entry in the
***************
*** 1484,1503 ****
                        {
                                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;
                                }
                        }
                }
--- 1503,1509 ----
                        {
                                if (proclock->holdMask & LOCKBIT_ON(i))
                                {
!                                       wakeupNeeded |= UnGrantLock(lock, i, 
proclock, lockMethodTable);
                                }
                        }
                }
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to