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);