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