aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1998-01-28 02:29:40 +0000
committerBruce Momjian <bruce@momjian.us>1998-01-28 02:29:40 +0000
commit8abd4243695985623887ce29ecc937d05ead008c (patch)
tree7724076401375f4679623a9ab5c80d6f130ec340
parent54399bb2f99860fa48532c998d87774b8b737f72 (diff)
downloadpostgresql-8abd4243695985623887ce29ecc937d05ead008c.tar.gz
postgresql-8abd4243695985623887ce29ecc937d05ead008c.zip
More deadlock code to check for escallation locks.
offsetof() addition to local socket size.
-rw-r--r--src/backend/storage/lmgr/README12
-rw-r--r--src/backend/storage/lmgr/lock.c114
-rw-r--r--src/backend/storage/lmgr/proc.c7
-rw-r--r--src/include/libpq/pqcomm.h8
4 files changed, 111 insertions, 30 deletions
diff --git a/src/backend/storage/lmgr/README b/src/backend/storage/lmgr/README
index e382003f2a4..821f4a37451 100644
--- a/src/backend/storage/lmgr/README
+++ b/src/backend/storage/lmgr/README
@@ -1,4 +1,4 @@
-$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.1.1.1 1996/07/09 06:21:55 scrappy Exp $
+$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.2 1998/01/28 02:29:26 momjian Exp $
This file is an attempt to save me (and future code maintainers) some
time and a lot of headaches. The existing lock manager code at the time
@@ -88,6 +88,12 @@ activeHolders -
holders, summing the values of activeHolders should total to the value
of nActive.
+---------------------------------------------------------------------------
-This is all I had the stomach for right now..... I will get back to this
-someday. -mer 17 June 1992 12:00 am
+Locks are accessed in two ways. Each PROC structure has a lockQueue,
+that is a circular linked list of LOCK pointers that this process holds
+or is waiting on.
+
+Second, there is a hash table that can do a lookup by combined LOCK
+address and transaction id(xid) which allows a process to see what
+type of locks it holds on that table.
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index a509050704a..e218a403425 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.23 1998/01/27 15:34:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.24 1998/01/28 02:29:27 momjian Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
@@ -755,7 +755,7 @@ LockResolveConflicts(LOCKTAB *ltable,
tmpMask = 2;
for (i = 1; i <= nLockTypes; i++, tmpMask <<= 1)
{
- if (lock->activeHolders[i] - myHolders[i])
+ if (lock->activeHolders[i] != myHolders[i])
{
bitmask |= tmpMask;
}
@@ -1429,14 +1429,38 @@ 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;
+ LOCKTAB *ltable;
+ XIDLookupEnt *result,
+ item;
+ HTAB *xidTable;
+ bool found;
+
+ static PROC* checked_procs[MaxBackendId];
+ static int nprocs;
+ static bool MyNHolding;
+
+ /* initialize at start of recursion */
if (skip_check)
{
- /* initialize at start of recursion */
checked_procs[0] = MyProc;
nprocs = 1;
+
+ ltable = AllTables[1];
+ xidTable = ltable->xidHash;
+
+ MemSet(&item, 0, XID_TAGSIZE);
+ TransactionIdStore(MyProc->xid, &item.tag.xid);
+ item.tag.lock = MAKE_OFFSET(findlock);
+#if 0
+ item.tag.pid = pid;
+#endif
+
+ if ((result = (XIDLookupEnt *)
+ hash_search(xidTable, (Pointer) &item, HASH_FIND, &found)) && found)
+ MyNHolding = result->nHolding;
+ else
+ MyNHolding = 0;
}
if (SHMQueueEmpty(lockQueue))
@@ -1469,13 +1493,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
if (lock == findlock && !skip_check)
return true;
- /*
- * 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;
@@ -1484,16 +1502,70 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
for (i = 0; i < waitQueue->size; i++)
{
- for (j = 0; j < nprocs; j++)
- if (checked_procs[j] == proc)
- break;
- if (j >= nprocs)
+ if (proc != MyProc &&
+ lock == findlock && /* skip_check also true */
+ MyNHolding) /* I already hold some lock on it */
+ {
+ /*
+ * For findlock's wait queue, we are interested in
+ * procs who are blocked waiting for a write-lock on the
+ * table we are waiting on, and already hold a lock on it.
+ * We first check to see if there is an escalation
+ * deadlock, where we hold a readlock and want a
+ * writelock, and someone else holds readlock on
+ * the same table, and wants a writelock.
+ *
+ * Basically, the test is, "Do we both hold some lock
+ * on findlock, and we are both waiting in the lock
+ * queue?"
+ */
+
+ Assert(skip_check);
+ Assert(MyProc->prio == 2);
+
+ ltable = AllTables[1];
+ xidTable = ltable->xidHash;
+
+ MemSet(&item, 0, XID_TAGSIZE);
+ TransactionIdStore(proc->xid, &item.tag.xid);
+ item.tag.lock = MAKE_OFFSET(findlock);
+#if 0
+ item.tag.pid = pid;
+#endif
+
+ if ((result = (XIDLookupEnt *)
+ hash_search(xidTable, (Pointer) &item, HASH_FIND, &found)) && found)
+ {
+ if (result->nHolding)
+ return true;
+ }
+ }
+ /*
+ * No sense in looking at the wait queue of the lock we are
+ * looking for.
+ * If lock == findlock, and I got here, skip_check must be
+ * true too.
+ */
+ if (lock != findlock)
{
- 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;
+ for (j = 0; j < nprocs; j++)
+ if (checked_procs[j] == proc)
+ break;
+ if (j >= nprocs && lock != findlock)
+ {
+ checked_procs[nprocs++] = proc;
+ Assert(nprocs <= MaxBackendId);
+ /*
+ * For non-MyProc entries, we are looking only waiters,
+ * not necessarily people who already hold locks and are
+ * waiting.
+ * Now we check for cases where we have two or more
+ * tables in a deadlock. We do this by continuing
+ * to search for someone holding a lock
+ */
+ if (DeadLockCheck(&(proc->lockQueue), findlock, false))
+ return true;
+ }
}
proc = (PROC *) MAKE_PTR(proc->links.prev);
}
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 893ea41833d..1ab096ac527 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.29 1998/01/27 03:00:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.30 1998/01/28 02:29:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -46,7 +46,7 @@
* This is so that we can support more backends. (system-wide semaphore
* sets run out pretty fast.) -ay 4/95
*
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.29 1998/01/27 03:00:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.30 1998/01/28 02:29:29 momjian Exp $
*/
#include <sys/time.h>
#include <unistd.h>
@@ -249,7 +249,10 @@ InitProcess(IPCKey key)
*/
SpinRelease(ProcStructLock);
+ MyProc->pid = 0;
+#if 0
MyProc->pid = MyProcPid;
+#endif
MyProc->xid = InvalidTransactionId;
/* ----------------
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index b3b67f8b73b..0145f262702 100644
--- a/src/include/libpq/pqcomm.h
+++ b/src/include/libpq/pqcomm.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: pqcomm.h,v 1.21 1998/01/27 15:35:22 momjian Exp $
+ * $Id: pqcomm.h,v 1.22 1998/01/28 02:29:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,10 +35,10 @@ typedef union SockAddr {
#define UNIXSOCK_PATH(sun,port) \
(sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)) + \
- + 1 + sizeof ((sun).sun_family))
+ offsetof(struct sockaddr_un, sun_path))
/*
- * + 1 is for BSD-specific sizeof((sun).sun_len)
- * We never actually set sun_len, and I can't think of a
+ * We do this because sun_len is in BSD's struct, while others don't.
+ * We never actually set BSD's sun_len, and I can't think of a
* platform-safe way of doing it, but the code still works. bjm
*/