I have completed this TODO item with the following patch, patch applied:

  * Merge LockMethodCtl and LockMethodTable into one shared structure


-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Index: src/backend/storage/lmgr/deadlock.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v
retrieving revision 1.10
diff -c -r1.10 deadlock.c
*** src/backend/storage/lmgr/deadlock.c	20 Jun 2002 20:29:35 -0000	1.10
--- src/backend/storage/lmgr/deadlock.c	18 Jul 2002 22:13:13 -0000
***************
*** 170,179 ****
   * only look at regular locks.
   *
   * We must have already locked the master lock before being called.
-  * NOTE: although the lockctl structure appears to allow each lock
-  * table to have a different LWLock, all locks that can block had
-  * better use the same LWLock, else this code will not be adequately
-  * interlocked!
   */
  bool
  DeadLockCheck(PGPROC *proc)
--- 170,175 ----
***************
*** 384,390 ****
  	HOLDER	   *holder;
  	SHM_QUEUE  *lockHolders;
  	LOCKMETHODTABLE *lockMethodTable;
- 	LOCKMETHODCTL *lockctl;
  	PROC_QUEUE *waitQueue;
  	int			queue_size;
  	int			conflictMask;
--- 380,385 ----
***************
*** 423,431 ****
  	if (lock == NULL)
  		return false;
  	lockMethodTable = GetLocksMethodTable(lock);
! 	lockctl = lockMethodTable->ctl;
! 	numLockModes = lockctl->numLockModes;
! 	conflictMask = lockctl->conflictTab[checkProc->waitLockMode];
  
  	/*
  	 * Scan for procs that already hold conflicting locks.	These are
--- 418,425 ----
  	if (lock == NULL)
  		return false;
  	lockMethodTable = GetLocksMethodTable(lock);
! 	numLockModes = lockMethodTable->numLockModes;
! 	conflictMask = lockMethodTable->conflictTab[checkProc->waitLockMode];
  
  	/*
  	 * Scan for procs that already hold conflicting locks.	These are
Index: src/backend/storage/lmgr/lock.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.108
diff -c -r1.108 lock.c
*** src/backend/storage/lmgr/lock.c	20 Jun 2002 20:29:35 -0000	1.108
--- src/backend/storage/lmgr/lock.c	18 Jul 2002 22:13:19 -0000
***************
*** 213,224 ****
  {
  	int			i;
  
! 	lockMethodTable->ctl->numLockModes = numModes;
  	numModes++;
  	for (i = 0; i < numModes; i++, prioP++, conflictsP++)
  	{
! 		lockMethodTable->ctl->conflictTab[i] = *conflictsP;
! 		lockMethodTable->ctl->prio[i] = *prioP;
  	}
  }
  
--- 213,224 ----
  {
  	int			i;
  
! 	lockMethodTable->numLockModes = numModes;
  	numModes++;
  	for (i = 0; i < numModes; i++, prioP++, conflictsP++)
  	{
! 		lockMethodTable->conflictTab[i] = *conflictsP;
! 		lockMethodTable->prio[i] = *prioP;
  	}
  }
  
***************
*** 263,269 ****
  
  	/* each lock table has a non-shared, permanent header */
  	lockMethodTable = (LOCKMETHODTABLE *)
! 		MemoryContextAlloc(TopMemoryContext, sizeof(LOCKMETHODTABLE));
  
  	/*
  	 * Lock the LWLock for the table (probably not necessary here)
--- 263,272 ----
  
  	/* each lock table has a non-shared, permanent header */
  	lockMethodTable = (LOCKMETHODTABLE *)
! 		ShmemInitStruct(shmemName, sizeof(LOCKMETHODTABLE), &found);
! 
! 	if (!lockMethodTable)
! 		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  
  	/*
  	 * Lock the LWLock for the table (probably not necessary here)
***************
*** 271,287 ****
  	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
  
  	/*
- 	 * allocate a control structure from shared memory or attach to it if
- 	 * it already exists.
- 	 */
- 	sprintf(shmemName, "%s (ctl)", tabName);
- 	lockMethodTable->ctl = (LOCKMETHODCTL *)
- 		ShmemInitStruct(shmemName, sizeof(LOCKMETHODCTL), &found);
- 
- 	if (!lockMethodTable->ctl)
- 		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
- 
- 	/*
  	 * no zero-th table
  	 */
  	NumLockMethods = 1;
