mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Rename fields of lock and lockholder structures to something a tad less
confusing, and clean up documentation.
This commit is contained in:
		@@ -1,4 +1,4 @@
 | 
				
			|||||||
$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.4 2000/12/22 00:51:54 tgl Exp $
 | 
					$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.5 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There are two fundamental lock structures: the per-lockable-object LOCK
 | 
					There are two fundamental lock structures: the per-lockable-object LOCK
 | 
				
			||||||
struct, and the per-lock-holder HOLDER struct.  A LOCK object exists
 | 
					struct, and the per-lock-holder HOLDER struct.  A LOCK object exists
 | 
				
			||||||
@@ -44,51 +44,52 @@ tag -
 | 
				
			|||||||
	only a single table (see Gray's paper on 2 phase locking if
 | 
						only a single table (see Gray's paper on 2 phase locking if
 | 
				
			||||||
	you are puzzled about how multi-level lock tables work).
 | 
						you are puzzled about how multi-level lock tables work).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mask -
 | 
					grantMask -
 | 
				
			||||||
    This field indicates what types of locks are currently held on the
 | 
					    This bitmask indicates what types of locks are currently held on the
 | 
				
			||||||
    given lockable object.  It is used (against the lock table's conflict
 | 
					    given lockable object.  It is used (against the lock table's conflict
 | 
				
			||||||
    table) to determine if the new lock request will conflict with existing
 | 
					    table) to determine if a new lock request will conflict with existing
 | 
				
			||||||
    lock types held.  Conficts are determined by bitwise AND operations
 | 
					    lock types held.  Conficts are determined by bitwise AND operations
 | 
				
			||||||
    between the mask and the conflict table entry for the given lock type
 | 
					    between the grantMask and the conflict table entry for the requested
 | 
				
			||||||
    to be set.  The current representation is that each bit (1 through 5)
 | 
					    lock type.  Bit i of grantMask is 1 if and only if granted[i] > 0.
 | 
				
			||||||
    is set when that lock type (WRITE, READ, WRITE INTENT, READ INTENT, EXTEND)
 | 
					
 | 
				
			||||||
    has been acquired for the lock.
 | 
					waitMask -
 | 
				
			||||||
 | 
					    This bitmask shows the types of locks being waited for.  Bit i of waitMask
 | 
				
			||||||
 | 
					    is 1 if and only if requested[i] > granted[i].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
waitProcs -
 | 
					waitProcs -
 | 
				
			||||||
    This is a shared memory queue of all process structures corresponding to
 | 
					    This is a shared memory queue of all process structures corresponding to
 | 
				
			||||||
    a backend that is waiting (sleeping) until another backend releases this
 | 
					    a backend that is waiting (sleeping) until another backend releases this
 | 
				
			||||||
    lock.  The process structure holds the information needed to determine
 | 
					    lock.  The process structure holds the information needed to determine
 | 
				
			||||||
    if it should be woken up when this lock is released.  If, for example,
 | 
					    if it should be woken up when this lock is released.
 | 
				
			||||||
    we are releasing a read lock and the process is sleeping trying to acquire
 | 
					 | 
				
			||||||
    a read lock then there is no point in waking it since the lock being
 | 
					 | 
				
			||||||
    released isn't what caused it to sleep in the first place.  There will
 | 
					 | 
				
			||||||
    be more on this below (when I get to releasing locks and waking sleeping
 | 
					 | 
				
			||||||
    process routines).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
nHolding -
 | 
					nRequested -
 | 
				
			||||||
    Keeps a count of how many times this lock has been attempted to be
 | 
					    Keeps a count of how many times this lock has been attempted to be
 | 
				
			||||||
    acquired.  The count includes attempts by processes which were put
 | 
					    acquired.  The count includes attempts by processes which were put
 | 
				
			||||||
    to sleep due to conflicts.  It also counts the same backend twice
 | 
					    to sleep due to conflicts.  It also counts the same backend twice
 | 
				
			||||||
    if, for example, a backend process first acquires a read and then
 | 
					    if, for example, a backend process first acquires a read and then
 | 
				
			||||||
    acquires a write.
 | 
					    acquires a write, or acquires a read lock twice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
holders -
 | 
					requested -
 | 
				
			||||||
    Keeps a count of how many locks of each type have been attempted.  Only
 | 
					    Keeps a count of how many locks of each type have been attempted.  Only
 | 
				
			||||||
    elements 1 through MAX_LOCK_TYPES are used as they correspond to the lock
 | 
					    elements 1 through MAX_LOCKMODES-1 are used as they correspond to the lock
 | 
				
			||||||
    type defined constants (WRITE through EXTEND).  Summing the values of
 | 
					    type defined constants.  Summing the values of requested[] should come out
 | 
				
			||||||
    holders should come out equal to nHolding.
 | 
					    equal to nRequested.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nActive -
 | 
					nGranted -
 | 
				
			||||||
    Keeps a count of how many times this lock has been succesfully acquired.
 | 
					    Keeps count of how many times this lock has been successfully acquired.
 | 
				
			||||||
    This count does not include attempts that are waiting due to conflicts,
 | 
					    This count does not include attempts that are waiting due to conflicts,
 | 
				
			||||||
    but can count the same backend twice (e.g. a read then a write -- since
 | 
					    but can count the same backend twice (e.g. a read then a write -- since
 | 
				
			||||||
    its the same transaction this won't cause a conflict)
 | 
					    its the same transaction this won't cause a conflict).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
activeHolders -
 | 
					granted -
 | 
				
			||||||
    Keeps a count of how locks of each type are currently held.  Once again
 | 
					    Keeps count of how many locks of each type are currently held.  Once again
 | 
				
			||||||
    only elements 1 through MAX_LOCK_TYPES are used (0 is not).  Also, like
 | 
					    only elements 1 through MAX_LOCKMODES-1 are used (0 is not).  Also, like
 | 
				
			||||||
    holders, summing the values of activeHolders should total to the value
 | 
					    requested, summing the values of granted should total to the value
 | 
				
			||||||
    of nActive.
 | 
					    of nGranted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We should always have 0 <= nGranted <= nRequested, and
 | 
				
			||||||
 | 
					0 <= granted[i] <= requested[i] for each i.  If the request counts go to
 | 
				
			||||||
 | 
					zero, the lock object is no longer needed and can be freed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---------------------------------------------------------------------------
 | 
					---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -116,14 +117,12 @@ tag -
 | 
				
			|||||||
    are always session locks, and we also use session locks for multi-
 | 
					    are always session locks, and we also use session locks for multi-
 | 
				
			||||||
    transaction operations like VACUUM.
 | 
					    transaction operations like VACUUM.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
holders -
 | 
					holding -
 | 
				
			||||||
    The number of successfully acquired locks of each type for this holder.
 | 
					    The number of successfully acquired locks of each type for this holder.
 | 
				
			||||||
    (CAUTION: the semantics are not the same as the LOCK's holder[], which
 | 
					    This should be <= the corresponding granted[] value of the lock object!
 | 
				
			||||||
    counts both acquired and pending requests.  Probably a different name
 | 
					 | 
				
			||||||
    should be used...)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
nHolding -
 | 
					nHolding -
 | 
				
			||||||
    Sum of the holders[] array.
 | 
					    Sum of the holding[] array.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
queue -
 | 
					queue -
 | 
				
			||||||
    List link for shared memory queue of all the HOLDER objects for the
 | 
					    List link for shared memory queue of all the HOLDER objects for the
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.77 2001/01/14 05:08:15 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.78 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *	  Outside modules can create a lock table and acquire/release
 | 
					 *	  Outside modules can create a lock table and acquire/release
 | 
				
			||||||
@@ -43,8 +43,8 @@
 | 
				
			|||||||
static int	WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
					static int	WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
				
			||||||
					   LOCK *lock, HOLDER *holder);
 | 
										   LOCK *lock, HOLDER *holder);
 | 
				
			||||||
static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc,
 | 
					static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc,
 | 
				
			||||||
							 int *myHolders);
 | 
												 int *myHolding);
 | 
				
			||||||
