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