aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r--src/backend/storage/lmgr/proc.c51
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);
}
}