diff options
author | Pavan Deolasee | 2017-02-09 08:05:46 +0000 |
---|---|---|
committer | Pavan Deolasee | 2017-02-09 08:05:46 +0000 |
commit | 7e40411483f6f917f8f316b69b26c8c660afc1c0 (patch) | |
tree | 880ff865336f89a4c554b68fd1491e5737c26822 | |
parent | e7542220d25fad39b753969296510893c9f9915d (diff) |
Handle locking correctly in a global session.
Rearrange code so that we first check if the backend belongs to a global
sessions and if another member of the same session is holding a conflicting
lock. In such cases, the requesting backend does not wait and is granted the
lock immediately.
PG 9.6 changed a few things in this area to support locking for parallel
sessions. May be we can reuse that code in XL, but for now just use XL's code
for supporting distributed sessions
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 13d5379145..37eec5b00a 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -1395,57 +1395,6 @@ LockCheckConflicts(LockMethod lockMethodTable, return STATUS_OK; } - /* If no group locking, it's definitely a conflict. */ - if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL) - { - Assert(proclock->tag.myProc == MyProc); - PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)", - proclock); - return STATUS_FOUND; - } - - /* - * Locks held in conflicting modes by members of our own lock group are - * not real conflicts; we can subtract those out and see if we still have - * a conflict. This is O(N) in the number of processes holding or - * awaiting locks on this object. We could improve that by making the - * shared memory state more complex (and larger) but it doesn't seem worth - * it. - */ - procLocks = &(lock->procLocks); - otherproclock = (PROCLOCK *) - SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink)); - while (otherproclock != NULL) - { - if (proclock != otherproclock && - proclock->groupLeader == otherproclock->groupLeader && - (otherproclock->holdMask & conflictMask) != 0) - { - int intersectMask = otherproclock->holdMask & conflictMask; - - for (i = 1; i <= numLockModes; i++) - { - if ((intersectMask & LOCKBIT_ON(i)) != 0) - { - if (conflictsRemaining[i] <= 0) - elog(PANIC, "proclocks held do not match lock"); - conflictsRemaining[i]--; - totalConflictsRemaining--; - } - } - - if (totalConflictsRemaining == 0) - { - PROCLOCK_PRINT("LockCheckConflicts: resolved (group)", - proclock); - return STATUS_OK; - } - } - otherproclock = (PROCLOCK *) - SHMQueueNext(procLocks, &otherproclock->lockLink, - offsetof(PROCLOCK, lockLink)); - } - #ifdef XCP /* * So the lock is conflicting with locks held by some other backend. @@ -1518,6 +1467,58 @@ LockCheckConflicts(LockMethod lockMethodTable, LWLockRelease(ProcArrayLock); #endif + /* If no group locking, it's definitely a conflict. */ + if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL) + { + Assert(proclock->tag.myProc == MyProc); + PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)", + proclock); + return STATUS_FOUND; + } + + /* + * Locks held in conflicting modes by members of our own lock group are + * not real conflicts; we can subtract those out and see if we still have + * a conflict. This is O(N) in the number of processes holding or + * awaiting locks on this object. We could improve that by making the + * shared memory state more complex (and larger) but it doesn't seem worth + * it. + */ + procLocks = &(lock->procLocks); + otherproclock = (PROCLOCK *) + SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink)); + while (otherproclock != NULL) + { + if (proclock != otherproclock && + proclock->groupLeader == otherproclock->groupLeader && + (otherproclock->holdMask & conflictMask) != 0) + { + int intersectMask = otherproclock->holdMask & conflictMask; + + for (i = 1; i <= numLockModes; i++) + { + if ((intersectMask & LOCKBIT_ON(i)) != 0) + { + if (conflictsRemaining[i] <= 0) + elog(PANIC, "proclocks held do not match lock"); + conflictsRemaining[i]--; + totalConflictsRemaining--; + } + } + + if (totalConflictsRemaining == 0) + { + PROCLOCK_PRINT("LockCheckConflicts: resolved (group)", + proclock); + return STATUS_OK; + } + } + otherproclock = (PROCLOCK *) + SHMQueueNext(procLocks, &otherproclock->lockLink, + offsetof(PROCLOCK, lockLink)); + } + + /* Nope, it's a real conflict. */ PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock); return STATUS_FOUND; |