From 11635c3f6fe1961dddc1155dfc4de145fa007c88 Mon Sep 17 00:00:00 2001 From: Neil Conway 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 7bb89e5a10..76b2ff9b48 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));