mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Special case in ProcSleep() wasn't sufficiently general: must check to
see if we shouldn't block whenever we insert ourselves anywhere before the end of the queue, not only at the front.
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user