8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.100 2001/03/22 06:16:17 momjian Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.100.2.1 2001/09/12 17:14:39 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -516,16 +516,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
516
516
SPINLOCK spinlock = lockctl -> masterLock ;
517
517
PROC_QUEUE * waitQueue = & (lock -> waitProcs );
518
518
int myHeldLocks = MyProc -> heldLocks ;
519
+ bool early_deadlock = false;
519
520
PROC * proc ;
520
521
int i ;
521
-
522
522
#ifndef __BEOS__
523
523
struct itimerval timeval ,
524
524
dummy ;
525
-
526
525
#else
527
526
bigtime_t time_interval ;
528
-
529
527
#endif
530
528
531
529
/*
@@ -545,7 +543,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
545
543
* immediately. This is the same as the test for immediate grant in
546
544
* LockAcquire, except we are only considering the part of the wait
547
545
* queue before my insertion point.
548
- *
549
546
*/
550
547
if (myHeldLocks != 0 )
551
548
{
@@ -560,9 +557,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
560
557
/* Must I wait for him ? */
561
558
if (lockctl -> conflictTab [lockmode ] & proc -> heldLocks )
562
559
{
563
- /* Yes, can report deadlock failure immediately */
564
- MyProc -> errType = STATUS_ERROR ;
565
- return STATUS_ERROR ;
560
+ /*
561
+ * Yes, so we have a deadlock. Easiest way to clean up
562
+ * correctly is to call RemoveFromWaitQueue(), but we
563
+ * can't do that until we are *on* the wait queue.
564
+ * So, set a flag to check below, and break out of loop.
565
+ */
566
+ early_deadlock = true;
567
+ break ;
566
568
}
567
569
/* I must go before this waiter. Check special case. */
568
570
if ((lockctl -> conflictTab [lockmode ] & aheadRequests ) == 0 &&
@@ -610,7 +612,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
610
612
MyProc -> waitHolder = holder ;
611
613
MyProc -> waitLockMode = lockmode ;
612
614
613
- MyProc -> errType = STATUS_OK ;/* initialize result for success */
615
+ MyProc -> errType = STATUS_OK ; /* initialize result for success */
616
+
617
+ /*
618
+ * If we detected deadlock, give up without waiting. This must agree
619
+ * with HandleDeadLock's recovery code, except that we shouldn't release
620
+ * the semaphore since we haven't tried to lock it yet.
621
+ */
622
+ if (early_deadlock )
623
+ {
624
+ RemoveFromWaitQueue (MyProc );
625
+ MyProc -> errType = STATUS_ERROR ;
626
+ return STATUS_ERROR ;
627
+ }
614
628
615
629
/* mark that we are waiting for a lock */
616
630
waitingForLock = true;
@@ -703,6 +717,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
703
717
*
704
718
* Also remove the process from the wait queue and set its links invalid.
705
719
* RETURN: the next process in the wait queue.
720
+ *
721
+ * XXX: presently, this code is only used for the "success" case, and only
722
+ * works correctly for that case. To clean up in failure case, would need
723
+ * to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
706
724
*/
707
725
PROC *
708
726
ProcWakeup (PROC * proc , int errType )
0 commit comments