|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.145 2004/12/31 22:01:05 pgsql Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.146 2005/02/04 02:04:53 neilc Exp $ |
12 | 12 | *
|
13 | 13 | * NOTES
|
14 | 14 | * Outside modules can create a lock table and acquire/release
|
@@ -166,6 +166,8 @@ static int WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
|
166 | 166 | ResourceOwnerowner);
|
167 | 167 | staticvoidLockCountMyLocks(SHMEM_OFFSETlockOffset,PGPROC*proc,
|
168 | 168 | int*myHolding);
|
| 169 | +staticboolUnGrantLock(LOCK*lock,LOCKMODElockmode, |
| 170 | +PROCLOCK*proclock,LockMethodlockMethodTable); |
169 | 171 |
|
170 | 172 |
|
171 | 173 | /*
|
@@ -957,6 +959,65 @@ GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
|
957 | 959 | Assert(lock->nGranted <=lock->nRequested);
|
958 | 960 | }
|
959 | 961 |
|
| 962 | +/* |
| 963 | + * UnGrantLock -- opposite of GrantLock. |
| 964 | + * |
| 965 | + * Updates the lock and proclock data structures to show that the lock |
| 966 | + * is no longer held nor requested by the current holder. |
| 967 | + * |
| 968 | + * Returns true if there were any waiters waiting on the lock that |
| 969 | + * should now be woken up with ProcLockWakeup. |
| 970 | + */ |
| 971 | +staticbool |
| 972 | +UnGrantLock(LOCK*lock,LOCKMODElockmode, |
| 973 | +PROCLOCK*proclock,LockMethodlockMethodTable) |
| 974 | +{ |
| 975 | +boolwakeupNeeded= false; |
| 976 | + |
| 977 | +Assert((lock->nRequested>0)&& (lock->requested[lockmode]>0)); |
| 978 | +Assert((lock->nGranted>0)&& (lock->granted[lockmode]>0)); |
| 979 | +Assert(lock->nGranted <=lock->nRequested); |
| 980 | + |
| 981 | +/* |
| 982 | + * fix the general lock stats |
| 983 | + */ |
| 984 | +lock->nRequested--; |
| 985 | +lock->requested[lockmode]--; |
| 986 | +lock->nGranted--; |
| 987 | +lock->granted[lockmode]--; |
| 988 | + |
| 989 | +if (lock->granted[lockmode]==0) |
| 990 | +{ |
| 991 | +/* change the conflict mask. No more of this lock type. */ |
| 992 | +lock->grantMask &=LOCKBIT_OFF(lockmode); |
| 993 | +} |
| 994 | + |
| 995 | +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); |
| 999 | + |
| 1000 | +/* |
| 1001 | + * We need only run ProcLockWakeup if the released lock conflicts with |
| 1002 | + * at least one of the lock types requested by waiter(s). Otherwise |
| 1003 | + * whatever conflict made them wait must still exist. NOTE: before |
| 1004 | + * MVCC, we could skip wakeup if lock->granted[lockmode] was still |
| 1005 | + * positive. But that's not true anymore, because the remaining |
| 1006 | + * granted locks might belong to some waiter, who could now be |
| 1007 | + * awakened because he doesn't conflict with his own locks. |
| 1008 | + */ |
| 1009 | +if (lockMethodTable->conflictTab[lockmode]&lock->waitMask) |
| 1010 | +wakeupNeeded= true; |
| 1011 | + |
| 1012 | +/* |
| 1013 | + * Now fix the per-proclock state. |
| 1014 | + */ |
| 1015 | +proclock->holdMask &=LOCKBIT_OFF(lockmode); |
| 1016 | +PROCLOCK_PRINT("UnGrantLock: updated",proclock); |
| 1017 | + |
| 1018 | +returnwakeupNeeded; |
| 1019 | +} |
| 1020 | + |
960 | 1021 | /*
|
961 | 1022 | * GrantLockLocal -- update the locallock data structures to show
|
962 | 1023 | *the lock request has been granted.
|
@@ -1265,46 +1326,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
1265 | 1326 | RemoveLocalLock(locallock);
|
1266 | 1327 | return FALSE;
|
1267 | 1328 | }
|
1268 |
| -Assert((lock->nRequested>0)&& (lock->requested[lockmode]>0)); |
1269 |
| -Assert((lock->nGranted>0)&& (lock->granted[lockmode]>0)); |
1270 |
| -Assert(lock->nGranted <=lock->nRequested); |
1271 |
| - |
1272 |
| -/* |
1273 |
| - * fix the general lock stats |
1274 |
| - */ |
1275 |
| -lock->nRequested--; |
1276 |
| -lock->requested[lockmode]--; |
1277 |
| -lock->nGranted--; |
1278 |
| -lock->granted[lockmode]--; |
1279 |
| - |
1280 |
| -if (lock->granted[lockmode]==0) |
1281 |
| -{ |
1282 |
| -/* change the conflict mask. No more of this lock type. */ |
1283 |
| -lock->grantMask &=LOCKBIT_OFF(lockmode); |
1284 |
| -} |
1285 |
| - |
1286 |
| -LOCK_PRINT("LockRelease: updated",lock,lockmode); |
1287 |
| -Assert((lock->nRequested >=0)&& (lock->requested[lockmode] >=0)); |
1288 |
| -Assert((lock->nGranted >=0)&& (lock->granted[lockmode] >=0)); |
1289 |
| -Assert(lock->nGranted <=lock->nRequested); |
1290 |
| - |
1291 |
| -/* |
1292 |
| - * We need only run ProcLockWakeup if the released lock conflicts with |
1293 |
| - * at least one of the lock types requested by waiter(s). Otherwise |
1294 |
| - * whatever conflict made them wait must still exist. NOTE: before |
1295 |
| - * MVCC, we could skip wakeup if lock->granted[lockmode] was still |
1296 |
| - * positive. But that's not true anymore, because the remaining |
1297 |
| - * granted locks might belong to some waiter, who could now be |
1298 |
| - * awakened because he doesn't conflict with his own locks. |
1299 |
| - */ |
1300 |
| -if (lockMethodTable->conflictTab[lockmode]&lock->waitMask) |
1301 |
| -wakeupNeeded= true; |
1302 | 1329 |
|
1303 |
| -/* |
1304 |
| - * Now fix the per-proclock state. |
1305 |
| - */ |
1306 |
| -proclock->holdMask &=LOCKBIT_OFF(lockmode); |
1307 |
| -PROCLOCK_PRINT("LockRelease: updated",proclock); |
| 1330 | +wakeupNeeded=UnGrantLock(lock,lockmode,proclock,lockMethodTable); |
1308 | 1331 |
|
1309 | 1332 | /*
|
1310 | 1333 | * If this was my last hold on this lock, delete my entry in the
|
@@ -1483,22 +1506,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
|
1483 | 1506 | for (i=1;i <=numLockModes;i++)
|
1484 | 1507 | {
|
1485 | 1508 | if (proclock->holdMask&LOCKBIT_ON(i))
|
1486 |
| -{ |
1487 |
| -lock->requested[i]--; |
1488 |
| -lock->granted[i]--; |
1489 |
| -Assert(lock->requested[i] >=0&&lock->granted[i] >=0); |
1490 |
| -if (lock->granted[i]==0) |
1491 |
| -lock->grantMask &=LOCKBIT_OFF(i); |
1492 |
| -lock->nRequested--; |
1493 |
| -lock->nGranted--; |
1494 |
| - |
1495 |
| -/* |
1496 |
| - * Read comments in LockRelease |
1497 |
| - */ |
1498 |
| -if (!wakeupNeeded&& |
1499 |
| -lockMethodTable->conflictTab[i]&lock->waitMask) |
1500 |
| -wakeupNeeded= true; |
1501 |
| -} |
| 1509 | +wakeupNeeded |=UnGrantLock(lock,i,proclock, |
| 1510 | +lockMethodTable); |
1502 | 1511 | }
|
1503 | 1512 | }
|
1504 | 1513 | Assert((lock->nRequested >=0)&& (lock->nGranted >=0));
|
|