From 137abc33199e91878b55fa054e0c409074e5856a Mon Sep 17 00:00:00 2001 From: Jingxian Li Date: Tue, 28 Nov 2023 16:01:48 +0800 Subject: [PATCH] LockAcquireExtended improvement --- src/backend/storage/lmgr/lock.c | 66 +++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index b8c57b3e16..e0ce691941 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -357,6 +357,8 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP) static uint32 proclock_hash(const void *key, Size keysize); static void RemoveLocalLock(LOCALLOCK *locallock); +static bool CheckLocalLockConflictTabCover(LockMethod lockMethodTable, + const LOCKTAG *locktag, LOCKMODE lockmode); static PROCLOCK *SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode); static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner); @@ -774,6 +776,7 @@ LockAcquireExtended(const LOCKTAG *locktag, uint32 hashcode; LWLock *partitionLock; bool found_conflict; + bool found_locallock_cover; bool log_lock = false; if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods)) @@ -938,6 +941,8 @@ LockAcquireExtended(const LOCKTAG *locktag, } } + found_locallock_cover = CheckLocalLockConflictTabCover(lockMethodTable, locktag, lockmode); + /* * If this lock could potentially have been taken via the fast-path by * some other backend, we must (temporarily) disable further use of the @@ -949,21 +954,24 @@ LockAcquireExtended(const LOCKTAG *locktag, uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); BeginStrongLockAcquire(locallock, fasthashcode); - if (!FastPathTransferRelationLocks(lockMethodTable, locktag, - hashcode)) + if (!found_locallock_cover) { - AbortStrongLockAcquire(); - if (locallock->nLocks == 0) - RemoveLocalLock(locallock); - if (locallockp) - *locallockp = NULL; - if (reportMemoryError) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"), - errhint("You might need to increase %s.", "max_locks_per_transaction"))); - else - return LOCKACQUIRE_NOT_AVAIL; + if (!FastPathTransferRelationLocks(lockMethodTable, locktag, + hashcode)) + { + AbortStrongLockAcquire(); + if (locallock->nLocks == 0) + RemoveLocalLock(locallock); + if (locallockp) + *locallockp = NULL; + if (reportMemoryError) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of shared memory"), + errhint("You might need to increase %s.", "max_locks_per_transaction"))); + else + return LOCKACQUIRE_NOT_AVAIL; + } } } @@ -1012,7 +1020,9 @@ LockAcquireExtended(const LOCKTAG *locktag, * wait queue. Otherwise, check for conflict with already-held locks. * (That's last because most complex check.) */ - if (lockMethodTable->conflictTab[lockmode] & lock->waitMask) + if (found_locallock_cover) + found_conflict = false; + else if (lockMethodTable->conflictTab[lockmode] & lock->waitMask) found_conflict = true; else found_conflict = LockCheckConflicts(lockMethodTable, lockmode, @@ -1137,6 +1147,32 @@ LockAcquireExtended(const LOCKTAG *locktag, return LOCKACQUIRE_OK; } +/* + * CheckLocalLockConflictTabCover -- test if there is a local lock + * whose conflictTab covers the requested lock's + * + * Returns true if any such local lock found, false if not. + */ +static bool +CheckLocalLockConflictTabCover(LockMethod lockMethodTable, + const LOCKTAG *locktag, LOCKMODE lockmode) +{ + int conflictMask = lockMethodTable->conflictTab[lockmode]; + + for (int i = lockMethodTable->numLockModes; i > lockmode; i--) + { + if ((lockMethodTable->conflictTab[i] & conflictMask) == conflictMask) + { + if (LockHeldByMe(locktag, (LOCKMODE) i)) + { + return true; + } + } + } + + return false; +} + /* * Find or create LOCK and PROCLOCK objects as needed for a new lock * request. -- 2.37.1.windows.1