88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.146 2005/02/04 02:04:53 neilc Exp $
11+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.147 2005/03/01 21:14:59 tgl Exp $
1212 *
1313 * NOTES
1414 * Outside modules can create a lock table and acquire/release
@@ -993,9 +993,6 @@ UnGrantLock(LOCK *lock, LOCKMODE lockmode,
993993 }
994994
995995 LOCK_PRINT ("UnGrantLock: updated" , lock , lockmode );
996- Assert ((lock -> nRequested >= 0 ) && (lock -> requested [lockmode ] >= 0 ));
997- Assert ((lock -> nGranted >= 0 ) && (lock -> granted [lockmode ] >= 0 ));
998- Assert (lock -> nGranted <= lock -> nRequested );
999996
1000997 /*
1001998 * We need only run ProcLockWakeup if the released lock conflicts with
@@ -1115,8 +1112,7 @@ WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
11151112 {
11161113 /*
11171114 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
1118- * now. Removal of the proclock and lock objects, if no longer
1119- * needed, will happen in xact cleanup (see above for motivation).
1115+ * now.
11201116 */
11211117 awaitedLock = NULL ;
11221118 LOCK_PRINT ("WaitOnLock: aborting on lock" ,
@@ -1148,22 +1144,21 @@ WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
11481144 *
11491145 * Locktable lock must be held by caller.
11501146 *
1151- * NB: this does not remove the process' proclock object, nor the lock object,
1152- * even though their counts might now have gone to zero. That will happen
1153- * during a subsequent LockReleaseAll call, which we expect will happen
1154- * during transaction cleanup. (Removal of a proc from its wait queue by
1155- * this routine can only happen if we are aborting the transaction.)
1147+ * NB: this does not clean up any locallock object that may exist for the lock.
11561148 */
11571149void
11581150RemoveFromWaitQueue (PGPROC * proc )
11591151{
11601152 LOCK * waitLock = proc -> waitLock ;
1153+ PROCLOCK * proclock = proc -> waitProcLock ;
11611154 LOCKMODE lockmode = proc -> waitLockMode ;
1155+ LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD (* waitLock );
11621156
11631157 /* Make sure proc is waiting */
11641158 Assert (proc -> links .next != INVALID_OFFSET );
11651159 Assert (waitLock );
11661160 Assert (waitLock -> waitProcs .size > 0 );
1161+ Assert (0 < lockmethodid && lockmethodid < NumLockMethods );
11671162
11681163 /* Remove proc from lock's wait queue */
11691164 SHMQueueDelete (& (proc -> links ));
@@ -1183,8 +1178,32 @@ RemoveFromWaitQueue(PGPROC *proc)
11831178 proc -> waitLock = NULL ;
11841179 proc -> waitProcLock = NULL ;
11851180
1181+ /*
1182+ * Delete the proclock immediately if it represents no already-held locks.
1183+ * This must happen now because if the owner of the lock decides to release
1184+ * it, and the requested/granted counts then go to zero, LockRelease
1185+ * expects there to be no remaining proclocks.
1186+ */
1187+ if (proclock -> holdMask == 0 )
1188+ {
1189+ PROCLOCK_PRINT ("RemoveFromWaitQueue: deleting proclock" , proclock );
1190+ SHMQueueDelete (& proclock -> lockLink );
1191+ SHMQueueDelete (& proclock -> procLink );
1192+ proclock = (PROCLOCK * ) hash_search (LockMethodProcLockHash [lockmethodid ],
1193+ (void * ) & (proclock -> tag ),
1194+ HASH_REMOVE , NULL );
1195+ if (!proclock )
1196+ elog (WARNING , "proclock table corrupted" );
1197+ }
1198+
1199+ /*
1200+ * There should still be some requests for the lock ... else what were
1201+ * we waiting for? Therefore no need to delete the lock object.
1202+ */
1203+ Assert (waitLock -> nRequested > 0 );
1204+
11861205 /* See if any other waiters for the lock can be woken up now */
1187- ProcLockWakeup (GetLocksMethodTable ( waitLock ) , waitLock );
1206+ ProcLockWakeup (LockMethods [ lockmethodid ] , waitLock );
11881207}
11891208
11901209/*
@@ -1207,7 +1226,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
12071226 PROCLOCK * proclock ;
12081227 LWLockId masterLock ;
12091228 LockMethod lockMethodTable ;
1210- bool wakeupNeeded = false ;
1229+ bool wakeupNeeded ;
12111230
12121231#ifdef LOCK_DEBUG
12131232 if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks )
@@ -1335,7 +1354,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
13351354 */
13361355 if (proclock -> holdMask == 0 )
13371356 {
1338- PROCLOCK_PRINT ("LockRelease: deleting" , proclock );
1357+ PROCLOCK_PRINT ("LockRelease: deleting proclock " , proclock );
13391358 SHMQueueDelete (& proclock -> lockLink );
13401359 SHMQueueDelete (& proclock -> procLink );
13411360 proclock = (PROCLOCK * ) hash_search (LockMethodProcLockHash [lockmethodid ],
@@ -1356,6 +1375,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
13561375 * We've just released the last lock, so garbage-collect the lock
13571376 * object.
13581377 */
1378+ LOCK_PRINT ("LockRelease: deleting lock" , lock , lockmode );
13591379 Assert (SHMQueueEmpty (& (lock -> procLocks )));
13601380 lock = (LOCK * ) hash_search (LockMethodLockHash [lockmethodid ],
13611381 (void * ) & (lock -> tag ),
0 commit comments