Re: [HACKERS] lock.h and proc.h

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: [HACKERS] lock.h and proc.h
Дата
Msg-id 200302180214.h1I2EIn04089@candle.pha.pa.us
обсуждение исходный текст
Список pgsql-patches
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);

В списке pgsql-patches по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: Patch to extend range of timestamps
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: createuser - allow user cancel or kill to work