8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.104 2001/07/06 21:04:26 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.105 2001/09/04 02:26:57 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -506,16 +506,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
506
506
SPINLOCK spinlock = lockctl -> masterLock ;
507
507
PROC_QUEUE * waitQueue = & (lock -> waitProcs );
508
508
int myHeldLocks = MyProc -> heldLocks ;
509
+ bool early_deadlock = false;
509
510
PROC * proc ;
510
511
int i ;
511
-
512
512
#ifndef __BEOS__
513
513
struct itimerval timeval ,
514
514
dummy ;
515
-
516
515
#else
517
516
bigtime_t time_interval ;
518
-
519
517
#endif
520
518
521
519
/*
@@ -535,7 +533,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
535
533
* immediately. This is the same as the test for immediate grant in
536
534
* LockAcquire, except we are only considering the part of the wait
537
535
* queue before my insertion point.
538
- *
539
536
*/
540
537
if (myHeldLocks != 0 )
541
538
{
@@ -550,9 +547,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
550
547
/* Must I wait for him ? */
551
548
if (lockctl -> conflictTab [lockmode ] & proc -> heldLocks )
552
549
{
553
- /* Yes, can report deadlock failure immediately */
554
- MyProc -> errType = STATUS_ERROR ;
555
- return STATUS_ERROR ;
550
+ /*
551
+ * Yes, so we have a deadlock. Easiest way to clean up
552
+ * correctly is to call RemoveFromWaitQueue(), but we
553
+ * can't do that until we are *on* the wait queue.
554
+ * So, set a flag to check below, and break out of loop.
555
+ */
556
+ early_deadlock = true;
557
+ break ;
556
558
}
557
559
/* I must go before this waiter. Check special case. */
558
560
if ((lockctl -> conflictTab [lockmode ] & aheadRequests ) == 0 &&
@@ -600,7 +602,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
600
602
MyProc -> waitHolder = holder ;
601
603
MyProc -> waitLockMode = lockmode ;
602
604
603
- MyProc -> errType = STATUS_OK ;/* initialize result for success */
605
+ MyProc -> errType = STATUS_OK ; /* initialize result for success */
606
+
607
+ /*
608
+ * If we detected deadlock, give up without waiting. This must agree
609
+ * with HandleDeadLock's recovery code, except that we shouldn't release
610
+ * the semaphore since we haven't tried to lock it yet.
611
+ */
612
+ if (early_deadlock )
613
+ {
614
+ RemoveFromWaitQueue (MyProc );
615
+ MyProc -> errType = STATUS_ERROR ;
616
+ return STATUS_ERROR ;
617
+ }
604
618
605
619
/* mark that we are waiting for a lock */
606
620
waitingForLock = true;
@@ -693,6 +707,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
693
707
*
694
708
* Also remove the process from the wait queue and set its links invalid.
695
709
* RETURN: the next process in the wait queue.
710
+ *
711
+ * XXX: presently, this code is only used for the "success" case, and only
712
+ * works correctly for that case. To clean up in failure case, would need
713
+ * to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
696
714
*/
697
715
PROC *
698
716
ProcWakeup (PROC * proc , int errType )
0 commit comments