Commit 981d045e authored by Bruce Momjian's avatar Bruce Momjian

Complete TODO item:

* Merge LockMethodCtl and LockMethodTable into one shared structure (Bruce)
parent 85d2a629
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.10 2002/06/20 20:29:35 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.11 2002/07/18 23:06:19 momjian Exp $
* *
* Interface: * Interface:
* *
...@@ -170,10 +170,6 @@ InitDeadLockChecking(void) ...@@ -170,10 +170,6 @@ InitDeadLockChecking(void)
* only look at regular locks. * only look at regular locks.
* *
* We must have already locked the master lock before being called. * 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 bool
DeadLockCheck(PGPROC *proc) DeadLockCheck(PGPROC *proc)
...@@ -384,7 +380,6 @@ FindLockCycleRecurse(PGPROC *checkProc, ...@@ -384,7 +380,6 @@ FindLockCycleRecurse(PGPROC *checkProc,
HOLDER *holder; HOLDER *holder;
SHM_QUEUE *lockHolders; SHM_QUEUE *lockHolders;
LOCKMETHODTABLE *lockMethodTable; LOCKMETHODTABLE *lockMethodTable;
LOCKMETHODCTL *lockctl;
PROC_QUEUE *waitQueue; PROC_QUEUE *waitQueue;
int queue_size; int queue_size;
int conflictMask; int conflictMask;
...@@ -423,9 +418,8 @@ FindLockCycleRecurse(PGPROC *checkProc, ...@@ -423,9 +418,8 @@ FindLockCycleRecurse(PGPROC *checkProc,
if (lock == NULL) if (lock == NULL)
return false; return false;
lockMethodTable = GetLocksMethodTable(lock); lockMethodTable = GetLocksMethodTable(lock);
lockctl = lockMethodTable->ctl; numLockModes = lockMethodTable->numLockModes;
numLockModes = lockctl->numLockModes; conflictMask = lockMethodTable->conflictTab[checkProc->waitLockMode];
conflictMask = lockctl->conflictTab[checkProc->waitLockMode];
/* /*
* Scan for procs that already hold conflicting locks. These are * Scan for procs that already hold conflicting locks. These are
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.108 2002/06/20 20:29:35 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.109 2002/07/18 23:06:19 momjian Exp $
* *
* NOTES * NOTES
* Outside modules can create a lock table and acquire/release * Outside modules can create a lock table and acquire/release
...@@ -213,12 +213,12 @@ LockMethodInit(LOCKMETHODTABLE *lockMethodTable, ...@@ -213,12 +213,12 @@ LockMethodInit(LOCKMETHODTABLE *lockMethodTable,
{ {
int i; int i;
lockMethodTable->ctl->numLockModes = numModes; lockMethodTable->numLockModes = numModes;
numModes++; numModes++;
for (i = 0; i < numModes; i++, prioP++, conflictsP++) for (i = 0; i < numModes; i++, prioP++, conflictsP++)
{ {
lockMethodTable->ctl->conflictTab[i] = *conflictsP; lockMethodTable->conflictTab[i] = *conflictsP;
lockMethodTable->ctl->prio[i] = *prioP; lockMethodTable->prio[i] = *prioP;
} }
} }
...@@ -263,24 +263,16 @@ LockMethodTableInit(char *tabName, ...@@ -263,24 +263,16 @@ LockMethodTableInit(char *tabName,
/* each lock table has a non-shared, permanent header */ /* each lock table has a non-shared, permanent header */
lockMethodTable = (LOCKMETHODTABLE *) lockMethodTable = (LOCKMETHODTABLE *)
MemoryContextAlloc(TopMemoryContext, sizeof(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) * Lock the LWLock for the table (probably not necessary here)
*/ */
LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); 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 * no zero-th table
*/ */
...@@ -291,9 +283,9 @@ LockMethodTableInit(char *tabName, ...@@ -291,9 +283,9 @@ LockMethodTableInit(char *tabName,
*/ */
if (!found) if (!found)
{ {
MemSet(lockMethodTable->ctl, 0, sizeof(LOCKMETHODCTL)); MemSet(lockMethodTable, 0, sizeof(LOCKMETHODTABLE));
lockMethodTable->ctl->masterLock = LockMgrLock; lockMethodTable->masterLock = LockMgrLock;
lockMethodTable->ctl->lockmethod = NumLockMethods; lockMethodTable->lockmethod = NumLockMethods;
} }
/* /*
...@@ -342,14 +334,14 @@ LockMethodTableInit(char *tabName, ...@@ -342,14 +334,14 @@ LockMethodTableInit(char *tabName,
if (!lockMethodTable->holderHash) if (!lockMethodTable->holderHash)
elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName); elog(FATAL, "LockMethodTableInit: couldn't initialize %s", tabName);
/* init ctl data structures */ /* init data structures */
LockMethodInit(lockMethodTable, conflictsP, prioP, numModes); LockMethodInit(lockMethodTable, conflictsP, prioP, numModes);
LWLockRelease(LockMgrLock); LWLockRelease(LockMgrLock);
pfree(shmemName); pfree(shmemName);
return lockMethodTable->ctl->lockmethod; return lockMethodTable->lockmethod;
} }
/* /*
...@@ -476,7 +468,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -476,7 +468,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
return FALSE; return FALSE;
} }
masterLock = lockMethodTable->ctl->masterLock; masterLock = lockMethodTable->masterLock;
LWLockAcquire(masterLock, LW_EXCLUSIVE); LWLockAcquire(masterLock, LW_EXCLUSIVE);
...@@ -576,7 +568,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -576,7 +568,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* XXX Doing numeric comparison on the lockmodes is a hack; it'd be * XXX Doing numeric comparison on the lockmodes is a hack; it'd be
* better to use a table. For now, though, this works. * better to use a table. For now, though, this works.
*/ */
for (i = lockMethodTable->ctl->numLockModes; i > 0; i--) for (i = lockMethodTable->numLockModes; i > 0; i--)
{ {
if (holder->holding[i] > 0) if (holder->holding[i] > 0)
{ {
...@@ -631,7 +623,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -631,7 +623,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* join wait queue. Otherwise, check for conflict with already-held * join wait queue. Otherwise, check for conflict with already-held
* locks. (That's last because most complex check.) * locks. (That's last because most complex check.)
*/ */
if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask) if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
status = STATUS_FOUND; status = STATUS_FOUND;
else else
status = LockCheckConflicts(lockMethodTable, lockmode, status = LockCheckConflicts(lockMethodTable, lockmode,
...@@ -683,7 +675,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -683,7 +675,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
int tmpMask; int tmpMask;
for (i = 1, tmpMask = 2; for (i = 1, tmpMask = 2;
i <= lockMethodTable->ctl->numLockModes; i <= lockMethodTable->numLockModes;
i++, tmpMask <<= 1) i++, tmpMask <<= 1)
{ {
if (myHolding[i] > 0) if (myHolding[i] > 0)
...@@ -749,8 +741,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable, ...@@ -749,8 +741,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
PGPROC *proc, PGPROC *proc,
int *myHolding) /* myHolding[] array or NULL */ int *myHolding) /* myHolding[] array or NULL */
{ {
LOCKMETHODCTL *lockctl = lockMethodTable->ctl; int numLockModes = lockMethodTable->numLockModes;
int numLockModes = lockctl->numLockModes;
int bitmask; int bitmask;
int i, int i,
tmpMask; tmpMask;
...@@ -765,7 +756,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable, ...@@ -765,7 +756,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
* each type of lock that conflicts with request. Bitwise compare * each type of lock that conflicts with request. Bitwise compare
* tells if there is a conflict. * tells if there is a conflict.
*/ */
if (!(lockctl->conflictTab[lockmode] & lock->grantMask)) if (!(lockMethodTable->conflictTab[lockmode] & lock->grantMask))
{ {
HOLDER_PRINT("LockCheckConflicts: no conflict", holder); HOLDER_PRINT("LockCheckConflicts: no conflict", holder);
return STATUS_OK; return STATUS_OK;
...@@ -798,7 +789,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable, ...@@ -798,7 +789,7 @@ LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
* locks held by other processes. If one of these conflicts with the * 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. * kind of lock that I want, there is a conflict and I have to sleep.
*/ */
if (!(lockctl->conflictTab[lockmode] & bitmask)) if (!(lockMethodTable->conflictTab[lockmode] & bitmask))
{ {
/* no conflict. OK to get the lock */ /* no conflict. OK to get the lock */
HOLDER_PRINT("LockCheckConflicts: resolved", holder); HOLDER_PRINT("LockCheckConflicts: resolved", holder);
...@@ -918,7 +909,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode, ...@@ -918,7 +909,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
* needed, will happen in xact cleanup (see above for motivation). * needed, will happen in xact cleanup (see above for motivation).
*/ */
LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode); LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
LWLockRelease(lockMethodTable->ctl->masterLock); LWLockRelease(lockMethodTable->masterLock);
elog(ERROR, "deadlock detected"); elog(ERROR, "deadlock detected");
/* not reached */ /* not reached */
} }
...@@ -1014,7 +1005,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -1014,7 +1005,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
return FALSE; return FALSE;
} }
masterLock = lockMethodTable->ctl->masterLock; masterLock = lockMethodTable->masterLock;
LWLockAcquire(masterLock, LW_EXCLUSIVE); LWLockAcquire(masterLock, LW_EXCLUSIVE);
/* /*
...@@ -1109,7 +1100,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, ...@@ -1109,7 +1100,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
* granted locks might belong to some waiter, who could now be * granted locks might belong to some waiter, who could now be
* awakened because he doesn't conflict with his own locks. * awakened because he doesn't conflict with his own locks.
*/ */
if (lockMethodTable->ctl->conflictTab[lockmode] & lock->waitMask) if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
wakeupNeeded = true; wakeupNeeded = true;
if (lock->nRequested == 0) if (lock->nRequested == 0)
...@@ -1208,8 +1199,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, PGPROC *proc, ...@@ -1208,8 +1199,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, PGPROC *proc,
return FALSE; return FALSE;
} }
numLockModes = lockMethodTable->ctl->numLockModes; numLockModes = lockMethodTable->numLockModes;
masterLock = lockMethodTable->ctl->masterLock; masterLock = lockMethodTable->masterLock;
LWLockAcquire(masterLock, LW_EXCLUSIVE); LWLockAcquire(masterLock, LW_EXCLUSIVE);
...@@ -1264,7 +1255,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PGPROC *proc, ...@@ -1264,7 +1255,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, PGPROC *proc,
* Read comments in LockRelease * Read comments in LockRelease
*/ */
if (!wakeupNeeded && if (!wakeupNeeded &&
lockMethodTable->ctl->conflictTab[i] & lock->waitMask) lockMethodTable->conflictTab[i] & lock->waitMask)
wakeupNeeded = true; wakeupNeeded = true;
} }
} }
...@@ -1355,8 +1346,8 @@ LockShmemSize(int maxBackends) ...@@ -1355,8 +1346,8 @@ LockShmemSize(int maxBackends)
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
size += maxBackends * MAXALIGN(sizeof(PGPROC)); /* each MyProc */ size += maxBackends * MAXALIGN(sizeof(PGPROC)); /* each MyProc */
size += MAX_LOCK_METHODS * MAXALIGN(sizeof(LOCKMETHODCTL)); /* each size += MAX_LOCK_METHODS * MAXALIGN(sizeof(LOCKMETHODTABLE)); /* each
* lockMethodTable->ctl */ * lockMethodTable */
/* lockHash table */ /* lockHash table */
size += hash_estimate_size(max_table_size, sizeof(LOCK)); size += hash_estimate_size(max_table_size, sizeof(LOCK));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.122 2002/07/13 01:02:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.123 2002/07/18 23:06:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -503,8 +503,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable, ...@@ -503,8 +503,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
LOCK *lock, LOCK *lock,
HOLDER *holder) HOLDER *holder)
{ {
LOCKMETHODCTL *lockctl = lockMethodTable->ctl; LWLockId masterLock = lockMethodTable->masterLock;
LWLockId masterLock = lockctl->masterLock;
PROC_QUEUE *waitQueue = &(lock->waitProcs); PROC_QUEUE *waitQueue = &(lock->waitProcs);
int myHeldLocks = MyProc->heldLocks; int myHeldLocks = MyProc->heldLocks;
bool early_deadlock = false; bool early_deadlock = false;
...@@ -537,10 +536,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable, ...@@ -537,10 +536,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
for (i = 0; i < waitQueue->size; i++) for (i = 0; i < waitQueue->size; i++)
{ {
/* Must he wait for me? */ /* Must he wait for me? */
if (lockctl->conflictTab[proc->waitLockMode] & myHeldLocks) if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
{ {
/* Must I wait for him ? */ /* Must I wait for him ? */
if (lockctl->conflictTab[lockmode] & proc->heldLocks) if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
{ {
/* /*
* Yes, so we have a deadlock. Easiest way to clean * Yes, so we have a deadlock. Easiest way to clean
...@@ -553,7 +552,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable, ...@@ -553,7 +552,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
break; break;
} }
/* I must go before this waiter. Check special case. */ /* I must go before this waiter. Check special case. */
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 && if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
LockCheckConflicts(lockMethodTable, LockCheckConflicts(lockMethodTable,
lockmode, lockmode,
lock, lock,
...@@ -725,7 +724,6 @@ ProcWakeup(PGPROC *proc, int errType) ...@@ -725,7 +724,6 @@ ProcWakeup(PGPROC *proc, int errType)
void void
ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock) ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
{ {
LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
PROC_QUEUE *waitQueue = &(lock->waitProcs); PROC_QUEUE *waitQueue = &(lock->waitProcs);
int queue_size = waitQueue->size; int queue_size = waitQueue->size;
PGPROC *proc; PGPROC *proc;
...@@ -746,7 +744,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock) ...@@ -746,7 +744,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
* Waken if (a) doesn't conflict with requests of earlier waiters, * Waken if (a) doesn't conflict with requests of earlier waiters,
* and (b) doesn't conflict with already-held locks. * and (b) doesn't conflict with already-held locks.
*/ */
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 && if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
LockCheckConflicts(lockMethodTable, LockCheckConflicts(lockMethodTable,
lockmode, lockmode,
lock, lock,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lock.h,v 1.61 2002/06/20 20:29:52 momjian Exp $ * $Id: lock.h,v 1.62 2002/07/18 23:06:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,17 +62,14 @@ typedef int LOCKMETHOD; ...@@ -62,17 +62,14 @@ typedef int LOCKMETHOD;
* There is normally only one lock method, the default one. * There is normally only one lock method, the default one.
* If user locks are enabled, an additional lock method is present. * 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 * This is the control structure for a lock table. It
* lives in shared memory. This information is the same * lives in shared memory. This information is the same
* for all backends. * 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 * lockmethod -- the handle used by the lock table's clients to
* refer to the type of lock table being used. * refer to the type of lock table being used.
* *
...@@ -88,28 +85,17 @@ typedef int LOCKMETHOD; ...@@ -88,28 +85,17 @@ typedef int LOCKMETHOD;
* starvation). XXX this field is not actually used at present! * starvation). XXX this field is not actually used at present!
* *
* masterLock -- synchronizes access to the table * masterLock -- synchronizes access to the table
*
*/ */
typedef struct LOCKMETHODCTL typedef struct LOCKMETHODTABLE
{ {
HTAB *lockHash;
HTAB *holderHash;
LOCKMETHOD lockmethod; LOCKMETHOD lockmethod;
int numLockModes; int numLockModes;
int conflictTab[MAX_LOCKMODES]; int conflictTab[MAX_LOCKMODES];
int prio[MAX_LOCKMODES]; int prio[MAX_LOCKMODES];
LWLockId masterLock; 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; } LOCKMETHODTABLE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment