diff options
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index fd4c4b14856..463af1fa5e3 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.97 2001/01/25 03:31:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.98 2001/01/26 18:23:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -537,13 +537,18 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable, * me to before that waiter anyway; but it's relatively cheap to detect * such a conflict immediately, and avoid delaying till deadlock timeout. * - * Special case: if I find I should go in front of the first waiter, - * and I do not conflict with already-held locks, then just grant myself - * the requested lock immediately. + * Special case: if I find I should go in front of some waiter, check + * to see if I conflict with already-held locks or the requests before + * that waiter. If not, then just grant myself the requested lock + * immediately. This is the same as the test for immediate grant in + * LockAcquire, except we are only considering the part of the wait queue + * before my insertion point. * ---------------------- */ if (myHeldLocks != 0) { + int aheadRequests = 0; + proc = (PROC *) MAKE_PTR(waitQueue->links.next); for (i = 0; i < waitQueue->size; i++) { @@ -557,26 +562,30 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable, MyProc->errType = STATUS_ERROR; return STATUS_ERROR; } - if (i == 0) + /* I must go before this waiter. Check special case. */ + if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 && + LockCheckConflicts(lockMethodTable, + lockmode, + lock, + holder, + MyProc, + NULL) == STATUS_OK) { - /* I must go before first waiter. Check special case. */ - if (LockCheckConflicts(lockMethodTable, - lockmode, - lock, - holder, - MyProc, - NULL) == STATUS_OK) - { - /* Skip the wait and just grant myself the lock. */ - GrantLock(lock, holder, lockmode); - return STATUS_OK; - } + /* Skip the wait and just grant myself the lock. */ + GrantLock(lock, holder, lockmode); + return STATUS_OK; } /* Break out of loop to put myself before him */ break; } + /* Nope, so advance to next waiter */ + aheadRequests |= (1 << proc->waitLockMode); proc = (PROC *) MAKE_PTR(proc->links.next); } + /* + * If we fall out of loop normally, proc points to waitQueue head, + * so we will insert at tail of queue as desired. + */ } else { @@ -739,7 +748,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock) PROC_QUEUE *waitQueue = &(lock->waitProcs); int queue_size = waitQueue->size; PROC *proc; - int conflictMask = 0; + int aheadRequests = 0; Assert(queue_size >= 0); @@ -756,7 +765,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock) * Waken if (a) doesn't conflict with requests of earlier waiters, * and (b) doesn't conflict with already-held locks. */ - if (((1 << lockmode) & conflictMask) == 0 && + if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 && LockCheckConflicts(lockMethodTable, lockmode, lock, @@ -775,8 +784,8 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock) } else { - /* Cannot wake this guy. Add his request to conflict mask. */ - conflictMask |= lockctl->conflictTab[lockmode]; + /* Cannot wake this guy. Remember his request for later checks. */ + aheadRequests |= (1 << lockmode); proc = (PROC *) MAKE_PTR(proc->links.next); } } |