mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
More deadlock code to check for escallation locks.
offsetof() addition to local socket size.
This commit is contained in:
parent
54399bb2f9
commit
8abd424369
@ -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
|
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
|
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
|
holders, summing the values of activeHolders should total to the value
|
||||||
of nActive.
|
of nActive.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
This is all I had the stomach for right now..... I will get back to this
|
Locks are accessed in two ways. Each PROC structure has a lockQueue,
|
||||||
someday. -mer 17 June 1992 12:00 am
|
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.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Outside modules can create a lock table and acquire/release
|
* Outside modules can create a lock table and acquire/release
|
||||||
@ -755,7 +755,7 @@ LockResolveConflicts(LOCKTAB *ltable,
|
|||||||
tmpMask = 2;
|
tmpMask = 2;
|
||||||
for (i = 1; i <= nLockTypes; i++, tmpMask <<= 1)
|
for (i = 1; i <= nLockTypes; i++, tmpMask <<= 1)
|
||||||
{
|
{
|
||||||
if (lock->activeHolders[i] - myHolders[i])
|
if (lock->activeHolders[i] != myHolders[i])
|
||||||
{
|
{
|
||||||
bitmask |= tmpMask;
|
bitmask |= tmpMask;
|
||||||
}
|
}
|
||||||
@ -1429,14 +1429,38 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
|||||||
XIDLookupEnt *tmp = NULL;
|
XIDLookupEnt *tmp = NULL;
|
||||||
SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
|
SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
|
||||||
LOCK *lock;
|
LOCK *lock;
|
||||||
|
|
||||||
|
LOCKTAB *ltable;
|
||||||
|
XIDLookupEnt *result,
|
||||||
|
item;
|
||||||
|
HTAB *xidTable;
|
||||||
|
bool found;
|
||||||
|
|
||||||
static PROC* checked_procs[MaxBackendId];
|
static PROC* checked_procs[MaxBackendId];
|
||||||
static int nprocs;
|
static int nprocs;
|
||||||
|
static bool MyNHolding;
|
||||||
|
|
||||||
|
/* initialize at start of recursion */
|
||||||
if (skip_check)
|
if (skip_check)
|
||||||
{
|
{
|
||||||
/* initialize at start of recursion */
|
|
||||||
checked_procs[0] = MyProc;
|
checked_procs[0] = MyProc;
|
||||||
nprocs = 1;
|
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))
|
if (SHMQueueEmpty(lockQueue))
|
||||||
@ -1469,12 +1493,6 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
|||||||
if (lock == findlock && !skip_check)
|
if (lock == findlock && !skip_check)
|
||||||
return true;
|
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_QUEUE *waitQueue = &(lock->waitProcs);
|
||||||
PROC *proc;
|
PROC *proc;
|
||||||
@ -1483,18 +1501,72 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
|||||||
|
|
||||||
proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
|
proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
|
||||||
for (i = 0; i < waitQueue->size; i++)
|
for (i = 0; i < waitQueue->size; i++)
|
||||||
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
for (j = 0; j < nprocs; j++)
|
for (j = 0; j < nprocs; j++)
|
||||||
if (checked_procs[j] == proc)
|
if (checked_procs[j] == proc)
|
||||||
break;
|
break;
|
||||||
if (j >= nprocs)
|
if (j >= nprocs && lock != findlock)
|
||||||
{
|
{
|
||||||
checked_procs[nprocs++] = proc;
|
checked_procs[nprocs++] = proc;
|
||||||
Assert(nprocs <= MaxBackendId);
|
Assert(nprocs <= MaxBackendId);
|
||||||
/* If we found a deadlock, we can stop right now */
|
/*
|
||||||
|
* 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))
|
if (DeadLockCheck(&(proc->lockQueue), findlock, false))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
proc = (PROC *) MAKE_PTR(proc->links.prev);
|
proc = (PROC *) MAKE_PTR(proc->links.prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* This is so that we can support more backends. (system-wide semaphore
|
||||||
* sets run out pretty fast.) -ay 4/95
|
* 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 <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -249,7 +249,10 @@ InitProcess(IPCKey key)
|
|||||||
*/
|
*/
|
||||||
SpinRelease(ProcStructLock);
|
SpinRelease(ProcStructLock);
|
||||||
|
|
||||||
|
MyProc->pid = 0;
|
||||||
|
#if 0
|
||||||
MyProc->pid = MyProcPid;
|
MyProc->pid = MyProcPid;
|
||||||
|
#endif
|
||||||
MyProc->xid = InvalidTransactionId;
|
MyProc->xid = InvalidTransactionId;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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) \
|
#define UNIXSOCK_PATH(sun,port) \
|
||||||
(sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (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 do this because sun_len is in BSD's struct, while others don't.
|
||||||
* We never actually set sun_len, and I can't think of a
|
* 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
|
* platform-safe way of doing it, but the code still works. bjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user