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
  [EMAIL PROTECTED]               |  (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;
  
  

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to