@@ -360,7 +360,8 @@ static PROCLOCK *SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
360
360
static void GrantLockLocal (LOCALLOCK * locallock , ResourceOwner owner );
361
361
static void BeginStrongLockAcquire (LOCALLOCK * locallock , uint32 fasthashcode );
362
362
static void FinishStrongLockAcquire (void );
363
- static void WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner );
363
+ static void WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner ,
364
+ bool dontWait );
364
365
static void ReleaseLockIfHeld (LOCALLOCK * locallock , bool sessionLock );
365
366
static void LockReassignOwner (LOCALLOCK * locallock , ResourceOwner parent );
366
367
static bool UnGrantLock (LOCK * lock , LOCKMODE lockmode ,
@@ -1024,50 +1025,15 @@ LockAcquireExtended(const LOCKTAG *locktag,
1024
1025
}
1025
1026
else
1026
1027
{
1027
- /*
1028
- * We can't acquire the lock immediately. If caller specified no
1029
- * blocking, remove useless table entries and return
1030
- * LOCKACQUIRE_NOT_AVAIL without waiting.
1031
- */
1032
- if (dontWait )
1033
- {
1034
- AbortStrongLockAcquire ();
1035
- if (proclock -> holdMask == 0 )
1036
- {
1037
- uint32 proclock_hashcode ;
1038
-
1039
- proclock_hashcode = ProcLockHashCode (& proclock -> tag , hashcode );
1040
- dlist_delete (& proclock -> lockLink );
1041
- dlist_delete (& proclock -> procLink );
1042
- if (!hash_search_with_hash_value (LockMethodProcLockHash ,
1043
- & (proclock -> tag ),
1044
- proclock_hashcode ,
1045
- HASH_REMOVE ,
1046
- NULL ))
1047
- elog (PANIC , "proclock table corrupted" );
1048
- }
1049
- else
1050
- PROCLOCK_PRINT ("LockAcquire: NOWAIT" , proclock );
1051
- lock -> nRequested -- ;
1052
- lock -> requested [lockmode ]-- ;
1053
- LOCK_PRINT ("LockAcquire: conditional lock failed" , lock , lockmode );
1054
- Assert ((lock -> nRequested > 0 ) && (lock -> requested [lockmode ] >= 0 ));
1055
- Assert (lock -> nGranted <= lock -> nRequested );
1056
- LWLockRelease (partitionLock );
1057
- if (locallock -> nLocks == 0 )
1058
- RemoveLocalLock (locallock );
1059
- if (locallockp )
1060
- * locallockp = NULL ;
1061
- return LOCKACQUIRE_NOT_AVAIL ;
1062
- }
1063
-
1064
1028
/*
1065
1029
* Set bitmask of locks this process already holds on this object.
1066
1030
*/
1067
1031
MyProc -> heldLocks = proclock -> holdMask ;
1068
1032
1069
1033
/*
1070
- * Sleep till someone wakes me up.
1034
+ * Sleep till someone wakes me up. We do this even in the dontWait
1035
+ * case, beause while trying to go to sleep, we may discover that we
1036
+ * can acquire the lock immediately after all.
1071
1037
*/
1072
1038
1073
1039
TRACE_POSTGRESQL_LOCK_WAIT_START (locktag -> locktag_field1 ,
@@ -1077,7 +1043,7 @@ LockAcquireExtended(const LOCKTAG *locktag,
1077
1043
locktag -> locktag_type ,
1078
1044
lockmode );
1079
1045
1080
- WaitOnLock (locallock , owner );
1046
+ WaitOnLock (locallock , owner , dontWait );
1081
1047
1082
1048
TRACE_POSTGRESQL_LOCK_WAIT_DONE (locktag -> locktag_field1 ,
1083
1049
locktag -> locktag_field2 ,
@@ -1093,17 +1059,63 @@ LockAcquireExtended(const LOCKTAG *locktag,
1093
1059
*/
1094
1060
1095
1061
/*
1096
- * Check the proclock entry status, in case something in the ipc
1097
- * communication doesn't work correctly.
1062
+ * Check the proclock entry status. If dontWait = true, this is an
1063
+ * expected case; otherwise, it will open happen if something in the
1064
+ * ipc communication doesn't work correctly.
1098
1065
*/
1099
1066
if (!(proclock -> holdMask & LOCKBIT_ON (lockmode )))
1100
1067
{
1101
1068
AbortStrongLockAcquire ();
1102
- PROCLOCK_PRINT ("LockAcquire: INCONSISTENT" , proclock );
1103
- LOCK_PRINT ("LockAcquire: INCONSISTENT" , lock , lockmode );
1104
- /* Should we retry ? */
1105
- LWLockRelease (partitionLock );
1106
- elog (ERROR , "LockAcquire failed" );
1069
+
1070
+ if (dontWait )
1071
+ {
1072
+ /*
1073
+ * We can't acquire the lock immediately. If caller specified
1074
+ * no blocking, remove useless table entries and return
1075
+ * LOCKACQUIRE_NOT_AVAIL without waiting.
1076
+ */
1077
+ if (proclock -> holdMask == 0 )
1078
+ {
1079
+ uint32 proclock_hashcode ;
1080
+
1081
+ proclock_hashcode = ProcLockHashCode (& proclock -> tag ,
1082
+ hashcode );
1083
+ dlist_delete (& proclock -> lockLink );
1084
+ dlist_delete (& proclock -> procLink );
1085
+ if (!hash_search_with_hash_value (LockMethodProcLockHash ,
1086
+ & (proclock -> tag ),
1087
+ proclock_hashcode ,
1088
+ HASH_REMOVE ,
1089
+ NULL ))
1090
+ elog (PANIC , "proclock table corrupted" );
1091
+ }
1092
+ else
1093
+ PROCLOCK_PRINT ("LockAcquire: NOWAIT" , proclock );
1094
+ lock -> nRequested -- ;
1095
+ lock -> requested [lockmode ]-- ;
1096
+ LOCK_PRINT ("LockAcquire: conditional lock failed" ,
1097
+ lock , lockmode );
1098
+ Assert ((lock -> nRequested > 0 ) &&
1099
+ (lock -> requested [lockmode ] >= 0 ));
1100
+ Assert (lock -> nGranted <= lock -> nRequested );
1101
+ LWLockRelease (partitionLock );
1102
+ if (locallock -> nLocks == 0 )
1103
+ RemoveLocalLock (locallock );
1104
+ if (locallockp )
1105
+ * locallockp = NULL ;
1106
+ return LOCKACQUIRE_NOT_AVAIL ;
1107
+ }
1108
+ else
1109
+ {
1110
+ /*
1111
+ * We should have gotten the lock, but somehow that didn't
1112
+ * happen. If we get here, it's a bug.
1113
+ */
1114
+ PROCLOCK_PRINT ("LockAcquire: INCONSISTENT" , proclock );
1115
+ LOCK_PRINT ("LockAcquire: INCONSISTENT" , lock , lockmode );
1116
+ LWLockRelease (partitionLock );
1117
+ elog (ERROR , "LockAcquire failed" );
1118
+ }
1107
1119
}
1108
1120
PROCLOCK_PRINT ("LockAcquire: granted" , proclock );
1109
1121
LOCK_PRINT ("LockAcquire: granted" , lock , lockmode );
@@ -1777,10 +1789,11 @@ MarkLockClear(LOCALLOCK *locallock)
1777
1789
* Caller must have set MyProc->heldLocks to reflect locks already held
1778
1790
* on the lockable object by this process.
1779
1791
*
1780
- * The appropriate partition lock must be held at entry.
1792
+ * The appropriate partition lock must be held at entry, and will still be
1793
+ * held at exit.
1781
1794
*/
1782
1795
static void
1783
- WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner )
1796
+ WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner , bool dontWait )
1784
1797
{
1785
1798
LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD (* locallock );
1786
1799
LockMethod lockMethodTable = LockMethods [lockmethodid ];
@@ -1813,8 +1826,14 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
1813
1826
*/
1814
1827
PG_TRY ();
1815
1828
{
1816
- if (ProcSleep (locallock , lockMethodTable ) != PROC_WAIT_STATUS_OK )
1829
+ /*
1830
+ * If dontWait = true, we handle success and failure in the same way
1831
+ * here. The caller will be able to sort out what has happened.
1832
+ */
1833
+ if (ProcSleep (locallock , lockMethodTable , dontWait ) != PROC_WAIT_STATUS_OK
1834
+ && !dontWait )
1817
1835
{
1836
+
1818
1837
/*
1819
1838
* We failed as a result of a deadlock, see CheckDeadLock(). Quit
1820
1839
* now.
0 commit comments