88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.97 2001/01/25 03:31:16 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.98 2001/01/26 18:23:12 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -537,13 +537,18 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
537537 * me to before that waiter anyway; but it's relatively cheap to detect
538538 * such a conflict immediately, and avoid delaying till deadlock timeout.
539539 *
540- * Special case: if I find I should go in front of the first waiter,
541- * and I do not conflict with already-held locks, then just grant myself
542- * the requested lock immediately.
540+ * Special case: if I find I should go in front of some waiter, check
541+ * to see if I conflict with already-held locks or the requests before
542+ * that waiter. If not, then just grant myself the requested lock
543+ * immediately. This is the same as the test for immediate grant in
544+ * LockAcquire, except we are only considering the part of the wait queue
545+ * before my insertion point.
543546 * ----------------------
544547 */
545548if (myHeldLocks != 0 )
546549{
550+ int aheadRequests = 0 ;
551+
547552proc = (PROC * )MAKE_PTR (waitQueue -> links .next );
548553for (i = 0 ;i < waitQueue -> size ;i ++ )
549554{
@@ -557,26 +562,30 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
557562MyProc -> errType = STATUS_ERROR ;
558563return STATUS_ERROR ;
559564}
560- if (i == 0 )
565+ /* I must go before this waiter. Check special case. */
566+ if ((lockctl -> conflictTab [lockmode ]& aheadRequests )== 0 &&
567+ LockCheckConflicts (lockMethodTable ,
568+ lockmode ,
569+ lock ,
570+ holder ,
571+ MyProc ,
572+ NULL )== STATUS_OK )
561573{
562- /* I must go before first waiter. Check special case. */
563- if (LockCheckConflicts (lockMethodTable ,
564- lockmode ,
565- lock ,
566- holder ,
567- MyProc ,
568- NULL )== STATUS_OK )
569- {
570- /* Skip the wait and just grant myself the lock. */
571- GrantLock (lock ,holder ,lockmode );
572- return STATUS_OK ;
573- }
574+ /* Skip the wait and just grant myself the lock. */
575+ GrantLock (lock ,holder ,lockmode );
576+ return STATUS_OK ;
574577}
575578/* Break out of loop to put myself before him */
576579break ;
577580}
581+ /* Nope, so advance to next waiter */
582+ aheadRequests |= (1 <<proc -> waitLockMode );
578583proc = (PROC * )MAKE_PTR (proc -> links .next );
579584}
585+ /*
586+ * If we fall out of loop normally, proc points to waitQueue head,
587+ * so we will insert at tail of queue as desired.
588+ */
580589}
581590else
582591{
@@ -739,7 +748,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
739748PROC_QUEUE * waitQueue = & (lock -> waitProcs );
740749int queue_size = waitQueue -> size ;
741750PROC * proc ;
742- int conflictMask = 0 ;
751+ int aheadRequests = 0 ;
743752
744753Assert (queue_size >=0 );
745754
@@ -756,7 +765,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
756765 * Waken if (a) doesn't conflict with requests of earlier waiters,
757766 * and (b) doesn't conflict with already-held locks.
758767 */
759- if ((( 1 << lockmode ) & conflictMask )== 0 &&
768+ if ((lockctl -> conflictTab [ lockmode ] & aheadRequests )== 0 &&
760769LockCheckConflicts (lockMethodTable ,
761770lockmode ,
762771lock ,
@@ -775,8 +784,8 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
775784}
776785else
777786{
778- /* Cannot wake this guy. Add his requestto conflict mask . */
779- conflictMask |=lockctl -> conflictTab [ lockmode ] ;
787+ /* Cannot wake this guy.Remember his requestfor later checks . */
788+ aheadRequests |=( 1 << lockmode ) ;
780789proc = (PROC * )MAKE_PTR (proc -> links .next );
781790}
782791}