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.
- HeikkiIndex: 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 - 1.145
--- lock.c 2 Feb 2005 19:40:26 -
***
*** 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.
!*/
!