hi..i have questions about struct pgproc (in file proc.h) and proclock ( in 
file lock.h) of the postgresql source code, does anyone know the exact 
difference between pgproc and proclock structs??
thank you
-sumaira





_________________________________________________________________
Protect your PC - get McAfee.com VirusScan Online  
http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963


Wed, 05 Feb 2003 06:54:30 -0800
"Sumaira Ali" <nat_lazy@hotmail.com>
lock.h and proc.h
"Sumaira Ali" <nat_lazy@hotmail.com> writes:
> hi..i have questions about struct pgproc (in file proc.h) and proclock ( in 
> file lock.h) of the postgresql source code, does anyone know the exact 
> difference between pgproc and proclock structs??

There's one PGPROC per process.  There's one PROCLOCK for each process
and each lock that that process has any interest in (ie, either
currently holds or is waiting for).

The comments for these structs seem to be a bit of a mess at the moment :-(
Bruce renamed the struct types recently, but appears not to have done a
good job of adjusting the comments to match.  It may help to know that
a proclock object was formerly called a "holder".

			regards, tom lane

Thu, 06 Feb 2003 10:19:12 -0500
Tom Lane <tgl@sss.pgh.pa.us>
Re: lock.h and proc.h 
Attached is a patch I just applied to clean this up.  I didn't realize
how bad it was. 

The reason for the name changes is that PROCLOCK is used by lock holders
and lock waiters.

---------------------------------------------------------------------------

Tom Lane wrote:
> "Sumaira Ali" <nat_lazy@hotmail.com> writes:
> > hi..i have questions about struct pgproc (in file proc.h) and proclock ( in 
> > file lock.h) of the postgresql source code, does anyone know the exact 
> > difference between pgproc and proclock structs??
> 
> There's one PGPROC per process.  There's one PROCLOCK for each process
> and each lock that that process has any interest in (ie, either
> currently holds or is waiting for).
> 
> The comments for these structs seem to be a bit of a mess at the moment :-(
> Bruce renamed the struct types recently, but appears not to have done a
> good job of adjusting the comments to match.  It may help to know that
> a proclock object was formerly called a "holder".
> 
> 			regards, tom lane
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
> 

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Index: src/backend/storage/lmgr/deadlock.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/storage/lmgr/deadlock.c,v
retrieving revision 1.16
diff -c -c -r1.16 deadlock.c
*** src/backend/storage/lmgr/deadlock.c	16 Jan 2003 21:01:44 -0000	1.16
--- src/backend/storage/lmgr/deadlock.c	18 Feb 2003 02:07:46 -0000
***************
*** 425,431 ****
  {
  	PGPROC	   *proc;
  	LOCK	   *lock;
! 	PROCLOCK   *holder;
  	SHM_QUEUE  *lockHolders;
  	LOCKMETHODTABLE *lockMethodTable;
  	PROC_QUEUE *waitQueue;
--- 425,431 ----
  {
  	PGPROC	   *proc;
  	LOCK	   *lock;
! 	PROCLOCK   *proclock;
  	SHM_QUEUE  *lockHolders;
  	LOCKMETHODTABLE *lockMethodTable;
  	PROC_QUEUE *waitQueue;
***************
*** 484,502 ****
  	 */
  	lockHolders = &(lock->lockHolders);
  
! 	holder = (PROCLOCK *) SHMQueueNext(lockHolders, lockHolders,
  									   offsetof(PROCLOCK, lockLink));
  
! 	while (holder)
  	{
! 		proc = (PGPROC *) MAKE_PTR(holder->tag.proc);
  
  		/* A proc never blocks itself */
  		if (proc != checkProc)
  		{
  			for (lm = 1; lm <= numLockModes; lm++)
  			{
! 				if (holder->holding[lm] > 0 &&
  					((1 << lm) & conflictMask) != 0)
  				{
  					/* This proc hard-blocks checkProc */
--- 484,502 ----
  	 */
  	lockHolders = &(lock->lockHolders);
  
! 	proclock = (PROCLOCK *) SHMQueueNext(lockHolders, lockHolders,
  									   offsetof(PROCLOCK, lockLink));
  
! 	while (proclock)
  	{
! 		proc = (PGPROC *) MAKE_PTR(proclock->tag.proc);
  
  		/* A proc never blocks itself */
  		if (proc != checkProc)
  		{
  			for (lm = 1; lm <= numLockModes; lm++)
  			{
! 				if (proclock->holding[lm] > 0 &&
  					((1 << lm) & conflictMask) != 0)
  				{
  					/* This proc hard-blocks checkProc */
***************
*** 512,524 ****
  
  						return true;
  					}
! 					/* If no deadlock, we're done looking at this holder */
  					break;
  				}
  			}
  		}
  
! 		holder = (PROCLOCK *) SHMQueueNext(lockHolders, &holder->lockLink,
  										   offsetof(PROCLOCK, lockLink));
  	}
  
--- 512,524 ----
  
  						return true;
  					}
! 					/* If no deadlock, we're done looking at this proclock */
  					break;
  				}
  			}
  		}
  
! 		proclock = (PROCLOCK *) SHMQueueNext(lockHolders, &proclock->lockLink,
  										   offsetof(PROCLOCK, lockLink));
  	}
  
Index: src/backend/storage/lmgr/lock.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.119
diff -c -c -r1.119 lock.c
*** src/backend/storage/lmgr/lock.c	16 Jan 2003 21:01:44 -0000	1.119
--- src/backend/storage/lmgr/lock.c	18 Feb 2003 02:07:48 -0000
***************
*** 47,53 ****
  
  
  static int WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
! 		   LOCK *lock, PROCLOCK *holder);
  static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
  				 int *myHolding);
  
--- 47,53 ----
  
  
  static int WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
! 		   LOCK *lock, PROCLOCK *proclock);
  static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
  				 int *myHolding);
  
***************
*** 124,151 ****
  
  
  inline static void
