diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 3bb5ce3..8c55d50 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -255,6 +255,10 @@ static HTAB *LockMethodProcLockHash; static HTAB *LockMethodLocalHash; +/* list of LOCALLOCK structures that each backend acquired */ +static dlist_head LocalLocks = DLIST_STATIC_INIT(LocalLocks); + + /* private state for error cleanup */ static LOCALLOCK *StrongLockInProgress; static LOCALLOCK *awaitedLock; @@ -794,6 +798,7 @@ LockAcquireExtended(const LOCKTAG *locktag, */ if (!found) { + dlist_push_head(&LocalLocks, &locallock->procLink); locallock->lock = NULL; locallock->proclock = NULL; locallock->hashcode = LockTagHashCode(&(localtag.lock)); @@ -1320,6 +1325,7 @@ RemoveLocalLock(LOCALLOCK *locallock) SpinLockRelease(&FastPathStrongRelationLocks->mutex); } + dlist_delete(&locallock->procLink); if (!hash_search(LockMethodLocalHash, (void *) &(locallock->tag), HASH_REMOVE, NULL)) @@ -2088,7 +2094,7 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock) void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) { - HASH_SEQ_STATUS status; + dlist_mutable_iter iter; LockMethod lockMethodTable; int i, numLockModes; @@ -2126,10 +2132,10 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) * pointers. Fast-path locks are cleaned up during the locallock table * scan, though. */ - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) { + locallock = dlist_container(LOCALLOCK, procLink, iter.cur); + /* * If the LOCALLOCK entry is unused, we must've run out of shared * memory while trying to set up this lock. Just forget the local @@ -2362,16 +2368,16 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) void LockReleaseSession(LOCKMETHODID lockmethodid) { - HASH_SEQ_STATUS status; + dlist_mutable_iter iter; LOCALLOCK *locallock; if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods)) elog(ERROR, "unrecognized lock method: %d", lockmethodid); - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) { + locallock = dlist_container(LOCALLOCK, procLink, iter.cur); + /* Ignore items that are not of the specified lock method */ if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid) continue; @@ -2394,13 +2400,14 @@ LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks) { if (locallocks == NULL) { - HASH_SEQ_STATUS status; + dlist_mutable_iter iter; LOCALLOCK *locallock; - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) + { + locallock = dlist_container(LOCALLOCK, procLink, iter.cur); ReleaseLockIfHeld(locallock, false); + } } else { @@ -2493,13 +2500,14 @@ LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks) if (locallocks == NULL) { - HASH_SEQ_STATUS status; + dlist_mutable_iter iter; LOCALLOCK *locallock; - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) + { + locallock = dlist_container(LOCALLOCK, procLink, iter.cur); LockReassignOwner(locallock, parent); + } } else { @@ -3133,8 +3141,7 @@ LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, void AtPrepare_Locks(void) { - HASH_SEQ_STATUS status; - LOCALLOCK *locallock; + dlist_mutable_iter iter; /* * For the most part, we don't need to touch shared memory for this --- @@ -3142,10 +3149,9 @@ AtPrepare_Locks(void) * Fast-path locks are an exception, however: we move any such locks to * the main table before allowing PREPARE TRANSACTION to succeed. */ - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) { + LOCALLOCK *locallock = dlist_container(LOCALLOCK, procLink, iter.cur); TwoPhaseLockRecord record; LOCALLOCKOWNER *lockOwners = locallock->lockOwners; bool haveSessionLock; @@ -3244,8 +3250,7 @@ void PostPrepare_Locks(TransactionId xid) { PGPROC *newproc = TwoPhaseGetDummyProc(xid); - HASH_SEQ_STATUS status; - LOCALLOCK *locallock; + dlist_mutable_iter iter; LOCK *lock; PROCLOCK *proclock; PROCLOCKTAG proclocktag; @@ -3267,10 +3272,9 @@ PostPrepare_Locks(TransactionId xid) * pointing to the same proclock, and we daren't end up with any dangling * pointers. */ - hash_seq_init(&status, LockMethodLocalHash); - - while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) + dlist_foreach_modify(iter, &LocalLocks) { + LOCALLOCK *locallock = dlist_container(LOCALLOCK, procLink, iter.cur); LOCALLOCKOWNER *lockOwners = locallock->lockOwners; bool haveSessionLock; bool haveXactLock; diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index 16b927c..5e39e36 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -18,6 +18,7 @@ #error "lock.h may not be included from frontend code" #endif +#include "lib/ilist.h" #include "storage/lockdefs.h" #include "storage/backendid.h" #include "storage/lwlock.h" @@ -404,15 +405,16 @@ typedef struct LOCALLOCK LOCALLOCKTAG tag; /* unique identifier of locallock entry */ /* data */ + uint32 hashcode; /* copy of LOCKTAG's hash value */ LOCK *lock; /* associated LOCK object, if any */ PROCLOCK *proclock; /* associated PROCLOCK object, if any */ - uint32 hashcode; /* copy of LOCKTAG's hash value */ + dlist_node procLink; /* list link in PGPROC's list of LOCALLOCKs */ int64 nLocks; /* total number of times lock is held */ - bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */ - bool lockCleared; /* we read all sinval msgs for lock */ int numLockOwners; /* # of relevant ResourceOwners */ int maxLockOwners; /* allocated size of array */ LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */ + bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */ + bool lockCleared; /* we read all sinval msgs for lock */ } LOCALLOCK; #define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)