--- 274,279 ----
***************
*** 291,299 ****
  	 */
  	if (!found)
  	{
! 		MemSet(lockMethodTable->ctl, 0, sizeof(LOCKMETHODCTL));
! 		lockMethodTable->ctl->masterLock = LockMgrLock;
! 		lockMethodTable->ctl->lockmethod = NumLockMethods;
  	}
  
  	/*
--- 283,291 ----
  	 */
  	if (!found)
  	{
! 		MemSet(lockMethodTable, 0, sizeof(LOCKMETHODTABLE));
! 		lockMethodTable->masterLock = LockMgrLock;
! 		lockMethodTable->lockmethod = NumLockMethods;
  	}
  
  	/*
***************
*** 342,355 ****
  	if (!lockMethodTable->holderHash)
  		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  
! 	/* init ctl data structures */
  	LockMethodInit(lockMethodTable, conflictsP, prioP, numModes);
  
  	LWLockRelease(LockMgrLock);
  
  	pfree(shmemName);
  
! 	return lockMethodTable->ctl->lockmethod;
  }
  
  /*
--- 334,347 ----
  	if (!lockMethodTable->holderHash)
  		elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
  
! 	/* init data structures */
  	LockMethodInit(lockMethodTable, conflictsP, prioP, numModes);
  
  	LWLockRelease(LockMgrLock);
  
  	pfree(shmemName);
  
! 	return lockMethodTable->lockmethod;
  }
  
  /*
***************
*** 476,482 ****
  		return FALSE;
  	}
  
! 	masterLock = lockMethodTable->ctl->masterLock;
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
--- 468,474 ----
  		return FALSE;
  	}
  
! 	masterLock = lockMethodTable->masterLock;
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
***************
*** 576,582 ****
  		 * XXX Doing numeric comparison on the lockmodes is a hack; it'd be
  		 * better to use a table.  For now, though, this works.
  		 */
