8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -537,13 +537,18 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
537
537
* me to before that waiter anyway; but it's relatively cheap to detect
538
538
* such a conflict immediately, and avoid delaying till deadlock timeout.
539
539
*
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.
543
546
* ----------------------
544
547
*/
545
548
if (myHeldLocks != 0 )
546
549
{
550
+ int aheadRequests = 0 ;
551
+
547
552
proc = (PROC * ) MAKE_PTR (waitQueue -> links .next );
548
553
for (i = 0 ; i < waitQueue -> size ; i ++ )
549
554
{
@@ -557,26 +562,30 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
557
562
MyProc -> errType = STATUS_ERROR ;
558
563
return STATUS_ERROR ;
559
564
}
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 )
561
573
{
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 ;
574
577
}
575
578
/* Break out of loop to put myself before him */
576
579
break ;
577
580
}
581
+ /* Nope, so advance to next waiter */
582
+ aheadRequests |= (1 << proc -> waitLockMode );
578
583
proc = (PROC * ) MAKE_PTR (proc -> links .next );
579
584
}
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
+ */
580
589
}
581
590
else
582
591
{
@@ -739,7 +748,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
739
748
PROC_QUEUE * waitQueue = & (lock -> waitProcs );
740
749
int queue_size = waitQueue -> size ;
741
750
PROC * proc ;
742
- int conflictMask = 0 ;
751
+ int aheadRequests = 0 ;
743
752
744
753
Assert (queue_size >= 0 );
745
754
@@ -756,7 +765,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
756
765
* Waken if (a) doesn't conflict with requests of earlier waiters,
757
766
* and (b) doesn't conflict with already-held locks.
758
767
*/
759
- if ((( 1 << lockmode ) & conflictMask ) == 0 &&
768
+ if ((lockctl -> conflictTab [ lockmode ] & aheadRequests ) == 0 &&
760
769
LockCheckConflicts (lockMethodTable ,
761
770
lockmode ,
762
771
lock ,
@@ -775,8 +784,8 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
775
784
}
776
785
else
777
786
{
778
- /* Cannot wake this guy. Add his request to conflict mask . */
779
- conflictMask |= lockctl -> conflictTab [ lockmode ] ;
787
+ /* Cannot wake this guy. Remember his request for later checks . */
788
+ aheadRequests |= ( 1 << lockmode ) ;
780
789
proc = (PROC * ) MAKE_PTR (proc -> links .next );
781
790
}
782
791
}
0 commit comments