! PROCLOCK_PRINT(const char *where, const PROCLOCK *holderP)
  {
  	if (
! 	(((PROCLOCK_LOCKMETHOD(*holderP) == DEFAULT_LOCKMETHOD && Trace_locks)
! 	  || (PROCLOCK_LOCKMETHOD(*holderP) == USER_LOCKMETHOD && Trace_userlocks))
! 	 && (((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))
  		)
  		elog(LOG,
! 			 "%s: holder(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
! 			 where, MAKE_OFFSET(holderP), holderP->tag.lock,
! 			 PROCLOCK_LOCKMETHOD(*(holderP)),
! 			 holderP->tag.proc, holderP->tag.xid,
! 		   holderP->holding[1], holderP->holding[2], holderP->holding[3],
! 		   holderP->holding[4], holderP->holding[5], holderP->holding[6],
! 			 holderP->holding[7], holderP->nHolding);
  }
  
  #else							/* not LOCK_DEBUG */
  
  #define LOCK_PRINT(where, lock, type)
! #define PROCLOCK_PRINT(where, holderP)
  #endif   /* not LOCK_DEBUG */
  
  
--- 124,151 ----
  
  
  inline static void
! PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
  {
  	if (
! 	(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
! 	  || (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
! 	 && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
! 		|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
  		)
  		elog(LOG,
! 			 "%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
! 			 where, MAKE_OFFSET(proclockP), proclockP->tag.lock,
! 			 PROCLOCK_LOCKMETHOD(*(proclockP)),
! 			 proclockP->tag.proc, proclockP->tag.xid,
! 		   proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
! 		   proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
! 			 proclockP->holding[7], proclockP->nHolding);
  }
  
  #else							/* not LOCK_DEBUG */
  
  #define LOCK_PRINT(where, lock, type)
! #define PROCLOCK_PRINT(where, proclockP)
  #endif   /* not LOCK_DEBUG */
  
  
***************
*** 312,332 ****
  
  	/*
  	 * allocate a hash table for PROCLOCK structs.	This is used to store
! 	 * per-lock-holder information.
  	 */
  	info.keysize = sizeof(PROCLOCKTAG);
  	info.entrysize = sizeof(PROCLOCK);
  	info.hash = tag_hash;
  	hash_flags = (HASH_ELEM | HASH_FUNCTION);
  
! 	sprintf(shmemName, "%s (holder hash)", tabName);
! 	lockMethodTable->holderHash = ShmemInitHash(shmemName,
  												init_table_size,
  												max_table_size,
  												&info,
  												hash_flags);
  
! 	if (!lockMethodTable->holderHash)
  		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  
  	/* init data structures */
--- 312,332 ----
  
  	/*
  	 * allocate a hash table for PROCLOCK structs.	This is used to store
! 	 * per-lock-proclock information.
  	 */
  	info.keysize = sizeof(PROCLOCKTAG);
  	info.entrysize = sizeof(PROCLOCK);
  	info.hash = tag_hash;
  	hash_flags = (HASH_ELEM | HASH_FUNCTION);
  
! 	sprintf(shmemName, "%s (proclock hash)", tabName);
! 	lockMethodTable->proclockHash = ShmemInitHash(shmemName,
  												init_table_size,
  												max_table_size,
  												&info,
  												hash_flags);
  
! 	if (!lockMethodTable->proclockHash)
  		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  
  	/* init data structures */
***************
*** 421,427 ****
   *		tag.objId						block id		lock id2
   *										or xact id
   *		tag.offnum						0				lock id1
!  *		holder.xid						xid or 0		0
   *		persistence						transaction		user or backend
   *										or backend
   *
--- 421,427 ----
   *		tag.objId						block id		lock id2
   *										or xact id
   *		tag.offnum						0				lock id1
!  *		proclock.xid					xid or 0		0
   *		persistence						transaction		user or backend
   *										or backend
   *
***************
*** 435,443 ****
  LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
  			TransactionId xid, LOCKMODE lockmode, bool dontWait)
  {
! 	PROCLOCK   *holder;
! 	PROCLOCKTAG holdertag;
! 	HTAB	   *holderTable;
  	bool		found;
  	LOCK	   *lock;
  	LWLockId	masterLock;
--- 435,443 ----
  LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
  			TransactionId xid, LOCKMODE lockmode, bool dontWait)
  {
! 	PROCLOCK   *proclock;
! 	PROCLOCKTAG proclocktag;
! 	HTAB	   *proclockTable;
  	bool		found;
  	LOCK	   *lock;
  	LWLockId	masterLock;
***************
*** 506,530 ****
  	}
  
  	/*
! 	 * Create the hash key for the holder table.
  	 */
! 	MemSet(&holdertag, 0, sizeof(PROCLOCKTAG)); /* must clear padding,
  												 * needed */
! 	holdertag.lock = MAKE_OFFSET(lock);
! 	holdertag.proc = MAKE_OFFSET(MyProc);
! 	TransactionIdStore(xid, &holdertag.xid);
  
  	/*
! 	 * Find or create a holder entry with this tag
  	 */
! 	holderTable = lockMethodTable->holderHash;
! 	holder = (PROCLOCK *) hash_search(holderTable,
! 									  (void *) &holdertag,
  									  HASH_ENTER, &found);
! 	if (!holder)
  	{
  		LWLockRelease(masterLock);
! 		elog(ERROR, "LockAcquire: holder table out of memory");
  		return FALSE;
  	}
  
--- 506,530 ----
  	}
  
  	/*
! 	 * Create the hash key for the proclock table.
  	 */
! 	MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG)); /* must clear padding,
  												 * needed */
! 	proclocktag.lock = MAKE_OFFSET(lock);
! 	proclocktag.proc = MAKE_OFFSET(MyProc);
! 	TransactionIdStore(xid, &proclocktag.xid);
  
  	/*
! 	 * Find or create a proclock entry with this tag
  	 */
! 	proclockTable = lockMethodTable->proclockHash;
! 	proclock = (PROCLOCK *) hash_search(proclockTable,
! 									  (void *) &proclocktag,
  									  HASH_ENTER, &found);
! 	if (!proclock)
  	{
  		LWLockRelease(masterLock);
! 		elog(ERROR, "LockAcquire: proclock table out of memory");
  		return FALSE;
  	}
  