! 		for (i = lockMethodTable->ctl->numLockModes; i > 0; i--)
  		{
  			if (holder->holding[i] > 0)
  			{
--- 568,574 ----
  		 * XXX Doing numeric comparison on the lockmodes is a hack; it'd be
  		 * better to use a table.  For now, though, this works.
  		 */
! 		for (i = lockMethodTable->numLockModes; i > 0; i--)
  		{
  			if (holder->holding[i] > 0)
  			{
***************
*** 631,637 ****
  	 * join wait queue.  Otherwise, check for conflict with already-held
  	 * locks.  (That's last because most complex check.)
  	 */
! 	if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask)
  		status = STATUS_FOUND;
  	else
  		status = LockCheckConflicts(lockMethodTable, lockmode,
--- 623,629 ----
  	 * join wait queue.  Otherwise, check for conflict with already-held
  	 * locks.  (That's last because most complex check.)
  	 */
! 	if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
  		status = STATUS_FOUND;
  	else
  		status = LockCheckConflicts(lockMethodTable, lockmode,
***************
*** 683,689 ****
  			int			tmpMask;
  
  			for (i = 1, tmpMask = 2;
! 				 i <= lockMethodTable->ctl->numLockModes;
  				 i++, tmpMask <<= 1)
  			{
  				if (myHolding[i] > 0)
--- 675,681 ----
  			int			tmpMask;
  
  			for (i = 1, tmpMask = 2;
! 				 i <= lockMethodTable->numLockModes;
  				 i++, tmpMask <<= 1)
  			{
  				if (myHolding[i] > 0)
***************
*** 749,756 ****
  				   PGPROC *proc,
  				   int *myHolding)		/* myHolding[] array or NULL */
  {
! 	LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
! 	int			numLockModes = lockctl->numLockModes;
  	int			bitmask;
  	int			i,
  				tmpMask;
--- 741,747 ----
  				   PGPROC *proc,
  				   int *myHolding)		/* myHolding[] array or NULL */
  {
! 	int			numLockModes = lockMethodTable->numLockModes;
  	int			bitmask;
  	int			i,
  				tmpMask;
***************
*** 765,771 ****
  	 * each type of lock that conflicts with request.	Bitwise compare
  	 * tells if there is a conflict.
  	 */
! 	if (!(lockctl->conflictTab[lockmode] & lock->grantMask))
  	{
  		HOLDER_PRINT("LockCheckConflicts: no conflict", holder);
  		return STATUS_OK;
--- 756,762 ----
  	 * each type of lock that conflicts with request.	Bitwise compare
  	 * tells if there is a conflict.
  	 */
! 	if (!(lockMethodTable->conflictTab[lockmode] & lock->grantMask))
  	{
  		HOLDER_PRINT("LockCheckConflicts: no conflict", holder);
  		return STATUS_OK;
***************
*** 798,804 ****
  	 * locks held by other processes.  If one of these conflicts with the
  	 * kind of lock that I want, there is a conflict and I have to sleep.
  	 */
! 	if (!(lockctl->conflictTab[lockmode] & bitmask))
  	{
  		/* no conflict. OK to get the lock */
  		HOLDER_PRINT("LockCheckConflicts: resolved", holder);
--- 789,795 ----
  	 * locks held by other processes.  If one of these conflicts with the
  	 * kind of lock that I want, there is a conflict and I have to sleep.
  	 */
! 	if (!(lockMethodTable->conflictTab[lockmode] & bitmask))
  	{
  		/* no conflict. OK to get the lock */
  		HOLDER_PRINT("LockCheckConflicts: resolved", holder);
***************
*** 918,924 ****
  		 * needed, will happen in xact cleanup (see above for motivation).
  		 */
  		LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
! 		LWLockRelease(lockMethodTable->ctl->masterLock);
  		elog(ERROR, "deadlock detected");
  		/* not reached */
  	}
--- 909,915 ----
  		 * needed, will happen in xact cleanup (see above for motivation).
  		 */
  		LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
! 		LWLockRelease(lockMethodTable->masterLock);
  		elog(ERROR, "deadlock detected");
  		/* not reached */
  	}
***************
*** 1014,1020 ****
  		return FALSE;
  	}
  
! 	masterLock = lockMethodTable->ctl->masterLock;
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
  	/*
--- 1005,1011 ----
  		return FALSE;
  	}
  
! 	masterLock = lockMethodTable->masterLock;
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
  	/*
***************
*** 1109,1115 ****
  	 * granted locks might belong to some waiter, who could now be
  	 * awakened because he doesn't conflict with his own locks.
  	 */
! 	if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask)
  		wakeupNeeded = true;
  
  	if (lock->nRequested == 0)
--- 1100,1106 ----
  	 * granted locks might belong to some waiter, who could now be
  	 * awakened because he doesn't conflict with his own locks.
  	 */
! 	if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
  		wakeupNeeded = true;
  
  	if (lock->nRequested == 0)
***************
*** 1208,1215 ****
  		return FALSE;
  	}
  
! 	numLockModes = lockMethodTable->ctl->numLockModes;
! 	masterLock = lockMethodTable->ctl->masterLock;
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
--- 1199,1206 ----
  		return FALSE;
  	}
  
! 	numLockModes = lockMethodTable->numLockModes;
! 	masterLock = lockMethodTable->masterLock;
  
  	LWLockAcquire(masterLock, LW_EXCLUSIVE);
  
***************
*** 1264,1270 ****
  					 * Read comments in LockRelease
  					 */
  					if (!wakeupNeeded &&
! 					lockMethodTable->ctl->conflictTab[i] & lock->waitMask)
  						wakeupNeeded = true;
  				}
  			}
--- 1255,1261 ----
  					 * Read comments in LockRelease
  					 */
  					if (!wakeupNeeded &&
! 					lockMethodTable->conflictTab[i] & lock->waitMask)
  						wakeupNeeded = true;
  				}
  			}
***************
*** 1355,1362 ****
  
  	size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
  	size += maxBackends * MAXALIGN(sizeof(PGPROC));		/* each MyProc */
! 	size += MAX_LOCK_METHODS * MAXALIGN(sizeof(LOCKMETHODCTL)); /* each
! 																 * lockMethodTable->ctl */
  
  	/* lockHash table */
  	size += hash_estimate_size(max_table_size, sizeof(LOCK));
--- 1346,1353 ----
  
  	size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
  	size += maxBackends * MAXALIGN(sizeof(PGPROC));		/* each MyProc */
! 	size += MAX_LOCK_METHODS * MAXALIGN(sizeof(LOCKMETHODTABLE)); /* each
! 																 * lockMethodTable */
  
  	/* lockHash table */
  	size += hash_estimate_size(max_table_size, sizeof(LOCK));
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.122
diff -c -r1.122 proc.c
*** src/backend/storage/lmgr/proc.c	13 Jul 2002 01:02:14 -0000	1.122
--- src/backend/storage/lmgr/proc.c	18 Jul 2002 22:13:20 -0000
***************
*** 503,510 ****
  		  LOCK *lock,
  		  HOLDER *holder)
  {
! 	LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
! 	LWLockId	masterLock = lockctl->masterLock;
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
  	int			myHeldLocks = MyProc->heldLocks;
  	bool		early_deadlock = false;
--- 503,509 ----
  		  LOCK *lock,
  		  HOLDER *holder)
  {
! 	LWLockId	masterLock = lockMethodTable->masterLock;
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
  	int			myHeldLocks = MyProc->heldLocks;
  	bool		early_deadlock = false;
***************
*** 537,546 ****
  		for (i = 0; i < waitQueue->size; i++)
  		{
  			/* Must he wait for me? */
! 			if (lockctl->conflictTab[proc->waitLockMode] & myHeldLocks)
  			{
  				/* Must I wait for him ? */
! 				if (lockctl->conflictTab[lockmode] & proc->heldLocks)
  				{
  					/*
  					 * Yes, so we have a deadlock.	Easiest way to clean
--- 536,545 ----
  		for (i = 0; i < waitQueue->size; i++)
  		{
  			/* Must he wait for me? */
! 			if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
  			{
  				/* Must I wait for him ? */
! 				if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
  				{
  					/*
  					 * Yes, so we have a deadlock.	Easiest way to clean
***************
*** 553,559 ****
  					break;
  				}
  				/* I must go before this waiter.  Check special case. */
! 				if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
  					LockCheckConflicts(lockMethodTable,
  									   lockmode,
  									   lock,
--- 552,558 ----
  					break;
  				}
  				/* I must go before this waiter.  Check special case. */
! 				if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
  					LockCheckConflicts(lockMethodTable,
  									   lockmode,
  									   lock,
***************
*** 725,731 ****
  void
  ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
  {
- 	LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
  	int			queue_size = waitQueue->size;
  	PGPROC	   *proc;
--- 724,729 ----
***************
*** 746,752 ****
  		 * Waken if (a) doesn't conflict with requests of earlier waiters,
  		 * and (b) doesn't conflict with already-held locks.
  		 */
! 		if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
  			LockCheckConflicts(lockMethodTable,
  							   lockmode,
  							   lock,
--- 744,750 ----
  		 * Waken if (a) doesn't conflict with requests of earlier waiters,
  		 * and (b) doesn't conflict with already-held locks.
  		 */
! 		if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
  			LockCheckConflicts(lockMethodTable,
  							   lockmode,
  							   lock,
Index: src/include/storage/lock.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/storage/lock.h,v
retrieving revision 1.61
diff -c -r1.61 lock.h
*** src/include/storage/lock.h	20 Jun 2002 20:29:52 -0000	1.61
--- src/include/storage/lock.h	18 Jul 2002 22:13:22 -0000
***************
*** 62,78 ****
   * There is normally only one lock method, the default one.
   * If user locks are enabled, an additional lock method is present.
   *
-  * LOCKMETHODCTL and LOCKMETHODTABLE are split because the first lives
-  * in shared memory.  (There isn't any really good reason for the split.)
-  * LOCKMETHODTABLE exists in private memory.  Both are created by the
-  * postmaster and should be the same in all backends.
-  */
- 
- /*
   * This is the control structure for a lock table.	It
   * lives in shared memory.	This information is the same
   * for all backends.
   *
   * lockmethod -- the handle used by the lock table's clients to
   *		refer to the type of lock table being used.
   *
--- 62,75 ----
   * There is normally only one lock method, the default one.
   * If user locks are enabled, an additional lock method is present.
   *
   * This is the control structure for a lock table.	It
   * lives in shared memory.	This information is the same
   * for all backends.
   *
+  * 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.
   *
***************
*** 88,115 ****
   *		starvation).  XXX this field is not actually used at present!
   *
   * masterLock -- synchronizes access to the table
   */
! typedef struct LOCKMETHODCTL
  {
  	LOCKMETHOD	lockmethod;
  	int			numLockModes;
  	int			conflictTab[MAX_LOCKMODES];
  	int			prio[MAX_LOCKMODES];
  	LWLockId	masterLock;
- } LOCKMETHODCTL;
- 
- /*
-  * Eack backend has a non-shared lock table header.
-  *
-  * lockHash -- hash table holding per-locked-object lock information
-  * holderHash -- hash table holding per-lock-holder lock information
-  * ctl - shared control structure described above.
-  */
- typedef struct LOCKMETHODTABLE
- {
- 	HTAB	   *lockHash;
- 	HTAB	   *holderHash;
- 	LOCKMETHODCTL *ctl;
  } LOCKMETHODTABLE;
  
  
--- 85,101 ----
   *		starvation).  XXX this field is not actually used at present!
   *
   * masterLock -- synchronizes access to the table
+  *
   */
! typedef struct LOCKMETHODTABLE
  {
+ 	HTAB	   *lockHash;
+ 	HTAB	   *holderHash;
  	LOCKMETHOD	lockmethod;
  	int			numLockModes;
  	int			conflictTab[MAX_LOCKMODES];
  	int			prio[MAX_LOCKMODES];
  	LWLockId	masterLock;
  } LOCKMETHODTABLE;
Thu, 18 Jul 2002 19:07:00 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
lock item completed