aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr/lock.c')
-rw-r--r--src/backend/storage/lmgr/lock.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 286824e27f6..a509050704a 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -7,12 +7,12 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.22 1998/01/27 03:00:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.23 1998/01/27 15:34:49 momjian Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
* locks. A lock table is a shared memory hash table. When
- * a process tries to acquire a lock of a type that conflicts
+ * a process tries to acquire a lock of a type that conflictRs
* with existing locks, it is put to sleep using the routines
* in storage/lmgr/proc.c.
*
@@ -39,6 +39,7 @@
#include "postgres.h"
#include "miscadmin.h"
#include "storage/shmem.h"
+#include "storage/sinvaladt.h"
#include "storage/spin.h"
#include "storage/proc.h"
#include "storage/lock.h"
@@ -1415,7 +1416,8 @@ LockingDisabled()
*
* This code takes a list of locks a process holds, and the lock that
* the process is sleeping on, and tries to find if any of the processes
- * waiting on its locks hold the lock it is waiting for.
+ * waiting on its locks hold the lock it is waiting for. If no deadlock
+ * is found, it goes on to look at all the processes waiting on their locks.
*
* We have already locked the master lock before being called.
*/
@@ -1427,7 +1429,16 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
XIDLookupEnt *tmp = NULL;
SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
LOCK *lock;
+ static PROC* checked_procs[MaxBackendId];
+ static int nprocs;
+ if (skip_check)
+ {
+ /* initialize at start of recursion */
+ checked_procs[0] = MyProc;
+ nprocs = 1;
+ }
+
if (SHMQueueEmpty(lockQueue))
return false;
@@ -1457,18 +1468,29 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
*/
if (lock == findlock && !skip_check)
return true;
- else if (lock != findlock || !skip_check)
+
+ /*
+ * No sense in looking at the wait queue of the lock we are
+ * looking for as it is MyProc's lock entry.
+ * If lock == findlock, and I got here, skip_check must be true.
+ */
+ if (lock != findlock)
{
PROC_QUEUE *waitQueue = &(lock->waitProcs);
PROC *proc;
int i;
+ int j;
proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
for (i = 0; i < waitQueue->size; i++)
{
- /* prevent endless loops */
- if (proc != MyProc && skip_check)
+ for (j = 0; j < nprocs; j++)
+ if (checked_procs[j] == proc)
+ break;
+ if (j >= nprocs)
{
+ checked_procs[nprocs++] = proc;
+ Assert(nprocs <= MaxBackendId);
/* If we found a deadlock, we can stop right now */
if (DeadLockCheck(&(proc->lockQueue), findlock, false))
return true;