diff options
Diffstat (limited to 'src/backend/storage/lmgr/lock.c')
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 34 |
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; |