static int LockGetMyHoldLocks(SHMEM_OFFSET lockOffset, PROC *proc);
 | 
					static int LockGetMyHeldLocks(SHMEM_OFFSET lockOffset, PROC *proc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *lock_types[] =
 | 
					static char *lock_types[] =
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -91,7 +91,7 @@ LOCK_DEBUG_ENABLED(const LOCK * lock)
 | 
				
			|||||||
    return
 | 
					    return
 | 
				
			||||||
        (((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
 | 
					        (((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
 | 
				
			||||||
          || (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
 | 
					          || (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
 | 
				
			||||||
         && (lock->tag.relId >= Trace_lock_oidmin))
 | 
					         && (lock->tag.relId >= (Oid) Trace_lock_oidmin))
 | 
				
			||||||
        || (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
 | 
					        || (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,17 +101,18 @@ LOCK_PRINT(const char * where, const LOCK * lock, LOCKMODE type)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	if (LOCK_DEBUG_ENABLED(lock))
 | 
						if (LOCK_DEBUG_ENABLED(lock))
 | 
				
			||||||
        elog(DEBUG,
 | 
					        elog(DEBUG,
 | 
				
			||||||
             "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) "
 | 
					             "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
 | 
				
			||||||
             "hold(%d,%d,%d,%d,%d,%d,%d)=%d "
 | 
					             "req(%d,%d,%d,%d,%d,%d,%d)=%d "
 | 
				
			||||||
             "act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
 | 
					             "grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
 | 
				
			||||||
             where, MAKE_OFFSET(lock),
 | 
					             where, MAKE_OFFSET(lock),
 | 
				
			||||||
             lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
 | 
					             lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
 | 
				
			||||||
             lock->tag.objId.blkno, lock->mask,
 | 
					             lock->tag.objId.blkno, lock->grantMask,
 | 
				
			||||||
             lock->holders[1], lock->holders[2], lock->holders[3], lock->holders[4],
 | 
					             lock->requested[1], lock->requested[2], lock->requested[3],
 | 
				
			||||||
             lock->holders[5], lock->holders[6], lock->holders[7], lock->nHolding,
 | 
								 lock->requested[4], lock->requested[5], lock->requested[6],
 | 
				
			||||||
             lock->activeHolders[1], lock->activeHolders[2], lock->activeHolders[3],
 | 
								 lock->requested[7], lock->nRequested,
 | 
				
			||||||
             lock->activeHolders[4], lock->activeHolders[5], lock->activeHolders[6],
 | 
					             lock->granted[1], lock->granted[2], lock->granted[3],
 | 
				
			||||||
             lock->activeHolders[7], lock->nActive,
 | 
					             lock->granted[4], lock->granted[5], lock->granted[6],
 | 
				
			||||||
 | 
					             lock->granted[7], lock->nGranted,
 | 
				
			||||||
             lock->waitProcs.size, lock_types[type]);
 | 
					             lock->waitProcs.size, lock_types[type]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -122,7 +123,7 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
 | 
				
			|||||||
	if (
 | 
						if (
 | 
				
			||||||
        (((HOLDER_LOCKMETHOD(*holderP) == DEFAULT_LOCKMETHOD && Trace_locks)
 | 
					        (((HOLDER_LOCKMETHOD(*holderP) == DEFAULT_LOCKMETHOD && Trace_locks)
 | 
				
			||||||
          || (HOLDER_LOCKMETHOD(*holderP) == USER_LOCKMETHOD && Trace_userlocks))
 | 
					          || (HOLDER_LOCKMETHOD(*holderP) == USER_LOCKMETHOD && Trace_userlocks))
 | 
				
			||||||
         && (((LOCK *)MAKE_PTR(holderP->tag.lock))->tag.relId >= Trace_lock_oidmin))
 | 
					         && (((LOCK *)MAKE_PTR(holderP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
 | 
				
			||||||
		|| (Trace_lock_table && (((LOCK *)MAKE_PTR(holderP->tag.lock))->tag.relId == Trace_lock_table))
 | 
							|| (Trace_lock_table && (((LOCK *)MAKE_PTR(holderP->tag.lock))->tag.relId == Trace_lock_table))
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        elog(DEBUG,
 | 
					        elog(DEBUG,
 | 
				
			||||||
@@ -130,8 +131,9 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
 | 
				
			|||||||
             where, MAKE_OFFSET(holderP), holderP->tag.lock,
 | 
					             where, MAKE_OFFSET(holderP), holderP->tag.lock,
 | 
				
			||||||
			 HOLDER_LOCKMETHOD(*(holderP)),
 | 
								 HOLDER_LOCKMETHOD(*(holderP)),
 | 
				
			||||||
             holderP->tag.pid, holderP->tag.xid,
 | 
					             holderP->tag.pid, holderP->tag.xid,
 | 
				
			||||||
             holderP->holders[1], holderP->holders[2], holderP->holders[3], holderP->holders[4],
 | 
					             holderP->holding[1], holderP->holding[2], holderP->holding[3],
 | 
				
			||||||
             holderP->holders[5], holderP->holders[6], holderP->holders[7], holderP->nHolding);
 | 
								 holderP->holding[4], holderP->holding[5], holderP->holding[6],
 | 
				
			||||||
 | 
								 holderP->holding[7], holderP->nHolding);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else  /* not LOCK_DEBUG */
 | 
					#else  /* not LOCK_DEBUG */
 | 
				
			||||||
@@ -146,7 +148,12 @@ HOLDER_PRINT(const char * where, const HOLDER * holderP)
 | 
				
			|||||||
SPINLOCK	LockMgrLock;		/* in Shmem or created in
 | 
					SPINLOCK	LockMgrLock;		/* in Shmem or created in
 | 
				
			||||||
								 * CreateSpinlocks() */
 | 
													 * CreateSpinlocks() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This is to simplify/speed up some bit arithmetic */
 | 
					/*
 | 
				
			||||||
 | 
					 * These are to simplify/speed up some bit arithmetic.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * XXX is a fetch from a static array really faster than a shift?
 | 
				
			||||||
 | 
					 * Wouldn't bet on it...
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static LOCKMASK BITS_OFF[MAX_LOCKMODES];
 | 
					static LOCKMASK BITS_OFF[MAX_LOCKMODES];
 | 
				
			||||||
static LOCKMASK BITS_ON[MAX_LOCKMODES];
 | 
					static LOCKMASK BITS_ON[MAX_LOCKMODES];
 | 
				
			||||||
@@ -471,7 +478,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	SPINLOCK	masterLock;
 | 
						SPINLOCK	masterLock;
 | 
				
			||||||
	LOCKMETHODTABLE *lockMethodTable;
 | 
						LOCKMETHODTABLE *lockMethodTable;
 | 
				
			||||||
	int			status;
 | 
						int			status;
 | 
				
			||||||
	int			myHolders[MAX_LOCKMODES];
 | 
						int			myHolding[MAX_LOCKMODES];
 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef LOCK_DEBUG
 | 
					#ifdef LOCK_DEBUG
 | 
				
			||||||
@@ -517,20 +524,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!found)
 | 
						if (!found)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		lock->mask = 0;
 | 
							lock->grantMask = 0;
 | 
				
			||||||
		lock->nHolding = 0;
 | 
							lock->waitMask = 0;
 | 
				
			||||||
		lock->nActive = 0;
 | 
							lock->nRequested = 0;
 | 
				
			||||||
		MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES);
 | 
							lock->nGranted = 0;
 | 
				
			||||||
		MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES);
 | 
							MemSet((char *) lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
 | 
				
			||||||
 | 
							MemSet((char *) lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
 | 
				
			||||||
		ProcQueueInit(&(lock->waitProcs));
 | 
							ProcQueueInit(&(lock->waitProcs));
 | 
				
			||||||
		LOCK_PRINT("LockAcquire: new", lock, lockmode);
 | 
							LOCK_PRINT("LockAcquire: new", lock, lockmode);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		LOCK_PRINT("LockAcquire: found", lock, lockmode);
 | 
							LOCK_PRINT("LockAcquire: found", lock, lockmode);
 | 
				
			||||||
		Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
 | 
							Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
 | 
				
			||||||
		Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] >= 0));
 | 
							Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
 | 
				
			||||||
		Assert(lock->nActive <= lock->nHolding);
 | 
							Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ------------------
 | 
						/* ------------------
 | 
				
			||||||
@@ -561,15 +569,15 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	if (!found)
 | 
						if (!found)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		holder->nHolding = 0;
 | 
							holder->nHolding = 0;
 | 
				
			||||||
		MemSet((char *) holder->holders, 0, sizeof(int) * MAX_LOCKMODES);
 | 
							MemSet((char *) holder->holding, 0, sizeof(int) * MAX_LOCKMODES);
 | 
				
			||||||
		ProcAddLock(&holder->queue);
 | 
							ProcAddLock(&holder->queue);
 | 
				
			||||||
		HOLDER_PRINT("LockAcquire: new", holder);
 | 
							HOLDER_PRINT("LockAcquire: new", holder);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		HOLDER_PRINT("LockAcquire: found", holder);
 | 
							HOLDER_PRINT("LockAcquire: found", holder);
 | 
				
			||||||
		Assert((holder->nHolding > 0) && (holder->holders[lockmode] >= 0));
 | 
							Assert((holder->nHolding >= 0) && (holder->holding[lockmode] >= 0));
 | 
				
			||||||
		Assert(holder->nHolding <= lock->nActive);
 | 
							Assert(holder->nHolding <= lock->nGranted);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CHECK_DEADLOCK_RISK
 | 
					#ifdef CHECK_DEADLOCK_RISK
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
@@ -588,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		 */
 | 
							 */
 | 
				
			||||||
		for (i = lockMethodTable->ctl->numLockModes; i > 0; i--)
 | 
							for (i = lockMethodTable->ctl->numLockModes; i > 0; i--)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (holder->holders[i] > 0)
 | 
								if (holder->holding[i] > 0)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (i >= (int) lockmode)
 | 
									if (i >= (int) lockmode)
 | 
				
			||||||
					break;		/* safe: we have a lock >= req level */
 | 
										break;		/* safe: we have a lock >= req level */
 | 
				
			||||||
@@ -603,21 +611,21 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ----------------
 | 
						/* ----------------
 | 
				
			||||||
	 * lock->nHolding and lock->holders count the total number of holders
 | 
						 * lock->nRequested and lock->requested[] count the total number of
 | 
				
			||||||
	 * either holding or waiting for the lock, so increment those immediately.
 | 
						 * requests, whether granted or waiting, so increment those immediately.
 | 
				
			||||||
	 * The other counts don't increment till we get the lock.
 | 
						 * The other counts don't increment till we get the lock.
 | 
				
			||||||
	 * ----------------
 | 
						 * ----------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	lock->nHolding++;
 | 
						lock->nRequested++;
 | 
				
			||||||
	lock->holders[lockmode]++;
 | 
						lock->requested[lockmode]++;
 | 
				
			||||||
	Assert((lock->nHolding > 0) && (lock->holders[lockmode] > 0));
 | 
						Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* --------------------
 | 
						/* --------------------
 | 
				
			||||||
	 * If I'm the only one holding any lock on this object, then there
 | 
						 * If I'm the only one holding any lock on this object, then there
 | 
				
			||||||
	 * cannot be a conflict. The same is true if I already hold this lock.
 | 
						 * cannot be a conflict. The same is true if I already hold this lock.
 | 
				
			||||||
	 * --------------------
 | 
						 * --------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (holder->nHolding == lock->nActive || holder->holders[lockmode] != 0)
 | 
						if (holder->nHolding == lock->nGranted || holder->holding[lockmode] != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		GrantLock(lock, holder, lockmode);
 | 
							GrantLock(lock, holder, lockmode);
 | 
				
			||||||
		HOLDER_PRINT("LockAcquire: owning", holder);
 | 
							HOLDER_PRINT("LockAcquire: owning", holder);
 | 
				
			||||||
@@ -630,8 +638,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	 * then there is no conflict, either.
 | 
						 * then there is no conflict, either.
 | 
				
			||||||
	 * --------------------
 | 
						 * --------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	LockCountMyLocks(holder->tag.lock, MyProc, myHolders);
 | 
						LockCountMyLocks(holder->tag.lock, MyProc, myHolding);
 | 
				
			||||||
	if (myHolders[lockmode] != 0)
 | 
						if (myHolding[lockmode] != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		GrantLock(lock, holder, lockmode);
 | 
							GrantLock(lock, holder, lockmode);
 | 
				
			||||||
		HOLDER_PRINT("LockAcquire: my other XID owning", holder);
 | 
							HOLDER_PRINT("LockAcquire: my other XID owning", holder);
 | 
				
			||||||
@@ -650,7 +658,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		 */
 | 
							 */
 | 
				
			||||||
		for (i = 1; i <= lockMethodTable->ctl->numLockModes; i++)
 | 
							for (i = 1; i <= lockMethodTable->ctl->numLockModes; i++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (myHolders[i] > 0 &&
 | 
								if (myHolding[i] > 0 &&
 | 
				
			||||||
				lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
 | 
									lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
 | 
				
			||||||
				break;			/* yes, there is a conflict */
 | 
									break;			/* yes, there is a conflict */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -664,12 +672,12 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		else
 | 
							else
 | 
				
			||||||
			status = LockResolveConflicts(lockmethod, lockmode,
 | 
								status = LockResolveConflicts(lockmethod, lockmode,
 | 
				
			||||||
										  lock, holder,
 | 
															  lock, holder,
 | 
				
			||||||
										  MyProc, myHolders);
 | 
															  MyProc, myHolding);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		status = LockResolveConflicts(lockmethod, lockmode,
 | 
							status = LockResolveConflicts(lockmethod, lockmode,
 | 
				
			||||||
									  lock, holder,
 | 
														  lock, holder,
 | 
				
			||||||
									  MyProc, myHolders);
 | 
														  MyProc, myHolding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status == STATUS_OK)
 | 
						if (status == STATUS_OK)
 | 
				
			||||||
		GrantLock(lock, holder, lockmode);
 | 
							GrantLock(lock, holder, lockmode);
 | 
				
			||||||
@@ -694,11 +702,11 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				HOLDER_PRINT("LockAcquire: NHOLDING", holder);
 | 
									HOLDER_PRINT("LockAcquire: NHOLDING", holder);
 | 
				
			||||||
			lock->nHolding--;
 | 
								lock->nRequested--;
 | 
				
			||||||
			lock->holders[lockmode]--;
 | 
								lock->requested[lockmode]--;
 | 
				
			||||||
			LOCK_PRINT("LockAcquire: user lock failed", lock, lockmode);
 | 
								LOCK_PRINT("LockAcquire: user lock failed", lock, lockmode);
 | 
				
			||||||
			Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
 | 
								Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
 | 
				
			||||||
			Assert(lock->nActive <= lock->nHolding);
 | 
								Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
			SpinRelease(masterLock);
 | 
								SpinRelease(masterLock);
 | 
				
			||||||
			return FALSE;
 | 
								return FALSE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -708,17 +716,17 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		 * Construct bitmask of locks this process holds on this object.
 | 
							 * Construct bitmask of locks this process holds on this object.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			int			holdLock = 0;
 | 
								int			heldLocks = 0;
 | 
				
			||||||
			int			tmpMask;
 | 
								int			tmpMask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (i = 1, tmpMask = 2;
 | 
								for (i = 1, tmpMask = 2;
 | 
				
			||||||
				 i <= lockMethodTable->ctl->numLockModes;
 | 
									 i <= lockMethodTable->ctl->numLockModes;
 | 
				
			||||||
				 i++, tmpMask <<= 1)
 | 
									 i++, tmpMask <<= 1)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (myHolders[i] > 0)
 | 
									if (myHolding[i] > 0)
 | 
				
			||||||
					holdLock |= tmpMask;
 | 
										heldLocks |= tmpMask;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			MyProc->holdLock = holdLock;
 | 
								MyProc->heldLocks = heldLocks;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
@@ -736,7 +744,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		 * Check the holder entry status, in case something in the ipc
 | 
							 * Check the holder entry status, in case something in the ipc
 | 
				
			||||||
		 * communication doesn't work correctly.
 | 
							 * communication doesn't work correctly.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (!((holder->nHolding > 0) && (holder->holders[lockmode] > 0)))
 | 
							if (!((holder->nHolding > 0) && (holder->holding[lockmode] > 0)))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			HOLDER_PRINT("LockAcquire: INCONSISTENT", holder);
 | 
								HOLDER_PRINT("LockAcquire: INCONSISTENT", holder);
 | 
				
			||||||
			LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
 | 
								LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
 | 
				
			||||||
@@ -763,7 +771,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
 * determining whether or not any new lock acquired conflicts with
 | 
					 * determining whether or not any new lock acquired conflicts with
 | 
				
			||||||
 * the old ones.
 | 
					 * the old ones.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The caller can optionally pass the process's total holders counts, if
 | 
					 * The caller can optionally pass the process's total holding counts, if
 | 
				
			||||||
 * known.  If NULL is passed then these values will be computed internally.
 | 
					 * known.  If NULL is passed then these values will be computed internally.
 | 
				
			||||||
 * ----------------------------
 | 
					 * ----------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -773,28 +781,28 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
 | 
				
			|||||||
					 LOCK *lock,
 | 
										 LOCK *lock,
 | 
				
			||||||
					 HOLDER *holder,
 | 
										 HOLDER *holder,
 | 
				
			||||||
					 PROC *proc,
 | 
										 PROC *proc,
 | 
				
			||||||
					 int *myHolders)		/* myHolders[] array or NULL */
 | 
										 int *myHolding)		/* myHolding[] array or NULL */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	LOCKMETHODCTL *lockctl = LockMethodTable[lockmethod]->ctl;
 | 
						LOCKMETHODCTL *lockctl = LockMethodTable[lockmethod]->ctl;
 | 
				
			||||||
	int			numLockModes = lockctl->numLockModes;
 | 
						int			numLockModes = lockctl->numLockModes;
 | 
				
			||||||
	int			bitmask;
 | 
						int			bitmask;
 | 
				
			||||||
	int			i,
 | 
						int			i,
 | 
				
			||||||
				tmpMask;
 | 
									tmpMask;
 | 
				
			||||||
	int			localHolders[MAX_LOCKMODES];
 | 
						int			localHolding[MAX_LOCKMODES];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Assert((holder->nHolding >= 0) && (holder->holders[lockmode] >= 0));
 | 
						Assert((holder->nHolding >= 0) && (holder->holding[lockmode] >= 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ----------------------------
 | 
						/* ----------------------------
 | 
				
			||||||
	 * first check for global conflicts: If no locks conflict
 | 
						 * first check for global conflicts: If no locks conflict
 | 
				
			||||||
	 * with mine, then I get the lock.
 | 
						 * with mine, then I get the lock.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * Checking for conflict: lock->mask represents the types of
 | 
						 * Checking for conflict: lock->grantMask represents the types of
 | 
				
			||||||
	 * currently held locks.  conflictTable[lockmode] has a bit
 | 
						 * currently held locks.  conflictTable[lockmode] has a bit
 | 
				
			||||||
	 * set for each type of lock that conflicts with mine.	Bitwise
 | 
						 * set for each type of lock that conflicts with mine.	Bitwise
 | 
				
			||||||
	 * compare tells if there is a conflict.
 | 
						 * compare tells if there is a conflict.
 | 
				
			||||||
	 * ----------------------------
 | 
						 * ----------------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!(lockctl->conflictTab[lockmode] & lock->mask))
 | 
						if (!(lockctl->conflictTab[lockmode] & lock->grantMask))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		HOLDER_PRINT("LockResolveConflicts: no conflict", holder);
 | 
							HOLDER_PRINT("LockResolveConflicts: no conflict", holder);
 | 
				
			||||||
		return STATUS_OK;
 | 
							return STATUS_OK;
 | 
				
			||||||
@@ -807,11 +815,11 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
 | 
				
			|||||||
	 * process under another XID also count as "our own locks".
 | 
						 * process under another XID also count as "our own locks".
 | 
				
			||||||
	 * ------------------------
 | 
						 * ------------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (myHolders == NULL)
 | 
						if (myHolding == NULL)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* Caller didn't do calculation of total holding for me */
 | 
							/* Caller didn't do calculation of total holding for me */
 | 
				
			||||||
		LockCountMyLocks(holder->tag.lock, proc, localHolders);
 | 
							LockCountMyLocks(holder->tag.lock, proc, localHolding);
 | 
				
			||||||
		myHolders = localHolders;
 | 
							myHolding = localHolding;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Compute mask of lock types held by other processes */
 | 
						/* Compute mask of lock types held by other processes */
 | 
				
			||||||
@@ -819,7 +827,7 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
 | 
				
			|||||||
	tmpMask = 2;
 | 
						tmpMask = 2;
 | 
				
			||||||
	for (i = 1; i <= numLockModes; i++, tmpMask <<= 1)
 | 
						for (i = 1; i <= numLockModes; i++, tmpMask <<= 1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (lock->activeHolders[i] != myHolders[i])
 | 
							if (lock->granted[i] != myHolding[i])
 | 
				
			||||||
			bitmask |= tmpMask;
 | 
								bitmask |= tmpMask;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -852,20 +860,20 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
 | 
				
			|||||||
 * be a net slowdown.
 | 
					 * be a net slowdown.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
 | 
					LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolding)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	HOLDER	   *holder = NULL;
 | 
						HOLDER	   *holder = NULL;
 | 
				
			||||||
	HOLDER	   *nextHolder = NULL;
 | 
						HOLDER	   *nextHolder = NULL;
 | 
				
			||||||
	SHM_QUEUE  *lockQueue = &(proc->lockQueue);
 | 
						SHM_QUEUE  *holderQueue = &(proc->holderQueue);
 | 
				
			||||||
	SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
 | 
						SHMEM_OFFSET end = MAKE_OFFSET(holderQueue);
 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MemSet(myHolders, 0, MAX_LOCKMODES * sizeof(int));
 | 
						MemSet(myHolding, 0, MAX_LOCKMODES * sizeof(int));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (SHMQueueEmpty(lockQueue))
 | 
						if (SHMQueueEmpty(holderQueue))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SHMQueueFirst(lockQueue, (Pointer *) &holder, &holder->queue);
 | 
						SHMQueueFirst(holderQueue, (Pointer *) &holder, &holder->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do
 | 
						do
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -885,7 +893,7 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			for (i = 1; i < MAX_LOCKMODES; i++)
 | 
								for (i = 1; i < MAX_LOCKMODES; i++)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				myHolders[i] += holder->holders[i];
 | 
									myHolding[i] += holder->holding[i];
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -894,47 +902,47 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, int *myHolders)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * LockGetMyHoldLocks -- compute bitmask of lock types held by a process
 | 
					 * LockGetMyHeldLocks -- compute bitmask of lock types held by a process
 | 
				
			||||||
 *		for a given lockable object.
 | 
					 *		for a given lockable object.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
LockGetMyHoldLocks(SHMEM_OFFSET lockOffset, PROC *proc)
 | 
					LockGetMyHeldLocks(SHMEM_OFFSET lockOffset, PROC *proc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			myHolders[MAX_LOCKMODES];
 | 
						int			myHolding[MAX_LOCKMODES];
 | 
				
			||||||
	int			holdLock = 0;
 | 
						int			heldLocks = 0;
 | 
				
			||||||
	int			i,
 | 
						int			i,
 | 
				
			||||||
				tmpMask;
 | 
									tmpMask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LockCountMyLocks(lockOffset, proc, myHolders);
 | 
						LockCountMyLocks(lockOffset, proc, myHolding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 1, tmpMask = 2;
 | 
						for (i = 1, tmpMask = 2;
 | 
				
			||||||
		 i < MAX_LOCKMODES;
 | 
							 i < MAX_LOCKMODES;
 | 
				
			||||||
		 i++, tmpMask <<= 1)
 | 
							 i++, tmpMask <<= 1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (myHolders[i] > 0)
 | 
							if (myHolding[i] > 0)
 | 
				
			||||||
			holdLock |= tmpMask;
 | 
								heldLocks |= tmpMask;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return holdLock;
 | 
						return heldLocks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * GrantLock -- update the lock and holder data structures to show
 | 
					 * GrantLock -- update the lock and holder data structures to show
 | 
				
			||||||
 *		the new lock has been granted.
 | 
					 *		the lock request has been granted.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode)
 | 
					GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	lock->nActive++;
 | 
						lock->nGranted++;
 | 
				
			||||||
	lock->activeHolders[lockmode]++;
 | 
						lock->granted[lockmode]++;
 | 
				
			||||||
	lock->mask |= BITS_ON[lockmode];
 | 
						lock->grantMask |= BITS_ON[lockmode];
 | 
				
			||||||
	if (lock->activeHolders[lockmode] == lock->holders[lockmode])
 | 
						if (lock->granted[lockmode] == lock->requested[lockmode])
 | 
				
			||||||
		lock->waitMask &= BITS_OFF[lockmode];
 | 
							lock->waitMask &= BITS_OFF[lockmode];
 | 
				
			||||||
	LOCK_PRINT("GrantLock", lock, lockmode);
 | 
						LOCK_PRINT("GrantLock", lock, lockmode);
 | 
				
			||||||
	Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] > 0));
 | 
						Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
 | 
				
			||||||
	Assert(lock->nActive <= lock->nHolding);
 | 
						Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
	holder->holders[lockmode]++;
 | 
						holder->holding[lockmode]++;
 | 
				
			||||||
	holder->nHolding++;
 | 
						holder->nHolding++;
 | 
				
			||||||
	Assert((holder->nHolding > 0) && (holder->holders[lockmode] > 0));
 | 
						Assert((holder->nHolding > 0) && (holder->holding[lockmode] > 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -952,14 +960,6 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	Assert(lockmethod < NumLockMethods);
 | 
						Assert(lockmethod < NumLockMethods);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * the waitqueue is ordered by priority. I insert myself according to
 | 
					 | 
				
			||||||
	 * the priority of the lock I am acquiring.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * SYNC NOTE: I am assuming that the lock table spinlock is sufficient
 | 
					 | 
				
			||||||
	 * synchronization for this queue.	That will not be true if/when
 | 
					 | 
				
			||||||
	 * people can be deleted from the queue by a SIGINT or something.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	LOCK_PRINT("WaitOnLock: sleeping on lock", lock, lockmode);
 | 
						LOCK_PRINT("WaitOnLock: sleeping on lock", lock, lockmode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	old_status = pstrdup(get_ps_display());
 | 
						old_status = pstrdup(get_ps_display());
 | 
				
			||||||
@@ -971,7 +971,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * NOTE: Think not to put any lock state cleanup after the call to
 | 
						 * NOTE: Think not to put any lock state cleanup after the call to
 | 
				
			||||||
	 * ProcSleep, in either the normal or failure path.  The lock state
 | 
						 * ProcSleep, in either the normal or failure path.  The lock state
 | 
				
			||||||
	 * must be fully set by the lock grantor, or by HandleDeadlock if we
 | 
						 * must be fully set by the lock grantor, or by HandleDeadLock if we
 | 
				
			||||||
	 * give up waiting for the lock.  This is necessary because of the
 | 
						 * give up waiting for the lock.  This is necessary because of the
 | 
				
			||||||
	 * possibility that a cancel/die interrupt will interrupt ProcSleep
 | 
						 * possibility that a cancel/die interrupt will interrupt ProcSleep
 | 
				
			||||||
	 * after someone else grants us the lock, but before we've noticed it.
 | 
						 * after someone else grants us the lock, but before we've noticed it.
 | 
				
			||||||
@@ -1074,9 +1074,6 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	LOCK_PRINT("LockRelease: found", lock, lockmode);
 | 
						LOCK_PRINT("LockRelease: found", lock, lockmode);
 | 
				
			||||||
	Assert((lock->nHolding > 0) && (lock->holders[lockmode] >= 0));
 | 
					 | 
				
			||||||
	Assert((lock->nActive > 0) && (lock->activeHolders[lockmode] >= 0));
 | 
					 | 
				
			||||||
	Assert(lock->nActive <= lock->nHolding);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Find the holder entry for this holder.
 | 
						 * Find the holder entry for this holder.
 | 
				
			||||||
@@ -1107,29 +1104,32 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	 * Check that we are actually holding a lock of the type we want to
 | 
						 * Check that we are actually holding a lock of the type we want to
 | 
				
			||||||
	 * release.
 | 
						 * release.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!(holder->holders[lockmode] > 0))
 | 
						if (!(holder->holding[lockmode] > 0))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		SpinRelease(masterLock);
 | 
							SpinRelease(masterLock);
 | 
				
			||||||
		HOLDER_PRINT("LockRelease: WRONGTYPE", holder);
 | 
							HOLDER_PRINT("LockRelease: WRONGTYPE", holder);
 | 
				
			||||||
		elog(NOTICE, "LockRelease: you don't own a lock of type %s",
 | 
							elog(NOTICE, "LockRelease: you don't own a lock of type %s",
 | 
				
			||||||
			 lock_types[lockmode]);
 | 
								 lock_types[lockmode]);
 | 
				
			||||||
		Assert(holder->holders[lockmode] >= 0);
 | 
							Assert(holder->holding[lockmode] >= 0);
 | 
				
			||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Assert(holder->nHolding > 0);
 | 
						Assert(holder->nHolding > 0);
 | 
				
			||||||
 | 
						Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
 | 
				
			||||||
 | 
						Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
 | 
				
			||||||
 | 
						Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * fix the general lock stats
 | 
						 * fix the general lock stats
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	lock->nHolding--;
 | 
						lock->nRequested--;
 | 
				
			||||||
	lock->holders[lockmode]--;
 | 
						lock->requested[lockmode]--;
 | 
				
			||||||
	lock->nActive--;
 | 
						lock->nGranted--;
 | 
				
			||||||
	lock->activeHolders[lockmode]--;
 | 
						lock->granted[lockmode]--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!(lock->activeHolders[lockmode]))
 | 
						if (lock->granted[lockmode] == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* change the conflict mask.  No more of this lock type. */
 | 
							/* change the conflict mask.  No more of this lock type. */
 | 
				
			||||||
		lock->mask &= BITS_OFF[lockmode];
 | 
							lock->grantMask &= BITS_OFF[lockmode];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NOT_USED
 | 
					#ifdef NOT_USED
 | 
				
			||||||
@@ -1139,14 +1139,14 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	 * with the remaining locks.
 | 
						 * with the remaining locks.
 | 
				
			||||||
	 * --------------------------
 | 
						 * --------------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (lock->activeHolders[lockmode])
 | 
						if (lock->granted[lockmode])
 | 
				
			||||||
		wakeupNeeded = false;
 | 
							wakeupNeeded = false;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Above is not valid any more (due to MVCC lock modes). Actually
 | 
							 * Above is not valid any more (due to MVCC lock modes). Actually
 | 
				
			||||||
		 * we should compare activeHolders[lockmode] with number of
 | 
							 * we should compare granted[lockmode] with number of
 | 
				
			||||||
		 * waiters holding lock of this type and try to wakeup only if
 | 
							 * waiters holding lock of this type and try to wakeup only if
 | 
				
			||||||
		 * these numbers are equal (and lock released conflicts with locks
 | 
							 * these numbers are equal (and lock released conflicts with locks
 | 
				
			||||||
		 * requested by waiters). For the moment we only check the last
 | 
							 * requested by waiters). For the moment we only check the last
 | 
				
			||||||
@@ -1156,11 +1156,11 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
		wakeupNeeded = true;
 | 
							wakeupNeeded = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LOCK_PRINT("LockRelease: updated", lock, lockmode);
 | 
						LOCK_PRINT("LockRelease: updated", lock, lockmode);
 | 
				
			||||||
	Assert((lock->nHolding >= 0) && (lock->holders[lockmode] >= 0));
 | 
						Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
 | 
				
			||||||
	Assert((lock->nActive >= 0) && (lock->activeHolders[lockmode] >= 0));
 | 
						Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
 | 
				
			||||||
	Assert(lock->nActive <= lock->nHolding);
 | 
						Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!lock->nHolding)
 | 
						if (!lock->nRequested)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* ------------------
 | 
							/* ------------------
 | 
				
			||||||
		 * if there's no one waiting in the queue,
 | 
							 * if there's no one waiting in the queue,
 | 
				
			||||||
@@ -1180,10 +1180,10 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Now fix the per-holder lock stats.
 | 
						 * Now fix the per-holder lock stats.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	holder->holders[lockmode]--;
 | 
						holder->holding[lockmode]--;
 | 
				
			||||||
	holder->nHolding--;
 | 
						holder->nHolding--;
 | 
				
			||||||
	HOLDER_PRINT("LockRelease: updated", holder);
 | 
						HOLDER_PRINT("LockRelease: updated", holder);
 | 
				
			||||||
	Assert((holder->nHolding >= 0) && (holder->holders[lockmode] >= 0));
 | 
						Assert((holder->nHolding >= 0) && (holder->holding[lockmode] >= 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If this was my last hold on this lock, delete my entry in the holder
 | 
						 * If this was my last hold on this lock, delete my entry in the holder
 | 
				
			||||||
@@ -1236,8 +1236,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	HOLDER	   *holder = NULL;
 | 
						HOLDER	   *holder = NULL;
 | 
				
			||||||
	HOLDER	   *nextHolder = NULL;
 | 
						HOLDER	   *nextHolder = NULL;
 | 
				
			||||||
	SHM_QUEUE  *lockQueue = &(proc->lockQueue);
 | 
						SHM_QUEUE  *holderQueue = &(proc->holderQueue);
 | 
				
			||||||
	SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
 | 
						SHMEM_OFFSET end = MAKE_OFFSET(holderQueue);
 | 
				
			||||||
	SPINLOCK	masterLock;
 | 
						SPINLOCK	masterLock;
 | 
				
			||||||
	LOCKMETHODTABLE *lockMethodTable;
 | 
						LOCKMETHODTABLE *lockMethodTable;
 | 
				
			||||||
	int			i,
 | 
						int			i,
 | 
				
			||||||
@@ -1260,7 +1260,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (SHMQueueEmpty(lockQueue))
 | 
						if (SHMQueueEmpty(holderQueue))
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	numLockModes = lockMethodTable->ctl->numLockModes;
 | 
						numLockModes = lockMethodTable->ctl->numLockModes;
 | 
				
			||||||
@@ -1268,7 +1268,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	SpinAcquire(masterLock);
 | 
						SpinAcquire(masterLock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SHMQueueFirst(lockQueue, (Pointer *) &holder, &holder->queue);
 | 
						SHMQueueFirst(holderQueue, (Pointer *) &holder, &holder->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nleft = 0;
 | 
						nleft = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1308,53 +1308,55 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		HOLDER_PRINT("LockReleaseAll", holder);
 | 
							HOLDER_PRINT("LockReleaseAll", holder);
 | 
				
			||||||
		LOCK_PRINT("LockReleaseAll", lock, 0);
 | 
							LOCK_PRINT("LockReleaseAll", lock, 0);
 | 
				
			||||||
		Assert(lock->nHolding > 0);
 | 
							Assert(lock->nRequested >= 0);
 | 
				
			||||||
		Assert(lock->nActive > 0);
 | 
							Assert(lock->nGranted >= 0);
 | 
				
			||||||
		Assert(lock->nActive <= lock->nHolding);
 | 
							Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
		Assert(holder->nHolding >= 0);
 | 
							Assert(holder->nHolding >= 0);
 | 
				
			||||||
		Assert(holder->nHolding <= lock->nHolding);
 | 
							Assert(holder->nHolding <= lock->nRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* ------------------
 | 
							/* ------------------
 | 
				
			||||||
		 * fix the general lock stats
 | 
							 * fix the general lock stats
 | 
				
			||||||
		 * ------------------
 | 
							 * ------------------
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (lock->nHolding != holder->nHolding)
 | 
							if (lock->nRequested != holder->nHolding)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			for (i = 1; i <= numLockModes; i++)
 | 
								for (i = 1; i <= numLockModes; i++)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Assert(holder->holders[i] >= 0);
 | 
									Assert(holder->holding[i] >= 0);
 | 
				
			||||||
				lock->holders[i] -= holder->holders[i];
 | 
									if (holder->holding[i] > 0)
 | 
				
			||||||
				lock->activeHolders[i] -= holder->holders[i];
 | 
									{
 | 
				
			||||||
				Assert((lock->holders[i] >= 0) \
 | 
										lock->requested[i] -= holder->holding[i];
 | 
				
			||||||
					   &&(lock->activeHolders[i] >= 0));
 | 
										lock->granted[i] -= holder->holding[i];
 | 
				
			||||||
				if (!lock->activeHolders[i])
 | 
										Assert(lock->requested[i] >= 0 && lock->granted[i] >= 0);
 | 
				
			||||||
					lock->mask &= BITS_OFF[i];
 | 
										if (lock->granted[i] == 0)
 | 
				
			||||||
 | 
											lock->grantMask &= BITS_OFF[i];
 | 
				
			||||||
					/*
 | 
										/*
 | 
				
			||||||
					 * Read comments in LockRelease
 | 
										 * Read comments in LockRelease
 | 
				
			||||||
					 */
 | 
										 */
 | 
				
			||||||
				if (!wakeupNeeded && holder->holders[i] > 0 &&
 | 
										if (!wakeupNeeded &&
 | 
				
			||||||
						lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
 | 
											lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
 | 
				
			||||||
						wakeupNeeded = true;
 | 
											wakeupNeeded = true;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			lock->nHolding -= holder->nHolding;
 | 
								}
 | 
				
			||||||
			lock->nActive -= holder->nHolding;
 | 
								lock->nRequested -= holder->nHolding;
 | 
				
			||||||
			Assert((lock->nHolding >= 0) && (lock->nActive >= 0));
 | 
								lock->nGranted -= holder->nHolding;
 | 
				
			||||||
			Assert(lock->nActive <= lock->nHolding);
 | 
								Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
 | 
				
			||||||
 | 
								Assert(lock->nGranted <= lock->nRequested);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* --------------
 | 
								/* --------------
 | 
				
			||||||
			 * set nHolding to zero so that we can garbage collect the lock
 | 
								 * set nRequested to zero so that we can garbage collect the lock
 | 
				
			||||||
			 * down below...
 | 
								 * down below...
 | 
				
			||||||
			 * --------------
 | 
								 * --------------
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			lock->nHolding = 0;
 | 
								lock->nRequested = 0;
 | 
				
			||||||
 | 
								lock->nGranted = 0;
 | 
				
			||||||
			/* Fix the lock status, just for next LOCK_PRINT message. */
 | 
								/* Fix the lock status, just for next LOCK_PRINT message. */
 | 
				
			||||||
			for (i = 1; i <= numLockModes; i++)
 | 
								for (i = 1; i <= numLockModes; i++)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Assert(lock->holders[i] == lock->activeHolders[i]);
 | 
									Assert(lock->requested[i] == lock->granted[i]);
 | 
				
			||||||
				lock->holders[i] = lock->activeHolders[i] = 0;
 | 
									lock->requested[i] = lock->granted[i] = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		LOCK_PRINT("LockReleaseAll: updated", lock, 0);
 | 
							LOCK_PRINT("LockReleaseAll: updated", lock, 0);
 | 
				
			||||||
@@ -1380,11 +1382,11 @@ LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
			return FALSE;
 | 
								return FALSE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!lock->nHolding)
 | 
							if (!lock->nRequested)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* --------------------
 | 
								/* --------------------
 | 
				
			||||||
			 * if there's no one waiting in the queue, we've just released
 | 
								 * We've just released the last lock, so garbage-collect the
 | 
				
			||||||
			 * the last lock.
 | 
								 * lock object.
 | 
				
			||||||
			 * --------------------
 | 
								 * --------------------
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
 | 
								LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
 | 
				
			||||||
@@ -1413,12 +1415,13 @@ next_item:
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
#ifdef LOCK_DEBUG
 | 
					#ifdef LOCK_DEBUG
 | 
				
			||||||
        if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
 | 
					        if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
 | 
				
			||||||
            elog(DEBUG, "LockReleaseAll: reinitializing lockQueue");
 | 
					            elog(DEBUG, "LockReleaseAll: reinitializing holderQueue");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		SHMQueueInit(lockQueue);
 | 
							SHMQueueInit(holderQueue);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SpinRelease(masterLock);
 | 
						SpinRelease(masterLock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef LOCK_DEBUG
 | 
					#ifdef LOCK_DEBUG
 | 
				
			||||||
    if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
 | 
					    if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
 | 
				
			||||||
        elog(DEBUG, "LockReleaseAll: done");
 | 
					        elog(DEBUG, "LockReleaseAll: done");
 | 
				
			||||||
@@ -1457,16 +1460,17 @@ LockShmemSize(int maxBackends)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * DeadlockCheck -- Checks for deadlocks for a given process
 | 
					 * DeadLockCheck -- Checks for deadlocks for a given process
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * We can't block on user locks, so no sense testing for deadlock
 | 
					 | 
				
			||||||
 * because there is no blocking, and no timer for the block.
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This code takes a list of locks a process holds, and the lock that
 | 
					 * 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
 | 
					 * 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.  If no deadlock
 | 
					 * 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.
 | 
					 * is found, it goes on to look at all the processes waiting on their locks.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * We can't block on user locks, so no sense testing for deadlock
 | 
				
			||||||
 | 
					 * because there is no blocking, and no timer for the block.  So,
 | 
				
			||||||
 | 
					 * only look at regular locks.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * We have already locked the master lock before being called.
 | 
					 * We have already locked the master lock before being called.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool
 | 
					bool
 | 
				
			||||||
@@ -1476,8 +1480,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
	HOLDER	   *nextHolder = NULL;
 | 
						HOLDER	   *nextHolder = NULL;
 | 
				
			||||||
	PROC	   *waitProc;
 | 
						PROC	   *waitProc;
 | 
				
			||||||
	PROC_QUEUE *waitQueue;
 | 
						PROC_QUEUE *waitQueue;
 | 
				
			||||||
	SHM_QUEUE  *lockQueue = &(thisProc->lockQueue);
 | 
						SHM_QUEUE  *holderQueue = &(thisProc->holderQueue);
 | 
				
			||||||
	SHMEM_OFFSET end = MAKE_OFFSET(lockQueue);
 | 
						SHMEM_OFFSET end = MAKE_OFFSET(holderQueue);
 | 
				
			||||||
	LOCKMETHODCTL *lockctl = LockMethodTable[DEFAULT_LOCKMETHOD]->ctl;
 | 
						LOCKMETHODCTL *lockctl = LockMethodTable[DEFAULT_LOCKMETHOD]->ctl;
 | 
				
			||||||
	LOCK	   *lock;
 | 
						LOCK	   *lock;
 | 
				
			||||||
	int			i,
 | 
						int			i,
 | 
				
			||||||
@@ -1494,10 +1498,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
		nprocs = 1;
 | 
							nprocs = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (SHMQueueEmpty(lockQueue))
 | 
						/*
 | 
				
			||||||
 | 
						 * Scan over all the locks held/awaited by thisProc.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (SHMQueueEmpty(holderQueue))
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SHMQueueFirst(lockQueue, (Pointer *) &holder, &holder->queue);
 | 
						SHMQueueFirst(holderQueue, (Pointer *) &holder, &holder->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do
 | 
						do
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1525,7 +1532,7 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
		LOCK_PRINT("DeadLockCheck", lock, 0);
 | 
							LOCK_PRINT("DeadLockCheck", lock, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * waitLock is always in lockQueue of waiting proc, if !first_run
 | 
							 * waitLock is always in holderQueue of waiting proc, if !first_run
 | 
				
			||||||
		 * then upper caller will handle waitProcs queue of waitLock.
 | 
							 * then upper caller will handle waitProcs queue of waitLock.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (thisProc->waitLock == lock && !first_run)
 | 
							if (thisProc->waitLock == lock && !first_run)
 | 
				
			||||||
@@ -1542,13 +1549,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
			Assert(holder->nHolding > 0);
 | 
								Assert(holder->nHolding > 0);
 | 
				
			||||||
			for (lm = 1; lm <= lockctl->numLockModes; lm++)
 | 
								for (lm = 1; lm <= lockctl->numLockModes; lm++)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (holder->holders[lm] > 0 &&
 | 
									if (holder->holding[lm] > 0 &&
 | 
				
			||||||
					lockctl->conflictTab[lm] & findlock->waitMask)
 | 
										lockctl->conflictTab[lm] & findlock->waitMask)
 | 
				
			||||||
					return true;
 | 
										return true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Else - get the next lock from thisProc's lockQueue
 | 
								 * Else - get the next lock from thisProc's holderQueue
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			goto nxtl;
 | 
								goto nxtl;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -1557,6 +1564,8 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
		waitProc = (PROC *) MAKE_PTR(waitQueue->links.prev);
 | 
							waitProc = (PROC *) MAKE_PTR(waitQueue->links.prev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
 | 
							 * Inner loop scans over all processes waiting for this lock.
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
		 * NOTE: loop must count down because we want to examine each item
 | 
							 * NOTE: loop must count down because we want to examine each item
 | 
				
			||||||
		 * in the queue even if waitQueue->size decreases due to waking up
 | 
							 * in the queue even if waitQueue->size decreases due to waking up
 | 
				
			||||||
		 * some of the processes.
 | 
							 * some of the processes.
 | 
				
			||||||
@@ -1573,14 +1582,14 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
			if (lock == findlock)		/* first_run also true */
 | 
								if (lock == findlock)		/* first_run also true */
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/*
 | 
									/*
 | 
				
			||||||
				 * If me blocked by his holdlock...
 | 
									 * If I'm blocked by his heldLocks...
 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
				if (lockctl->conflictTab[MyProc->waitLockMode] & waitProc->holdLock)
 | 
									if (lockctl->conflictTab[MyProc->waitLockMode] & waitProc->heldLocks)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					/* and he blocked by me -> deadlock */
 | 
										/* and he blocked by me -> deadlock */
 | 
				
			||||||
					if (lockctl->conflictTab[waitProc->waitLockMode] & MyProc->holdLock)
 | 
										if (lockctl->conflictTab[waitProc->waitLockMode] & MyProc->heldLocks)
 | 
				
			||||||
						return true;
 | 
											return true;
 | 
				
			||||||
					/* we shouldn't look at lockQueue of our blockers */
 | 
										/* we shouldn't look at holderQueue of our blockers */
 | 
				
			||||||
					goto nextWaitProc;
 | 
										goto nextWaitProc;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1591,11 +1600,11 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
				 * implicitly). Note that we don't do like test if
 | 
									 * implicitly). Note that we don't do like test if
 | 
				
			||||||
				 * !first_run (when thisProc is holder and non-waiter on
 | 
									 * !first_run (when thisProc is holder and non-waiter on
 | 
				
			||||||
				 * lock) and so we call DeadLockCheck below for every
 | 
									 * lock) and so we call DeadLockCheck below for every
 | 
				
			||||||
				 * waitProc in thisProc->lockQueue, even for waitProc-s
 | 
									 * waitProc in thisProc->holderQueue, even for waitProc-s
 | 
				
			||||||
				 * un-blocked by thisProc. Should we? This could save us
 | 
									 * un-blocked by thisProc. Should we? This could save us
 | 
				
			||||||
				 * some time...
 | 
									 * some time...
 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
				if (!(lockctl->conflictTab[waitProc->waitLockMode] & MyProc->holdLock) &&
 | 
									if (!(lockctl->conflictTab[waitProc->waitLockMode] & MyProc->heldLocks) &&
 | 
				
			||||||
					!(lockctl->conflictTab[waitProc->waitLockMode] & (1 << MyProc->waitLockMode)))
 | 
										!(lockctl->conflictTab[waitProc->waitLockMode] & (1 << MyProc->waitLockMode)))
 | 
				
			||||||
					goto nextWaitProc;
 | 
										goto nextWaitProc;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -1609,13 +1618,13 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
					goto nextWaitProc;
 | 
										goto nextWaitProc;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Recursively check this process's lockQueue. */
 | 
								/* Recursively check this process's holderQueue. */
 | 
				
			||||||
			Assert(nprocs < MAXBACKENDS);
 | 
								Assert(nprocs < MAXBACKENDS);
 | 
				
			||||||
			checked_procs[nprocs++] = waitProc;
 | 
								checked_procs[nprocs++] = waitProc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (DeadLockCheck(waitProc, findlock))
 | 
								if (DeadLockCheck(waitProc, findlock))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				int			holdLock;
 | 
									int			heldLocks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/*
 | 
									/*
 | 
				
			||||||
				 * Ok, but is waitProc waiting for me (thisProc) ?
 | 
									 * Ok, but is waitProc waiting for me (thisProc) ?
 | 
				
			||||||
@@ -1623,15 +1632,15 @@ DeadLockCheck(PROC *thisProc, LOCK *findlock)
 | 
				
			|||||||
				if (thisProc->waitLock == lock)
 | 
									if (thisProc->waitLock == lock)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Assert(first_run);
 | 
										Assert(first_run);
 | 
				
			||||||
					holdLock = thisProc->holdLock;
 | 
										heldLocks = thisProc->heldLocks;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					/* should we cache holdLock to speed this up? */
 | 
										/* should we cache heldLocks to speed this up? */
 | 
				
			||||||
					holdLock = LockGetMyHoldLocks(holder->tag.lock, thisProc);
 | 
										heldLocks = LockGetMyHeldLocks(holder->tag.lock, thisProc);
 | 
				
			||||||
					Assert(holdLock != 0);
 | 
										Assert(heldLocks != 0);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (lockctl->conflictTab[waitProc->waitLockMode] & holdLock)
 | 
									if (lockctl->conflictTab[waitProc->waitLockMode] & heldLocks)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					/*
 | 
										/*
 | 
				
			||||||
					 * Last attempt to avoid deadlock: try to wakeup myself.
 | 
										 * Last attempt to avoid deadlock: try to wakeup myself.
 | 
				
			||||||
@@ -1703,7 +1712,7 @@ nxtl:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef LOCK_DEBUG
 | 
					#ifdef LOCK_DEBUG
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Dump all locks in the proc->lockQueue. Must have already acquired
 | 
					 * Dump all locks in the proc->holderQueue. Must have already acquired
 | 
				
			||||||
 * the masterLock.
 | 
					 * the masterLock.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@@ -1711,7 +1720,7 @@ DumpLocks(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	SHMEM_OFFSET location;
 | 
						SHMEM_OFFSET location;
 | 
				
			||||||
	PROC	   *proc;
 | 
						PROC	   *proc;
 | 
				
			||||||
	SHM_QUEUE  *lockQueue;
 | 
						SHM_QUEUE  *holderQueue;
 | 
				
			||||||
	HOLDER	   *holder = NULL;
 | 
						HOLDER	   *holder = NULL;
 | 
				
			||||||
	HOLDER	   *nextHolder = NULL;
 | 
						HOLDER	   *nextHolder = NULL;
 | 
				
			||||||
	SHMEM_OFFSET end;
 | 
						SHMEM_OFFSET end;
 | 
				
			||||||
@@ -1725,8 +1734,8 @@ DumpLocks(void)
 | 
				
			|||||||
	proc = (PROC *) MAKE_PTR(location);
 | 
						proc = (PROC *) MAKE_PTR(location);
 | 
				
			||||||
	if (proc != MyProc)
 | 
						if (proc != MyProc)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	lockQueue = &proc->lockQueue;
 | 
						holderQueue = &proc->holderQueue;
 | 
				
			||||||
	end = MAKE_OFFSET(lockQueue);
 | 
						end = MAKE_OFFSET(holderQueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Assert(lockmethod < NumLockMethods);
 | 
						Assert(lockmethod < NumLockMethods);
 | 
				
			||||||
	lockMethodTable = LockMethodTable[lockmethod];
 | 
						lockMethodTable = LockMethodTable[lockmethod];
 | 
				
			||||||
@@ -1736,10 +1745,10 @@ DumpLocks(void)
 | 
				
			|||||||
	if (proc->waitLock)
 | 
						if (proc->waitLock)
 | 
				
			||||||
		LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);
 | 
							LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (SHMQueueEmpty(lockQueue))
 | 
						if (SHMQueueEmpty(holderQueue))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SHMQueueFirst(lockQueue, (Pointer *) &holder, &holder->queue);
 | 
						SHMQueueFirst(holderQueue, (Pointer *) &holder, &holder->queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do
 | 
						do
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.92 2001/01/14 05:08:16 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.93 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -48,7 +48,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.92 2001/01/14 05:08:16 tgl Exp $
 | 
					 * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.93 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include "postgres.h"
 | 
					#include "postgres.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -230,7 +230,7 @@ InitProcess(void)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* this cannot be initialized until after the buffer pool */
 | 
							/* this cannot be initialized until after the buffer pool */
 | 
				
			||||||
		SHMQueueInit(&(MyProc->lockQueue));
 | 
							SHMQueueInit(&(MyProc->holderQueue));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -311,8 +311,8 @@ ZeroProcSemaphore(PROC *proc)
 | 
				
			|||||||
 * Locktable lock must be held by caller.
 | 
					 * Locktable lock must be held by caller.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NB: this does not remove the process' holder object, nor the lock object,
 | 
					 * NB: this does not remove the process' holder object, nor the lock object,
 | 
				
			||||||
 * even though their holder counts might now have gone to zero.  That will
 | 
					 * even though their counts might now have gone to zero.  That will happen
 | 
				
			||||||
 * happen during a subsequent LockReleaseAll call, which we expect will happen
 | 
					 * during a subsequent LockReleaseAll call, which we expect will happen
 | 
				
			||||||
 * during transaction cleanup.  (Removal of a proc from its wait queue by
 | 
					 * during transaction cleanup.  (Removal of a proc from its wait queue by
 | 
				
			||||||
 * this routine can only happen if we are aborting the transaction.)
 | 
					 * this routine can only happen if we are aborting the transaction.)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -331,14 +331,14 @@ RemoveFromWaitQueue(PROC *proc)
 | 
				
			|||||||
	SHMQueueDelete(&(proc->links));
 | 
						SHMQueueDelete(&(proc->links));
 | 
				
			||||||
	waitLock->waitProcs.size--;
 | 
						waitLock->waitProcs.size--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Undo increments of holder counts by waiting process */
 | 
						/* Undo increments of request counts by waiting process */
 | 
				
			||||||
	Assert(waitLock->nHolding > 0);
 | 
						Assert(waitLock->nRequested > 0);
 | 
				
			||||||
	Assert(waitLock->nHolding > proc->waitLock->nActive);
 | 
						Assert(waitLock->nRequested > proc->waitLock->nGranted);
 | 
				
			||||||
	waitLock->nHolding--;
 | 
						waitLock->nRequested--;
 | 
				
			||||||
	Assert(waitLock->holders[lockmode] > 0);
 | 
						Assert(waitLock->requested[lockmode] > 0);
 | 
				
			||||||
	waitLock->holders[lockmode]--;
 | 
						waitLock->requested[lockmode]--;
 | 
				
			||||||
	/* don't forget to clear waitMask bit if appropriate */
 | 
						/* don't forget to clear waitMask bit if appropriate */
 | 
				
			||||||
	if (waitLock->activeHolders[lockmode] == waitLock->holders[lockmode])
 | 
						if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
 | 
				
			||||||
		waitLock->waitMask &= ~(1 << lockmode);
 | 
							waitLock->waitMask &= ~(1 << lockmode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clean up the proc's own state */
 | 
						/* Clean up the proc's own state */
 | 
				
			||||||
@@ -546,7 +546,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
 | 
				
			|||||||
	int			waitMask = lock->waitMask;
 | 
						int			waitMask = lock->waitMask;
 | 
				
			||||||
	PROC	   *proc;
 | 
						PROC	   *proc;
 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	int			aheadHolders[MAX_LOCKMODES];
 | 
						int			aheadGranted[MAX_LOCKMODES];
 | 
				
			||||||
	bool		selfConflict = (lockctl->conflictTab[lockmode] & myMask),
 | 
						bool		selfConflict = (lockctl->conflictTab[lockmode] & myMask),
 | 
				
			||||||
				prevSame = false;
 | 
									prevSame = false;
 | 
				
			||||||
#ifndef __BEOS__
 | 
					#ifndef __BEOS__
 | 
				
			||||||
@@ -559,7 +559,7 @@ ProcSleep(LOCKMETHODCTL *lockctl,
 | 
				
			|||||||
	MyProc->waitLock = lock;
 | 
						MyProc->waitLock = lock;
 | 
				
			||||||
	MyProc->waitHolder = holder;
 | 
						MyProc->waitHolder = holder;
 | 
				
			||||||
	MyProc->waitLockMode = lockmode;
 | 
						MyProc->waitLockMode = lockmode;
 | 
				
			||||||
	/* We assume the caller set up MyProc->holdLock */
 | 
						/* We assume the caller set up MyProc->heldLocks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
 | 
						proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -567,57 +567,61 @@ ProcSleep(LOCKMETHODCTL *lockctl,
 | 
				
			|||||||
	if (!(lockctl->conflictTab[lockmode] & waitMask))
 | 
						if (!(lockctl->conflictTab[lockmode] & waitMask))
 | 
				
			||||||
		goto ins;
 | 
							goto ins;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* otherwise, determine where we should go into the queue */
 | 
				
			||||||
	for (i = 1; i < MAX_LOCKMODES; i++)
 | 
						for (i = 1; i < MAX_LOCKMODES; i++)
 | 
				
			||||||
		aheadHolders[i] = lock->activeHolders[i];
 | 
							aheadGranted[i] = lock->granted[i];
 | 
				
			||||||
	(aheadHolders[lockmode])++;
 | 
						(aheadGranted[lockmode])++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < waitQueue->size; i++)
 | 
						for (i = 0; i < waitQueue->size; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* am I waiting for him ? */
 | 
							LOCKMODE	procWaitMode = proc->waitLockMode;
 | 
				
			||||||
		if (lockctl->conflictTab[lockmode] & proc->holdLock)
 | 
					
 | 
				
			||||||
 | 
							/* must I wait for him ? */
 | 
				
			||||||
 | 
							if (lockctl->conflictTab[lockmode] & proc->heldLocks)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* is he waiting for me ? */
 | 
								/* is he waiting for me ? */
 | 
				
			||||||
			if (lockctl->conflictTab[proc->waitLockMode] & MyProc->holdLock)
 | 
								if (lockctl->conflictTab[procWaitMode] & MyProc->heldLocks)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Yes, report deadlock failure */
 | 
									/* Yes, report deadlock failure */
 | 
				
			||||||
				MyProc->errType = STATUS_ERROR;
 | 
									MyProc->errType = STATUS_ERROR;
 | 
				
			||||||
				goto rt;
 | 
									goto rt;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			/* being waiting for him - go past */
 | 
								/* I must go after him in queue - so continue loop */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* if he waits for me */
 | 
							/* if he waits for me, go before him in queue */
 | 
				
			||||||
		else if (lockctl->conflictTab[proc->waitLockMode] & MyProc->holdLock)
 | 
							else if (lockctl->conflictTab[procWaitMode] & MyProc->heldLocks)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		/* if conflicting locks requested */
 | 
							/* if conflicting locks requested */
 | 
				
			||||||
		else if (lockctl->conflictTab[proc->waitLockMode] & myMask)
 | 
							else if (lockctl->conflictTab[procWaitMode] & myMask)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * If I request non self-conflicting lock and there are others
 | 
								 * If I request non self-conflicting lock and there are others
 | 
				
			||||||
			 * requesting the same lock just before me - stay here.
 | 
								 * requesting the same lock just before this guy - stop here.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (!selfConflict && prevSame)
 | 
								if (!selfConflict && prevSame)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Last attempt to don't move any more: if we don't conflict with
 | 
							 * Last attempt to not move any further to the back of the queue:
 | 
				
			||||||
		 * rest waiters in queue.
 | 
							 * if we don't conflict with remaining waiters, stop here.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		else if (!(lockctl->conflictTab[lockmode] & waitMask))
 | 
							else if (!(lockctl->conflictTab[lockmode] & waitMask))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		prevSame = (proc->waitLockMode == lockmode);
 | 
							/* Move past this guy, and update state accordingly */
 | 
				
			||||||
		(aheadHolders[proc->waitLockMode])++;
 | 
							prevSame = (procWaitMode == lockmode);
 | 
				
			||||||
		if (aheadHolders[proc->waitLockMode] == lock->holders[proc->waitLockMode])
 | 
							(aheadGranted[procWaitMode])++;
 | 
				
			||||||
			waitMask &= ~(1 << proc->waitLockMode);
 | 
							if (aheadGranted[procWaitMode] == lock->requested[procWaitMode])
 | 
				
			||||||
 | 
								waitMask &= ~(1 << procWaitMode);
 | 
				
			||||||
		proc = (PROC *) MAKE_PTR(proc->links.prev);
 | 
							proc = (PROC *) MAKE_PTR(proc->links.prev);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ins:;
 | 
					ins:;
 | 
				
			||||||
	/* -------------------
 | 
						/* -------------------
 | 
				
			||||||
	 * Insert self into queue.  These operations are atomic (because
 | 
						 * Insert self into queue, ahead of the given proc.
 | 
				
			||||||
	 * of the spinlock).
 | 
						 * These operations are atomic (because of the spinlock).
 | 
				
			||||||
	 * -------------------
 | 
						 * -------------------
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	SHMQueueInsertTL(&(proc->links), &(MyProc->links));
 | 
						SHMQueueInsertTL(&(proc->links), &(MyProc->links));
 | 
				
			||||||
@@ -838,7 +842,7 @@ nextProc:
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
ProcAddLock(SHM_QUEUE *elem)
 | 
					ProcAddLock(SHM_QUEUE *elem)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SHMQueueInsertTL(&MyProc->lockQueue, elem);
 | 
						SHMQueueInsertTL(&MyProc->holderQueue, elem);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* --------------------
 | 
					/* --------------------
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 | 
					 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 | 
				
			||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $Id: lock.h,v 1.40 2000/12/22 00:51:54 tgl Exp $
 | 
					 * $Id: lock.h,v 1.41 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -150,26 +150,28 @@ typedef struct LOCKTAG
 | 
				
			|||||||
 * Per-locked-object lock information:
 | 
					 * Per-locked-object lock information:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * tag -- uniquely identifies the object being locked
 | 
					 * tag -- uniquely identifies the object being locked
 | 
				
			||||||
 * mask -- union of the conflict masks of all lock types
 | 
					 * grantMask -- bitmask for all lock types currently granted on this object.
 | 
				
			||||||
 *		currently held on this object.
 | 
					 * waitMask -- bitmask for all lock types currently awaited on this object.
 | 
				
			||||||
 * waitProcs -- queue of processes waiting for this lock
 | 
					 * waitProcs -- queue of processes waiting for this lock.
 | 
				
			||||||
 * holders -- count of each lock type currently held on the
 | 
					 * requested -- count of each lock type currently requested on the lock
 | 
				
			||||||
 *		lock.
 | 
					 *		(includes requests already granted!!).
 | 
				
			||||||
 * nHolding -- total locks of all types.
 | 
					 * nRequested -- total requested locks of all types.
 | 
				
			||||||
 | 
					 * granted -- count of each lock type currently granted on the lock.
 | 
				
			||||||
 | 
					 * nGranted -- total granted locks of all types.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct LOCK
 | 
					typedef struct LOCK
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* hash key */
 | 
						/* hash key */
 | 
				
			||||||
	LOCKTAG		tag;
 | 
						LOCKTAG		tag;			/* unique identifier of lockable object */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* data */
 | 
						/* data */
 | 
				
			||||||
	int			mask;
 | 
						int			grantMask;		/* bitmask for lock types already granted */
 | 
				
			||||||
	int			waitMask;
 | 
						int			waitMask;		/* bitmask for lock types awaited */
 | 
				
			||||||
	PROC_QUEUE	waitProcs;
 | 
						PROC_QUEUE	waitProcs;		/* list of PROC objects waiting on lock */
 | 
				
			||||||
	int			holders[MAX_LOCKMODES];
 | 
						int			requested[MAX_LOCKMODES]; /* counts of requested locks */
 | 
				
			||||||
	int			nHolding;
 | 
						int			nRequested;		/* total of requested[] array */
 | 
				
			||||||
	int			activeHolders[MAX_LOCKMODES];
 | 
						int			granted[MAX_LOCKMODES];	/* counts of granted locks */
 | 
				
			||||||
	int			nActive;
 | 
						int			nGranted;		/* total of granted[] array */
 | 
				
			||||||
} LOCK;
 | 
					} LOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SHMEM_LOCKTAB_KEYSIZE  sizeof(LOCKTAG)
 | 
					#define SHMEM_LOCKTAB_KEYSIZE  sizeof(LOCKTAG)
 | 
				
			||||||
@@ -193,6 +195,12 @@ typedef struct LOCK
 | 
				
			|||||||
 * Currently, session holders are used for user locks and for cross-xact
 | 
					 * Currently, session holders are used for user locks and for cross-xact
 | 
				
			||||||
 * locks obtained for VACUUM.  We assume that a session lock never conflicts
 | 
					 * locks obtained for VACUUM.  We assume that a session lock never conflicts
 | 
				
			||||||
 * with per-transaction locks obtained by the same backend.
 | 
					 * with per-transaction locks obtained by the same backend.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The holding[] array counts the granted locks (of each type) represented
 | 
				
			||||||
 | 
					 * by this holder.  Note that there will be a holder object, possibly with
 | 
				
			||||||
 | 
					 * zero holding[], for any lock that the process is currently waiting on.
 | 
				
			||||||
 | 
					 * Otherwise, holder objects whose counts have gone to zero are recycled
 | 
				
			||||||
 | 
					 * as soon as convenient.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct HOLDERTAG
 | 
					typedef struct HOLDERTAG
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -204,12 +212,12 @@ typedef struct HOLDERTAG
 | 
				
			|||||||
typedef struct HOLDER
 | 
					typedef struct HOLDER
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* tag */
 | 
						/* tag */
 | 
				
			||||||
	HOLDERTAG	tag;
 | 
						HOLDERTAG	tag;			/* unique identifier of holder object */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* data */
 | 
						/* data */
 | 
				
			||||||
	int			holders[MAX_LOCKMODES];
 | 
						int			holding[MAX_LOCKMODES];	/* count of locks currently held */
 | 
				
			||||||
	int			nHolding;
 | 
						int			nHolding;		/* total of holding[] array */
 | 
				
			||||||
	SHM_QUEUE	queue;
 | 
						SHM_QUEUE	queue;			/* list link for process' list of holders */
 | 
				
			||||||
} HOLDER;
 | 
					} HOLDER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SHMEM_HOLDERTAB_KEYSIZE  sizeof(HOLDERTAG)
 | 
					#define SHMEM_HOLDERTAB_KEYSIZE  sizeof(HOLDERTAG)
 | 
				
			||||||
@@ -241,7 +249,7 @@ extern bool LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
 | 
				
			|||||||
						   bool allxids, TransactionId xid);
 | 
											   bool allxids, TransactionId xid);
 | 
				
			||||||
extern int LockResolveConflicts(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
					extern int LockResolveConflicts(LOCKMETHOD lockmethod, LOCKMODE lockmode,
 | 
				
			||||||
								LOCK *lock, HOLDER *holder, PROC *proc,
 | 
													LOCK *lock, HOLDER *holder, PROC *proc,
 | 
				
			||||||
								int *myHolders);
 | 
													int *myHolding);
 | 
				
			||||||
extern void GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode);
 | 
					extern void GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode);
 | 
				
			||||||
extern int	LockShmemSize(int maxBackends);
 | 
					extern int	LockShmemSize(int maxBackends);
 | 
				
			||||||
extern bool DeadLockCheck(PROC *thisProc, LOCK *findlock);
 | 
					extern bool DeadLockCheck(PROC *thisProc, LOCK *findlock);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 | 
					 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 | 
				
			||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $Id: proc.h,v 1.34 2001/01/14 05:08:16 tgl Exp $
 | 
					 * $Id: proc.h,v 1.35 2001/01/16 06:11:34 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -27,13 +27,20 @@ typedef struct
 | 
				
			|||||||
} SEMA;
 | 
					} SEMA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Each backend has:
 | 
					 * Each backend has a PROC struct in shared memory.  There is also a list
 | 
				
			||||||
 | 
					 * of currently-unused PROC structs that will be reallocated to new backends
 | 
				
			||||||
 | 
					 * (a fairly pointless optimization, but it's there anyway).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * links: list link for any list the PROC is in.  When waiting for a lock,
 | 
				
			||||||
 | 
					 * the PROC is linked into that lock's waitProcs queue.  A recycled PROC
 | 
				
			||||||
 | 
					 * is linked into ProcGlobal's freeProcs list.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct proc
 | 
					struct proc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* proc->links MUST BE THE FIRST ELEMENT OF STRUCT (see ProcWakeup()) */
 | 
						/* proc->links MUST BE THE FIRST ELEMENT OF STRUCT (see ProcWakeup()) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SHM_QUEUE	links;			/* proc can be waiting for one event(lock) */
 | 
						SHM_QUEUE	links;			/* list link if process is in a list */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SEMA		sem;			/* ONE semaphore to sleep on */
 | 
						SEMA		sem;			/* ONE semaphore to sleep on */
 | 
				
			||||||
	int			errType;		/* error code tells why we woke up */
 | 
						int			errType;		/* error code tells why we woke up */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,16 +55,17 @@ struct proc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Info about lock the process is currently waiting for, if any */
 | 
						/* Info about lock the process is currently waiting for, if any */
 | 
				
			||||||
	LOCK	   *waitLock;		/* Lock object we're sleeping on ... */
 | 
						LOCK	   *waitLock;		/* Lock object we're sleeping on ... */
 | 
				
			||||||
	HOLDER	   *waitHolder;		/* Per-holder info for our lock */
 | 
						HOLDER	   *waitHolder;		/* Per-holder info for awaited lock */
 | 
				
			||||||
	LOCKMODE	waitLockMode;	/* type of lock we're waiting for */
 | 
						LOCKMODE	waitLockMode;	/* type of lock we're waiting for */
 | 
				
			||||||
	LOCKMASK	holdLock;		/* bitmask for lock types already held */
 | 
						LOCKMASK	heldLocks;		/* bitmask for lock types already held on
 | 
				
			||||||
 | 
													 * this lock object by this backend */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			pid;			/* This backend's process id */
 | 
						int			pid;			/* This backend's process id */
 | 
				
			||||||
	Oid			databaseId;		/* OID of database this backend is using */
 | 
						Oid			databaseId;		/* OID of database this backend is using */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	short		sLocks[MAX_SPINS];		/* Spin lock stats */
 | 
						short		sLocks[MAX_SPINS];		/* Spin lock stats */
 | 
				
			||||||
	SHM_QUEUE	lockQueue;		/* locks associated with current
 | 
						SHM_QUEUE	holderQueue;	/* list of HOLDER objects for locks held or
 | 
				
			||||||
								 * transaction */
 | 
													 * awaited by this backend */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
 | 
					/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user