***************
*** 533,550 ****
  	 */
  	if (!found)
  	{
! 		holder->nHolding = 0;
! 		MemSet((char *) holder->holding, 0, sizeof(int) * MAX_LOCKMODES);
! 		/* Add holder to appropriate lists */
! 		SHMQueueInsertBefore(&lock->lockHolders, &holder->lockLink);
! 		SHMQueueInsertBefore(&MyProc->procHolders, &holder->procLink);
! 		PROCLOCK_PRINT("LockAcquire: new", holder);
  	}
  	else
  	{
! 		PROCLOCK_PRINT("LockAcquire: found", holder);
! 		Assert((holder->nHolding >= 0) && (holder->holding[lockmode] >= 0));
! 		Assert(holder->nHolding <= lock->nGranted);
  
  #ifdef CHECK_DEADLOCK_RISK
  
--- 533,550 ----
  	 */
  	if (!found)
  	{
! 		proclock->nHolding = 0;
! 		MemSet((char *) proclock->holding, 0, sizeof(int) * MAX_LOCKMODES);
! 		/* Add proclock to appropriate lists */
! 		SHMQueueInsertBefore(&lock->lockHolders, &proclock->lockLink);
! 		SHMQueueInsertBefore(&MyProc->procHolders, &proclock->procLink);
! 		PROCLOCK_PRINT("LockAcquire: new", proclock);
  	}
  	else
  	{
! 		PROCLOCK_PRINT("LockAcquire: found", proclock);
! 		Assert((proclock->nHolding >= 0) && (proclock->holding[lockmode] >= 0));
! 		Assert(proclock->nHolding <= lock->nGranted);
  
  #ifdef CHECK_DEADLOCK_RISK
  
***************
*** 565,571 ****
  		 */
  		for (i = lockMethodTable->numLockModes; i > 0; i--)
  		{
! 			if (holder->holding[i] > 0)
  			{
  				if (i >= (int) lockmode)
  					break;		/* safe: we have a lock >= req level */
--- 565,571 ----
  		 */
  		for (i = lockMethodTable->numLockModes; i > 0; i--)
  		{
! 			if (proclock->holding[i] > 0)
  			{
  				if (i >= (int) lockmode)
  					break;		/* safe: we have a lock >= req level */
***************
*** 592,614 ****
  	 * If I already hold one or more locks of the requested type, just
  	 * grant myself another one without blocking.
  	 */
! 	if (holder->holding[lockmode] > 0)
  	{
! 		GrantLock(lock, holder, lockmode);
! 		PROCLOCK_PRINT("LockAcquire: owning", holder);
  		LWLockRelease(masterLock);
  		return TRUE;
  	}
  
  	/*
! 	 * If this process (under any XID) is a holder of the lock, also grant
  	 * myself another one without blocking.
  	 */
! 	LockCountMyLocks(holder->tag.lock, MyProc, myHolding);
  	if (myHolding[lockmode] > 0)
  	{
! 		GrantLock(lock, holder, lockmode);
! 		PROCLOCK_PRINT("LockAcquire: my other XID owning", holder);
  		LWLockRelease(masterLock);
  		return TRUE;
  	}
--- 592,614 ----
  	 * If I already hold one or more locks of the requested type, just
  	 * grant myself another one without blocking.
  	 */
! 	if (proclock->holding[lockmode] > 0)
  	{
! 		GrantLock(lock, proclock, lockmode);
! 		PROCLOCK_PRINT("LockAcquire: owning", proclock);
  		LWLockRelease(masterLock);
  		return TRUE;
  	}
  
  	/*
! 	 * If this process (under any XID) is a proclock of the lock, also grant
  	 * myself another one without blocking.
  	 */
! 	LockCountMyLocks(proclock->tag.lock, MyProc, myHolding);
  	if (myHolding[lockmode] > 0)
  	{
! 		GrantLock(lock, proclock, lockmode);
! 		PROCLOCK_PRINT("LockAcquire: my other XID owning", proclock);
  		LWLockRelease(masterLock);
  		return TRUE;
  	}
***************
*** 622,634 ****
  		status = STATUS_FOUND;
  	else
  		status = LockCheckConflicts(lockMethodTable, lockmode,
! 									lock, holder,
  									MyProc, myHolding);
  
  	if (status == STATUS_OK)
  	{
  		/* No conflict with held or previously requested locks */
! 		GrantLock(lock, holder, lockmode);
  	}
  	else
  	{
--- 622,634 ----
  		status = STATUS_FOUND;
  	else
  		status = LockCheckConflicts(lockMethodTable, lockmode,
! 									lock, proclock,
  									MyProc, myHolding);
  
  	if (status == STATUS_OK)
  	{
  		/* No conflict with held or previously requested locks */
! 		GrantLock(lock, proclock, lockmode);
  	}
  	else
  	{
***************
*** 636,658 ****
  
  		/*
  		 * We can't acquire the lock immediately.  If caller specified no
! 		 * blocking, remove the holder entry and return FALSE without
  		 * waiting.
  		 */
  		if (dontWait)
  		{
! 			if (holder->nHolding == 0)
  			{
! 				SHMQueueDelete(&holder->lockLink);
! 				SHMQueueDelete(&holder->procLink);
! 				holder = (PROCLOCK *) hash_search(holderTable,
! 												  (void *) holder,
  												  HASH_REMOVE, NULL);
! 				if (!holder)
! 					elog(WARNING, "LockAcquire: remove holder, table corrupted");
  			}
  			else
! 				PROCLOCK_PRINT("LockAcquire: NHOLDING", holder);
  			lock->nRequested--;
  			lock->requested[lockmode]--;
  			LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
--- 636,658 ----
  
  		/*
  		 * We can't acquire the lock immediately.  If caller specified no
! 		 * blocking, remove the proclock entry and return FALSE without
  		 * waiting.
  		 */
  		if (dontWait)
  		{
! 			if (proclock->nHolding == 0)
  			{
! 				SHMQueueDelete(&proclock->lockLink);
! 				SHMQueueDelete(&proclock->procLink);
! 				proclock = (PROCLOCK *) hash_search(proclockTable,
! 												  (void *) proclock,
  												  HASH_REMOVE, NULL);
! 				if (!proclock)
! 					elog(WARNING, "LockAcquire: remove proclock, table corrupted");
  			}
  			else
! 				PROCLOCK_PRINT("LockAcquire: NHOLDING", proclock);
  			lock->nRequested--;
  			lock->requested[lockmode]--;
  			LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
***************
*** 682,688 ****
  		/*
  		 * Sleep till someone wakes me up.
  		 */
! 		status = WaitOnLock(lockmethod, lockmode, lock, holder);
  
  		/*
  		 * NOTE: do not do any material change of state between here and
--- 682,688 ----
  		/*
  		 * Sleep till someone wakes me up.
  		 */
! 		status = WaitOnLock(lockmethod, lockmode, lock, proclock);
  
  		/*
  		 * NOTE: do not do any material change of state between here and
***************
*** 692,709 ****
  		 */
  
  		/*
! 		 * Check the holder entry status, in case something in the ipc
  		 * communication doesn't work correctly.
  		 */
! 		if (!((holder->nHolding > 0) && (holder->holding[lockmode] > 0)))
  		{
! 			PROCLOCK_PRINT("LockAcquire: INCONSISTENT", holder);
  			LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
  			/* Should we retry ? */
  			LWLockRelease(masterLock);
  			return FALSE;
  		}
! 		PROCLOCK_PRINT("LockAcquire: granted", holder);
  		LOCK_PRINT("LockAcquire: granted", lock, lockmode);
  	}
  
--- 692,709 ----
  		 */
  
  		/*
! 		 * Check the proclock entry status, in case something in the ipc
  		 * communication doesn't work correctly.
  		 */
! 		if (!((proclock->nHolding > 0) && (proclock->holding[lockmode] > 0)))
  		{
! 			PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
  			LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
  			/* Should we retry ? */
  			LWLockRelease(masterLock);
  			return FALSE;
  		}
! 		PROCLOCK_PRINT("LockAcquire: granted", proclock);
  		LOCK_PRINT("LockAcquire: granted", lock, lockmode);
  	}
  
***************
*** 732,738 ****
  LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
  				   LOCKMODE lockmode,
  				   LOCK *lock,
! 				   PROCLOCK *holder,
  				   PGPROC *proc,
  				   int *myHolding)		/* myHolding[] array or NULL */
  {
--- 732,738 ----
  LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
  				   LOCKMODE lockmode,
  				   LOCK *lock,
! 				   PROCLOCK *proclock,
  				   PGPROC *proc,
  				   int *myHolding)		/* myHolding[] array or NULL */
  {
***************
*** 753,759 ****
  	 */
  	if (!(lockMethodTable->conflictTab[lockmode] & lock->grantMask))
  	{
! 		PROCLOCK_PRINT("LockCheckConflicts: no conflict", holder);
  		return STATUS_OK;
  	}
  
--- 753,759 ----
  	 */
  	if (!(lockMethodTable->conflictTab[lockmode] & lock->grantMask))
  	{
! 		PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
  		return STATUS_OK;
  	}
  
***************
*** 766,772 ****
  	if (myHolding == NULL)
  	{
  		/* Caller didn't do calculation of total holding for me */
! 		LockCountMyLocks(holder->tag.lock, proc, localHolding);
  		myHolding = localHolding;
  	}
  
--- 766,772 ----
  	if (myHolding == NULL)
  	{
  		/* Caller didn't do calculation of total holding for me */
! 		LockCountMyLocks(proclock->tag.lock, proc, localHolding);
  		myHolding = localHolding;
  	}
  
***************
*** 787,797 ****
  	if (!(lockMethodTable->conflictTab[lockmode] & bitmask))
  	{
  		/* no conflict. OK to get the lock */
! 		PROCLOCK_PRINT("LockCheckConflicts: resolved", holder);
  		return STATUS_OK;
  	}
  
! 	PROCLOCK_PRINT("LockCheckConflicts: conflicting", holder);
  	return STATUS_FOUND;
  }
  
--- 787,797 ----
  	if (!(lockMethodTable->conflictTab[lockmode] & bitmask))
  	{
  		/* no conflict. OK to get the lock */
! 		PROCLOCK_PRINT("LockCheckConflicts: resolved", proclock);
  		return STATUS_OK;
  	}
  
! 	PROCLOCK_PRINT("LockCheckConflicts: conflicting", proclock);
  	return STATUS_FOUND;
  }
  
***************
*** 809,844 ****
  LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc, int *myHolding)
  {
  	SHM_QUEUE  *procHolders = &(proc->procHolders);
! 	PROCLOCK   *holder;
  	int			i;
  
  	MemSet(myHolding, 0, MAX_LOCKMODES * sizeof(int));
  
! 	holder = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (holder)
  	{
! 		if (lockOffset == holder->tag.lock)
  		{
  			for (i = 1; i < MAX_LOCKMODES; i++)
! 				myHolding[i] += holder->holding[i];
  		}
  
! 		holder = (PROCLOCK *) SHMQueueNext(procHolders, &holder->procLink,
  										   offsetof(PROCLOCK, procLink));
  	}
  }
  
  /*
!  * GrantLock -- update the lock and holder data structures to show
   *		the lock request has been granted.
   *
   * NOTE: if proc was blocked, it also needs to be removed from the wait list
   * and have its waitLock/waitHolder fields cleared.  That's not done here.
   */
  void
! GrantLock(LOCK *lock, PROCLOCK *holder, LOCKMODE lockmode)
  {
  	lock->nGranted++;
  	lock->granted[lockmode]++;
--- 809,844 ----
  LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc, int *myHolding)
  {
  	SHM_QUEUE  *procHolders = &(proc->procHolders);
! 	PROCLOCK   *proclock;
  	int			i;
  
  	MemSet(myHolding, 0, MAX_LOCKMODES * sizeof(int));
  
! 	proclock = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (proclock)
  	{
! 		if (lockOffset == proclock->tag.lock)
  		{
  			for (i = 1; i < MAX_LOCKMODES; i++)
! 				myHolding[i] += proclock->holding[i];
  		}
  
! 		proclock = (PROCLOCK *) SHMQueueNext(procHolders, &proclock->procLink,
  										   offsetof(PROCLOCK, procLink));
  	}
  }
  
  /*
!  * GrantLock -- update the lock and proclock data structures to show
   *		the lock request has been granted.
   *
   * NOTE: if proc was blocked, it also needs to be removed from the wait list
   * and have its waitLock/waitHolder fields cleared.  That's not done here.
   */
  void
! GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
  {
  	lock->nGranted++;
  	lock->granted[lockmode]++;
***************
*** 848,856 ****
  	LOCK_PRINT("GrantLock", lock, lockmode);
  	Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
  	Assert(lock->nGranted <= lock->nRequested);
! 	holder->holding[lockmode]++;
! 	holder->nHolding++;
! 	Assert((holder->nHolding > 0) && (holder->holding[lockmode] > 0));
  }
  
  /*
--- 848,856 ----
  	LOCK_PRINT("GrantLock", lock, lockmode);
  	Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
  	Assert(lock->nGranted <= lock->nRequested);
! 	proclock->holding[lockmode]++;
! 	proclock->nHolding++;
! 	Assert((proclock->nHolding > 0) && (proclock->holding[lockmode] > 0));
  }
  
  /*
***************
*** 863,869 ****
   */
  static int
  WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
! 		   LOCK *lock, PROCLOCK *holder)
  {
  	LOCKMETHODTABLE *lockMethodTable = LockMethodTable[lockmethod];
  	char	   *new_status,
--- 863,869 ----
   */
  static int
  WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
! 		   LOCK *lock, PROCLOCK *proclock)
  {
  	LOCKMETHODTABLE *lockMethodTable = LockMethodTable[lockmethod];
  	char	   *new_status,
***************
*** 896,906 ****
  	if (ProcSleep(lockMethodTable,
  				  lockmode,
  				  lock,
! 				  holder) != STATUS_OK)
  	{
  		/*
  		 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
! 		 * now.  Removal of the holder and lock objects, if no longer
  		 * needed, will happen in xact cleanup (see above for motivation).
  		 */
  		LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
--- 896,906 ----
  	if (ProcSleep(lockMethodTable,
  				  lockmode,
  				  lock,
! 				  proclock) != STATUS_OK)
  	{
  		/*
  		 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
! 		 * now.  Removal of the proclock and lock objects, if no longer
  		 * needed, will happen in xact cleanup (see above for motivation).
  		 */
  		LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
***************
*** 930,936 ****
   *
   * Locktable lock must be held by caller.
   *
!  * NB: this does not remove the process' holder object, nor the lock object,
   * even though their counts might now have gone to zero.  That will happen
   * during a subsequent LockReleaseAll call, which we expect will happen
   * during transaction cleanup.	(Removal of a proc from its wait queue by
--- 930,936 ----
   *
   * Locktable lock must be held by caller.
   *
!  * NB: this does not remove the process' proclock object, nor the lock object,
   * even though their counts might now have gone to zero.  That will happen
   * during a subsequent LockReleaseAll call, which we expect will happen
   * during transaction cleanup.	(Removal of a proc from its wait queue by
***************
*** 986,994 ****
  	LOCK	   *lock;
  	LWLockId	masterLock;
  	LOCKMETHODTABLE *lockMethodTable;
! 	PROCLOCK   *holder;
! 	PROCLOCKTAG holdertag;
! 	HTAB	   *holderTable;
  	bool		wakeupNeeded = false;
  
  #ifdef LOCK_DEBUG
--- 986,994 ----
  	LOCK	   *lock;
  	LWLockId	masterLock;
  	LOCKMETHODTABLE *lockMethodTable;
! 	PROCLOCK   *proclock;
! 	PROCLOCKTAG proclocktag;
! 	HTAB	   *proclockTable;
  	bool		wakeupNeeded = false;
  
  #ifdef LOCK_DEBUG
***************
*** 1031,1049 ****
  	LOCK_PRINT("LockRelease: found", lock, lockmode);
  
  	/*
! 	 * Find the holder entry for this holder.
  	 */
! 	MemSet(&holdertag, 0, sizeof(PROCLOCKTAG)); /* must clear padding,
  												 * needed */
! 	holdertag.lock = MAKE_OFFSET(lock);
! 	holdertag.proc = MAKE_OFFSET(MyProc);
! 	TransactionIdStore(xid, &holdertag.xid);
! 
! 	holderTable = lockMethodTable->holderHash;
! 	holder = (PROCLOCK *) hash_search(holderTable,
! 									  (void *) &holdertag,
  									  HASH_FIND_SAVE, NULL);
! 	if (!holder)
  	{
  		LWLockRelease(masterLock);
  #ifdef USER_LOCKS
--- 1031,1049 ----
  	LOCK_PRINT("LockRelease: found", lock, lockmode);
  
  	/*
! 	 * Find the proclock entry for this proclock.
  	 */
! 	MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG)); /* must clear padding,
  												 * needed */
! 	proclocktag.lock = MAKE_OFFSET(lock);
! 	proclocktag.proc = MAKE_OFFSET(MyProc);
! 	TransactionIdStore(xid, &proclocktag.xid);
! 
! 	proclockTable = lockMethodTable->proclockHash;
! 	proclock = (PROCLOCK *) hash_search(proclockTable,
! 									  (void *) &proclocktag,
  									  HASH_FIND_SAVE, NULL);
! 	if (!proclock)
  	{
  		LWLockRelease(masterLock);
  #ifdef USER_LOCKS
***************
*** 1051,1075 ****
  			elog(WARNING, "LockRelease: no lock with this tag");
  		else
  #endif
! 			elog(WARNING, "LockRelease: holder table corrupted");
  		return FALSE;
  	}
! 	PROCLOCK_PRINT("LockRelease: found", holder);
  
  	/*
  	 * Check that we are actually holding a lock of the type we want to
  	 * release.
  	 */
! 	if (!(holder->holding[lockmode] > 0))
  	{
! 		PROCLOCK_PRINT("LockRelease: WRONGTYPE", holder);
! 		Assert(holder->holding[lockmode] >= 0);
  		LWLockRelease(masterLock);
  		elog(WARNING, "LockRelease: you don't own a lock of type %s",
  			 lock_mode_names[lockmode]);
  		return FALSE;
  	}
! 	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);
--- 1051,1075 ----
  			elog(WARNING, "LockRelease: no lock with this tag");
  		else
  #endif
! 			elog(WARNING, "LockRelease: proclock table corrupted");
  		return FALSE;
  	}
! 	PROCLOCK_PRINT("LockRelease: found", proclock);
  
  	/*
  	 * Check that we are actually holding a lock of the type we want to
  	 * release.
  	 */
! 	if (!(proclock->holding[lockmode] > 0))
  	{
! 		PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
! 		Assert(proclock->holding[lockmode] >= 0);
  		LWLockRelease(masterLock);
  		elog(WARNING, "LockRelease: you don't own a lock of type %s",
  			 lock_mode_names[lockmode]);
  		return FALSE;
  	}
! 	Assert(proclock->nHolding > 0);
  	Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
  	Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
  	Assert(lock->nGranted <= lock->nRequested);
***************
*** 1126,1154 ****
  	}
  
  	/*
! 	 * Now fix the per-holder lock stats.
  	 */
! 	holder->holding[lockmode]--;
! 	holder->nHolding--;
! 	PROCLOCK_PRINT("LockRelease: updated", holder);
! 	Assert((holder->nHolding >= 0) && (holder->holding[lockmode] >= 0));
  
  	/*
  	 * If this was my last hold on this lock, delete my entry in the
! 	 * holder table.
  	 */
! 	if (holder->nHolding == 0)
  	{
! 		PROCLOCK_PRINT("LockRelease: deleting", holder);
! 		SHMQueueDelete(&holder->lockLink);
! 		SHMQueueDelete(&holder->procLink);
! 		holder = (PROCLOCK *) hash_search(holderTable,
! 										  (void *) &holder,
  										  HASH_REMOVE_SAVED, NULL);
! 		if (!holder)
  		{
  			LWLockRelease(masterLock);
! 			elog(WARNING, "LockRelease: remove holder, table corrupted");
  			return FALSE;
  		}
  	}
--- 1126,1154 ----
  	}
  
  	/*
! 	 * Now fix the per-proclock lock stats.
  	 */
! 	proclock->holding[lockmode]--;
! 	proclock->nHolding--;
! 	PROCLOCK_PRINT("LockRelease: updated", proclock);
! 	Assert((proclock->nHolding >= 0) && (proclock->holding[lockmode] >= 0));
  
  	/*
  	 * If this was my last hold on this lock, delete my entry in the
! 	 * proclock table.
  	 */
! 	if (proclock->nHolding == 0)
  	{
! 		PROCLOCK_PRINT("LockRelease: deleting", proclock);
! 		SHMQueueDelete(&proclock->lockLink);
! 		SHMQueueDelete(&proclock->procLink);
! 		proclock = (PROCLOCK *) hash_search(proclockTable,
! 										  (void *) &proclock,
  										  HASH_REMOVE_SAVED, NULL);
! 		if (!proclock)
  		{
  			LWLockRelease(masterLock);
! 			elog(WARNING, "LockRelease: remove proclock, table corrupted");
  			return FALSE;
  		}
  	}
***************
*** 1179,1185 ****
  			   bool allxids, TransactionId xid)
  {
  	SHM_QUEUE  *procHolders = &(proc->procHolders);
! 	PROCLOCK   *holder;
  	PROCLOCK   *nextHolder;
  	LWLockId	masterLock;
  	LOCKMETHODTABLE *lockMethodTable;
--- 1179,1185 ----
  			   bool allxids, TransactionId xid)
  {
  	SHM_QUEUE  *procHolders = &(proc->procHolders);
! 	PROCLOCK   *proclock;
  	PROCLOCK   *nextHolder;
  	LWLockId	masterLock;
  	LOCKMETHODTABLE *lockMethodTable;
***************
*** 1206,1254 ****
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
! 	holder = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (holder)
  	{
  		bool		wakeupNeeded = false;
  
! 		/* Get link first, since we may unlink/delete this holder */
! 		nextHolder = (PROCLOCK *) SHMQueueNext(procHolders, &holder->procLink,
  										   offsetof(PROCLOCK, procLink));
  
! 		Assert(holder->tag.proc == MAKE_OFFSET(proc));
  
! 		lock = (LOCK *) MAKE_PTR(holder->tag.lock);
  
  		/* Ignore items that are not of the lockmethod to be removed */
  		if (LOCK_LOCKMETHOD(*lock) != lockmethod)
  			goto next_item;
  
  		/* If not allxids, ignore items that are of the wrong xid */
! 		if (!allxids && !TransactionIdEquals(xid, holder->tag.xid))
  			goto next_item;
  
! 		PROCLOCK_PRINT("LockReleaseAll", holder);
  		LOCK_PRINT("LockReleaseAll", lock, 0);
  		Assert(lock->nRequested >= 0);
  		Assert(lock->nGranted >= 0);
  		Assert(lock->nGranted <= lock->nRequested);
! 		Assert(holder->nHolding >= 0);
! 		Assert(holder->nHolding <= lock->nRequested);
  
  		/*
  		 * fix the general lock stats
  		 */
! 		if (lock->nRequested != holder->nHolding)
  		{
  			for (i = 1; i <= numLockModes; i++)
  			{
! 				Assert(holder->holding[i] >= 0);
! 				if (holder->holding[i] > 0)
  				{
! 					lock->requested[i] -= holder->holding[i];
! 					lock->granted[i] -= holder->holding[i];
  					Assert(lock->requested[i] >= 0 && lock->granted[i] >= 0);
  					if (lock->granted[i] == 0)
  						lock->grantMask &= BITS_OFF[i];
--- 1206,1254 ----
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
! 	proclock = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (proclock)
  	{
  		bool		wakeupNeeded = false;
  
! 		/* Get link first, since we may unlink/delete this proclock */
! 		nextHolder = (PROCLOCK *) SHMQueueNext(procHolders, &proclock->procLink,
  										   offsetof(PROCLOCK, procLink));
  
! 		Assert(proclock->tag.proc == MAKE_OFFSET(proc));
  
! 		lock = (LOCK *) MAKE_PTR(proclock->tag.lock);
  
  		/* Ignore items that are not of the lockmethod to be removed */
  		if (LOCK_LOCKMETHOD(*lock) != lockmethod)
  			goto next_item;
  
  		/* If not allxids, ignore items that are of the wrong xid */
! 		if (!allxids && !TransactionIdEquals(xid, proclock->tag.xid))
  			goto next_item;
  
! 		PROCLOCK_PRINT("LockReleaseAll", proclock);
  		LOCK_PRINT("LockReleaseAll", lock, 0);
  		Assert(lock->nRequested >= 0);
  		Assert(lock->nGranted >= 0);
  		Assert(lock->nGranted <= lock->nRequested);
! 		Assert(proclock->nHolding >= 0);
! 		Assert(proclock->nHolding <= lock->nRequested);
  
  		/*
  		 * fix the general lock stats
  		 */
! 		if (lock->nRequested != proclock->nHolding)
  		{
  			for (i = 1; i <= numLockModes; i++)
  			{
! 				Assert(proclock->holding[i] >= 0);
! 				if (proclock->holding[i] > 0)
  				{
! 					lock->requested[i] -= proclock->holding[i];
! 					lock->granted[i] -= proclock->holding[i];
  					Assert(lock->requested[i] >= 0 && lock->granted[i] >= 0);
  					if (lock->granted[i] == 0)
  						lock->grantMask &= BITS_OFF[i];
***************
*** 1261,1275 ****
  						wakeupNeeded = true;
  				}
  			}
! 			lock->nRequested -= holder->nHolding;
! 			lock->nGranted -= holder->nHolding;
  			Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
  			Assert(lock->nGranted <= lock->nRequested);
  		}
  		else
  		{
  			/*
! 			 * This holder accounts for all the requested locks on the
  			 * object, so we can be lazy and just zero things out.
  			 */
  			lock->nRequested = 0;
--- 1261,1275 ----
  						wakeupNeeded = true;
  				}
  			}
! 			lock->nRequested -= proclock->nHolding;
! 			lock->nGranted -= proclock->nHolding;
  			Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
  			Assert(lock->nGranted <= lock->nRequested);
  		}
  		else
  		{
  			/*
! 			 * This proclock accounts for all the requested locks on the
  			 * object, so we can be lazy and just zero things out.
  			 */
  			lock->nRequested = 0;
***************
*** 1283,1307 ****
  		}
  		LOCK_PRINT("LockReleaseAll: updated", lock, 0);
  
! 		PROCLOCK_PRINT("LockReleaseAll: deleting", holder);
  
  		/*
! 		 * Remove the holder entry from the linked lists
  		 */
! 		SHMQueueDelete(&holder->lockLink);
! 		SHMQueueDelete(&holder->procLink);
  
  		/*
! 		 * remove the holder entry from the hashtable
  		 */
! 		holder = (PROCLOCK *) hash_search(lockMethodTable->holderHash,
! 										  (void *) holder,
  										  HASH_REMOVE,
  										  NULL);
! 		if (!holder)
  		{
  			LWLockRelease(masterLock);
! 			elog(WARNING, "LockReleaseAll: holder table corrupted");
  			return FALSE;
  		}
  
--- 1283,1307 ----
  		}
  		LOCK_PRINT("LockReleaseAll: updated", lock, 0);
  
! 		PROCLOCK_PRINT("LockReleaseAll: deleting", proclock);
  
  		/*
! 		 * Remove the proclock entry from the linked lists
  		 */
! 		SHMQueueDelete(&proclock->lockLink);
! 		SHMQueueDelete(&proclock->procLink);
  
  		/*
! 		 * remove the proclock entry from the hashtable
  		 */
! 		proclock = (PROCLOCK *) hash_search(lockMethodTable->proclockHash,
! 										  (void *) proclock,
  										  HASH_REMOVE,
  										  NULL);
! 		if (!proclock)
  		{
  			LWLockRelease(masterLock);
! 			elog(WARNING, "LockReleaseAll: proclock table corrupted");
  			return FALSE;
  		}
  
***************
*** 1327,1333 ****
  			ProcLockWakeup(lockMethodTable, lock);
  
  next_item:
! 		holder = nextHolder;
  	}
  
  	LWLockRelease(masterLock);
--- 1327,1333 ----
  			ProcLockWakeup(lockMethodTable, lock);
  
  next_item:
! 		proclock = nextHolder;
  	}
  
  	LWLockRelease(masterLock);
***************
*** 1353,1359 ****
  	/* lockHash table */
  	size += hash_estimate_size(max_table_size, sizeof(LOCK));
  
! 	/* holderHash table */
  	size += hash_estimate_size(max_table_size, sizeof(PROCLOCK));
  
  	/*
--- 1353,1359 ----
  	/* lockHash table */
  	size += hash_estimate_size(max_table_size, sizeof(LOCK));
  
! 	/* proclockHash table */
  	size += hash_estimate_size(max_table_size, sizeof(PROCLOCK));
  
  	/*
***************
*** 1383,1390 ****
  GetLockStatusData(void)
  {
  	LockData   *data;
! 	HTAB	   *holderTable;
! 	PROCLOCK   *holder;
  	HASH_SEQ_STATUS seqstat;
  	int			i;
  
--- 1383,1390 ----
  GetLockStatusData(void)
  {
  	LockData   *data;
! 	HTAB	   *proclockTable;
! 	PROCLOCK   *proclock;
  	HASH_SEQ_STATUS seqstat;
  	int			i;
  
***************
*** 1392,1419 ****
  
  	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
  
! 	holderTable = LockMethodTable[DEFAULT_LOCKMETHOD]->holderHash;
  
! 	data->nelements = i = holderTable->hctl->nentries;
  
  	if (i == 0)
  		i = 1;					/* avoid palloc(0) if empty table */
  
! 	data->holderaddrs = (SHMEM_OFFSET *) palloc(sizeof(SHMEM_OFFSET) * i);
! 	data->holders = (PROCLOCK *) palloc(sizeof(PROCLOCK) * i);
  	data->procs = (PGPROC *) palloc(sizeof(PGPROC) * i);
  	data->locks = (LOCK *) palloc(sizeof(LOCK) * i);
  
! 	hash_seq_init(&seqstat, holderTable);
  
  	i = 0;
! 	while ((holder = hash_seq_search(&seqstat)))
  	{
! 		PGPROC	   *proc = (PGPROC *) MAKE_PTR(holder->tag.proc);
! 		LOCK	   *lock = (LOCK *) MAKE_PTR(holder->tag.lock);
  
! 		data->holderaddrs[i] = MAKE_OFFSET(holder);
! 		memcpy(&(data->holders[i]), holder, sizeof(PROCLOCK));
  		memcpy(&(data->procs[i]), proc, sizeof(PGPROC));
  		memcpy(&(data->locks[i]), lock, sizeof(LOCK));
  
--- 1392,1419 ----
  
  	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
  
! 	proclockTable = LockMethodTable[DEFAULT_LOCKMETHOD]->proclockHash;
  
! 	data->nelements = i = proclockTable->hctl->nentries;
  
  	if (i == 0)
  		i = 1;					/* avoid palloc(0) if empty table */
  
! 	data->proclockaddrs = (SHMEM_OFFSET *) palloc(sizeof(SHMEM_OFFSET) * i);
! 	data->proclocks = (PROCLOCK *) palloc(sizeof(PROCLOCK) * i);
  	data->procs = (PGPROC *) palloc(sizeof(PGPROC) * i);
  	data->locks = (LOCK *) palloc(sizeof(LOCK) * i);
  
! 	hash_seq_init(&seqstat, proclockTable);
  
  	i = 0;
! 	while ((proclock = hash_seq_search(&seqstat)))
  	{
! 		PGPROC	   *proc = (PGPROC *) MAKE_PTR(proclock->tag.proc);
! 		LOCK	   *lock = (LOCK *) MAKE_PTR(proclock->tag.lock);
  
! 		data->proclockaddrs[i] = MAKE_OFFSET(proclock);
! 		memcpy(&(data->proclocks[i]), proclock, sizeof(PROCLOCK));
  		memcpy(&(data->procs[i]), proc, sizeof(PGPROC));
  		memcpy(&(data->locks[i]), lock, sizeof(LOCK));
  
***************
*** 1446,1452 ****
  {
  	PGPROC	   *proc;
  	SHM_QUEUE  *procHolders;
! 	PROCLOCK   *holder;
  	LOCK	   *lock;
  	int			lockmethod = DEFAULT_LOCKMETHOD;
  	LOCKMETHODTABLE *lockMethodTable;
--- 1446,1452 ----
  {
  	PGPROC	   *proc;
  	SHM_QUEUE  *procHolders;
! 	PROCLOCK   *proclock;
  	LOCK	   *lock;
  	int			lockmethod = DEFAULT_LOCKMETHOD;
  	LOCKMETHODTABLE *lockMethodTable;
***************
*** 1465,1483 ****
  	if (proc->waitLock)
  		LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);
  
! 	holder = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (holder)
  	{
! 		Assert(holder->tag.proc == MAKE_OFFSET(proc));
  
! 		lock = (LOCK *) MAKE_PTR(holder->tag.lock);
  
! 		PROCLOCK_PRINT("DumpLocks", holder);
  		LOCK_PRINT("DumpLocks", lock, 0);
  
! 		holder = (PROCLOCK *) SHMQueueNext(procHolders, &holder->procLink,
  										   offsetof(PROCLOCK, procLink));
  	}
  }
--- 1465,1483 ----
  	if (proc->waitLock)
  		LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);
  
! 	proclock = (PROCLOCK *) SHMQueueNext(procHolders, procHolders,
  									   offsetof(PROCLOCK, procLink));
  
! 	while (proclock)
  	{
! 		Assert(proclock->tag.proc == MAKE_OFFSET(proc));
  
! 		lock = (LOCK *) MAKE_PTR(proclock->tag.lock);
  
! 		PROCLOCK_PRINT("DumpLocks", proclock);
  		LOCK_PRINT("DumpLocks", lock, 0);
  
! 		proclock = (PROCLOCK *) SHMQueueNext(procHolders, &proclock->procLink,
  										   offsetof(PROCLOCK, procLink));
  	}
  }
***************
*** 1489,1499 ****
  DumpAllLocks(void)
  {
  	PGPROC	   *proc;
! 	PROCLOCK   *holder;
  	LOCK	   *lock;
  	int			lockmethod = DEFAULT_LOCKMETHOD;
  	LOCKMETHODTABLE *lockMethodTable;
! 	HTAB	   *holderTable;
  	HASH_SEQ_STATUS status;
  
  	proc = MyProc;
--- 1489,1499 ----
  DumpAllLocks(void)
  {
  	PGPROC	   *proc;
! 	PROCLOCK   *proclock;
  	LOCK	   *lock;
  	int			lockmethod = DEFAULT_LOCKMETHOD;
  	LOCKMETHODTABLE *lockMethodTable;
! 	HTAB	   *proclockTable;
  	HASH_SEQ_STATUS status;
  
  	proc = MyProc;
***************
*** 1505,1527 ****
  	if (!lockMethodTable)
  		return;
  
! 	holderTable = lockMethodTable->holderHash;
  
  	if (proc->waitLock)
  		LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);
  
! 	hash_seq_init(&status, holderTable);
! 	while ((holder = (PROCLOCK *) hash_seq_search(&status)) != NULL)
  	{
! 		PROCLOCK_PRINT("DumpAllLocks", holder);
  
! 		if (holder->tag.lock)
  		{
! 			lock = (LOCK *) MAKE_PTR(holder->tag.lock);
  			LOCK_PRINT("DumpAllLocks", lock, 0);
  		}
  		else
! 			elog(LOG, "DumpAllLocks: holder->tag.lock = NULL");
  	}
  }
  
--- 1505,1527 ----
  	if (!lockMethodTable)
  		return;
  
! 	proclockTable = lockMethodTable->proclockHash;
  
  	if (proc->waitLock)
  		LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);
  
! 	hash_seq_init(&status, proclockTable);
! 	while ((proclock = (PROCLOCK *) hash_seq_search(&status)) != NULL)
  	{
! 		PROCLOCK_PRINT("DumpAllLocks", proclock);
  
! 		if (proclock->tag.lock)
  		{
! 			lock = (LOCK *) MAKE_PTR(proclock->tag.lock);
  			LOCK_PRINT("DumpAllLocks", lock, 0);
  		}
  		else
! 			elog(LOG, "DumpAllLocks: proclock->tag.lock = NULL");
  	}
  }
  
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.128
diff -c -c -r1.128 proc.c
*** src/backend/storage/lmgr/proc.c	16 Jan 2003 21:01:44 -0000	1.128
--- src/backend/storage/lmgr/proc.c	18 Feb 2003 02:07:49 -0000
***************
*** 521,527 ****
  ProcSleep(LOCKMETHODTABLE *lockMethodTable,
  		  LOCKMODE lockmode,
  		  LOCK *lock,
! 		  PROCLOCK *holder)
  {
  	LWLockId	masterLock = lockMethodTable->masterLock;
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
--- 521,527 ----
  ProcSleep(LOCKMETHODTABLE *lockMethodTable,
  		  LOCKMODE lockmode,
  		  LOCK *lock,
! 		  PROCLOCK *proclock)
  {
  	LWLockId	masterLock = lockMethodTable->masterLock;
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
***************
*** 577,588 ****
  					LockCheckConflicts(lockMethodTable,
  									   lockmode,
  									   lock,
! 									   holder,
  									   MyProc,
  									   NULL) == STATUS_OK)
  				{
  					/* Skip the wait and just grant myself the lock. */
! 					GrantLock(lock, holder, lockmode);
  					return STATUS_OK;
  				}
  				/* Break out of loop to put myself before him */
--- 577,588 ----
  					LockCheckConflicts(lockMethodTable,
  									   lockmode,
  									   lock,
! 									   proclock,
  									   MyProc,
  									   NULL) == STATUS_OK)
  				{
  					/* Skip the wait and just grant myself the lock. */
! 					GrantLock(lock, proclock, lockmode);
  					return STATUS_OK;
  				}
  				/* Break out of loop to put myself before him */
***************
*** 615,621 ****
  
  	/* Set up wait information in PGPROC object, too */
  	MyProc->waitLock = lock;
! 	MyProc->waitHolder = holder;
  	MyProc->waitLockMode = lockmode;
  
  	MyProc->errType = STATUS_OK;	/* initialize result for success */
--- 615,621 ----
  
  	/* Set up wait information in PGPROC object, too */
  	MyProc->waitLock = lock;
! 	MyProc->waitHolder = proclock;
  	MyProc->waitLockMode = lockmode;
  
  	MyProc->errType = STATUS_OK;	/* initialize result for success */
Index: src/backend/utils/adt/lockfuncs.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/lockfuncs.c,v
retrieving revision 1.7
diff -c -c -r1.7 lockfuncs.c
*** src/backend/utils/adt/lockfuncs.c	4 Sep 2002 20:31:28 -0000	1.7
--- src/backend/utils/adt/lockfuncs.c	18 Feb 2003 02:07:49 -0000
***************
*** 88,94 ****
  
  	while (mystatus->currIdx < lockData->nelements)
  	{
! 		PROCLOCK   *holder;
  		LOCK	   *lock;
  		PGPROC	   *proc;
  		bool		granted;
--- 88,94 ----
  
  	while (mystatus->currIdx < lockData->nelements)
  	{
! 		PROCLOCK   *proclock;
  		LOCK	   *lock;
  		PGPROC	   *proc;
  		bool		granted;
***************
*** 98,104 ****
  		HeapTuple	tuple;
  		Datum		result;
  
! 		holder = &(lockData->holders[mystatus->currIdx]);
  		lock = &(lockData->locks[mystatus->currIdx]);
  		proc = &(lockData->procs[mystatus->currIdx]);
  
--- 98,104 ----
  		HeapTuple	tuple;
  		Datum		result;
  
! 		proclock = &(lockData->proclocks[mystatus->currIdx]);
  		lock = &(lockData->locks[mystatus->currIdx]);
  		proc = &(lockData->procs[mystatus->currIdx]);
  
***************
*** 110,119 ****
  		granted = false;
  		for (mode = 0; mode < MAX_LOCKMODES; mode++)
  		{
! 			if (holder->holding[mode] > 0)
  			{
  				granted = true;
! 				holder->holding[mode] = 0;
  				break;
  			}
  		}
--- 110,119 ----
  		granted = false;
  		for (mode = 0; mode < MAX_LOCKMODES; mode++)
  		{
! 			if (proclock->holding[mode] > 0)
  			{
  				granted = true;
! 				proclock->holding[mode] = 0;
  				break;
  			}
  		}
***************
*** 124,130 ****
  		 */
  		if (!granted)
  		{
! 			if (proc->waitLock == (LOCK *) MAKE_PTR(holder->tag.lock))
  			{
  				/* Yes, so report it with proper mode */
  				mode = proc->waitLockMode;
--- 124,130 ----
  		 */
  		if (!granted)
  		{
! 			if (proc->waitLock == (LOCK *) MAKE_PTR(proclock->tag.lock))
  			{
  				/* Yes, so report it with proper mode */
  				mode = proc->waitLockMode;
Index: src/include/storage/lock.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/storage/lock.h,v
retrieving revision 1.68
diff -c -c -r1.68 lock.h
*** src/include/storage/lock.h	16 Jan 2003 21:01:45 -0000	1.68
--- src/include/storage/lock.h	18 Feb 2003 02:07:50 -0000
***************
*** 68,74 ****
   *
   * lockHash -- hash table holding per-locked-object lock information
   *
!  * holderHash -- hash table holding per-lock-holder lock information
   *
   * lockmethod -- the handle used by the lock table's clients to
   *		refer to the type of lock table being used.
--- 68,74 ----
   *
   * lockHash -- hash table holding per-locked-object lock information
   *
!  * proclockHash -- hash table holding per-lock-waiter/holder lock information
   *
   * lockmethod -- the handle used by the lock table's clients to
   *		refer to the type of lock table being used.
***************
*** 86,92 ****
  typedef struct LOCKMETHODTABLE
  {
  	HTAB	   *lockHash;
! 	HTAB	   *holderHash;
  	LOCKMETHOD	lockmethod;
  	int			numLockModes;
  	int			conflictTab[MAX_LOCKMODES];
--- 86,92 ----
  typedef struct LOCKMETHODTABLE
  {
  	HTAB	   *lockHash;
! 	HTAB	   *proclockHash;
  	LOCKMETHOD	lockmethod;
  	int			numLockModes;
  	int			conflictTab[MAX_LOCKMODES];
***************
*** 156,179 ****
  
  /*
   * We may have several different transactions holding or awaiting locks
!  * on the same lockable object.  We need to store some per-holder information
!  * for each such holder (or would-be holder).
   *
   * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the
!  * holder hashtable.  A PROCLOCKTAG value uniquely identifies a lock holder.
   *
!  * There are two possible kinds of holder tags: a transaction (identified
   * both by the PGPROC of the backend running it, and the xact's own ID) and
   * a session (identified by backend PGPROC, with xid = InvalidTransactionId).
   *
!  * Currently, session holders are used for user locks and for cross-xact
   * locks obtained for VACUUM.  We assume that a session lock never conflicts
   * 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.
   *
   * Each PROCLOCK object is linked into lists for both the associated LOCK object
--- 156,180 ----
  
  /*
   * We may have several different transactions holding or awaiting locks
!  * on the same lockable object.  We need to store some per-waiter/holder
!  * information for each such holder (or would-be holder).
   *
   * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the
!  * proclock hashtable.  A PROCLOCKTAG value uniquely identifies a lock
!  * holder/waiter.
   *
!  * There are two possible kinds of proclock tags: a transaction (identified
   * both by the PGPROC of the backend running it, and the xact's own ID) and
   * a session (identified by backend PGPROC, with xid = InvalidTransactionId).
   *
!  * Currently, session proclocks are used for user locks and for cross-xact
   * locks obtained for VACUUM.  We assume that a session lock never conflicts
   * with per-transaction locks obtained by the same backend.
   *
   * The holding[] array counts the granted locks (of each type) represented
!  * by this proclock. Note that there will be a proclock object, possibly with
   * zero holding[], for any lock that the process is currently waiting on.
!  * Otherwise, proclock objects whose counts have gone to zero are recycled
   * as soon as convenient.
   *
   * Each PROCLOCK object is linked into lists for both the associated LOCK object
***************
*** 192,208 ****
  typedef struct PROCLOCK
  {
  	/* tag */
! 	PROCLOCKTAG tag;			/* unique identifier of holder object */
  
  	/* data */
  	int			holding[MAX_LOCKMODES]; /* count of locks currently held */
  	int			nHolding;		/* total of holding[] array */
! 	SHM_QUEUE	lockLink;		/* list link for lock's list of holders */
! 	SHM_QUEUE	procLink;		/* list link for process's list of holders */
  } PROCLOCK;
  
! #define PROCLOCK_LOCKMETHOD(holder) \
! 		(((LOCK *) MAKE_PTR((holder).tag.lock))->tag.lockmethod)
  
  /*
   * This struct holds information passed from lmgr internals to the lock
--- 193,209 ----
  typedef struct PROCLOCK
  {
  	/* tag */
! 	PROCLOCKTAG tag;			/* unique identifier of proclock object */
  
  	/* data */
  	int			holding[MAX_LOCKMODES]; /* count of locks currently held */
  	int			nHolding;		/* total of holding[] array */
! 	SHM_QUEUE	lockLink;		/* list link for lock's list of proclocks */
! 	SHM_QUEUE	procLink;		/* list link for process's list of proclocks */
  } PROCLOCK;
  
! #define PROCLOCK_LOCKMETHOD(proclock) \
! 		(((LOCK *) MAKE_PTR((proclock).tag.lock))->tag.lockmethod)
  
  /*
   * This struct holds information passed from lmgr internals to the lock
***************
*** 215,222 ****
  typedef struct
  {
  	int			nelements;		/* The length of each of the arrays */
! 	SHMEM_OFFSET *holderaddrs;
! 	PROCLOCK   *holders;
  	PGPROC	   *procs;
  	LOCK	   *locks;
  } LockData;
--- 216,223 ----
  typedef struct
  {
  	int			nelements;		/* The length of each of the arrays */
! 	SHMEM_OFFSET *proclockaddrs;
! 	PROCLOCK   *proclocks;
  	PGPROC	   *procs;
  	LOCK	   *locks;
  } LockData;
***************
*** 237,245 ****
  			   bool allxids, TransactionId xid);
  extern int LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
  				   LOCKMODE lockmode,
! 				   LOCK *lock, PROCLOCK *holder, PGPROC *proc,
  				   int *myHolding);
! extern void GrantLock(LOCK *lock, PROCLOCK *holder, LOCKMODE lockmode);
  extern void RemoveFromWaitQueue(PGPROC *proc);
  extern int	LockShmemSize(int maxBackends);
  extern bool DeadLockCheck(PGPROC *proc);
--- 238,246 ----
  			   bool allxids, TransactionId xid);
  extern int LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
  				   LOCKMODE lockmode,
! 				   LOCK *lock, PROCLOCK *proclock, PGPROC *proc,
  				   int *myHolding);
! extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
  extern void RemoveFromWaitQueue(PGPROC *proc);
  extern int	LockShmemSize(int maxBackends);
  extern bool DeadLockCheck(PGPROC *proc);
Index: src/include/storage/proc.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/storage/proc.h,v
retrieving revision 1.62
diff -c -c -r1.62 proc.h
*** src/include/storage/proc.h	31 Oct 2002 21:34:17 -0000	1.62
--- src/include/storage/proc.h	18 Feb 2003 02:07:51 -0000
***************
*** 102,108 ****
  
  extern void ProcQueueInit(PROC_QUEUE *queue);
  extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode,
! 		  LOCK *lock, PROCLOCK *holder);
  extern PGPROC *ProcWakeup(PGPROC *proc, int errType);
  extern void ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock);
  extern bool LockWaitCancel(void);
--- 102,108 ----
  
  extern void ProcQueueInit(PROC_QUEUE *queue);
  extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode,
! 		  LOCK *lock, PROCLOCK *proclock);
  extern PGPROC *ProcWakeup(PGPROC *proc, int errType);
  extern void ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock);
  extern bool LockWaitCancel(void);
Mon, 17 Feb 2003 21:14:18 -0500 (EST)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: [HACKERS] lock.h and proc.h