diff options
Diffstat (limited to 'src/backend/storage/lmgr/lock.c')
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 2137 |
1 files changed, 1093 insertions, 1044 deletions
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 15ede2e0ed9..7e592945f1b 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -1,37 +1,37 @@ /*------------------------------------------------------------------------- * * lock.c-- - * simple lock acquisition + * simple lock acquisition * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.11 1997/08/19 21:33:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.12 1997/09/07 04:48:58 momjian Exp $ * * NOTES - * Outside modules can create a lock table and acquire/release - * locks. A lock table is a shared memory hash table. When - * a process tries to acquire a lock of a type that conflicts - * with existing locks, it is put to sleep using the routines - * in storage/lmgr/proc.c. + * Outside modules can create a lock table and acquire/release + * locks. A lock table is a shared memory hash table. When + * a process tries to acquire a lock of a type that conflicts + * with existing locks, it is put to sleep using the routines + * in storage/lmgr/proc.c. * - * Interface: + * Interface: * - * LockAcquire(), LockRelease(), LockTabInit(). + * LockAcquire(), LockRelease(), LockTabInit(). * - * LockReplace() is called only within this module and by the - * lkchain module. It releases a lock without looking - * the lock up in the lock table. + * LockReplace() is called only within this module and by the + * lkchain module. It releases a lock without looking + * the lock up in the lock table. * - * NOTE: This module is used to define new lock tables. The - * multi-level lock table (multi.c) used by the heap - * access methods calls these routines. See multi.c for - * examples showing how to use this interface. + * NOTE: This module is used to define new lock tables. The + * multi-level lock table (multi.c) used by the heap + * access methods calls these routines. See multi.c for + * examples showing how to use this interface. * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include <sys/types.h> #include <unistd.h> @@ -48,8 +48,9 @@ #include "access/xact.h" #include "access/transam.h" -static int WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock, - LOCKT lockt); +static int +WaitOnLock(LOCKTAB * ltable, LockTableId tableId, LOCK * lock, + LOCKT lockt); /*#define LOCK_MGR_DEBUG*/ @@ -60,84 +61,85 @@ static int WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock, #define LOCK_DUMP_AUX(where,lock,type) #define XID_PRINT(where,xidentP) -#else /* LOCK_MGR_DEBUG */ - -int lockDebug = 0; -unsigned int lock_debug_oid_min = BootstrapObjectIdData; -static char *lock_types[] = { - "NONE", - "WRITE", - "READ", - "WRITE INTENT", - "READ INTENT", - "EXTEND" +#else /* LOCK_MGR_DEBUG */ + +int lockDebug = 0; +unsigned int lock_debug_oid_min = BootstrapObjectIdData; +static char *lock_types[] = { + "NONE", + "WRITE", + "READ", + "WRITE INTENT", + "READ INTENT", + "EXTEND" }; #define LOCK_PRINT(where,tag,type)\ - if ((lockDebug >= 1) && (tag->relId >= lock_debug_oid_min)) \ - elog(DEBUG, \ - "%s: pid (%d) rel (%d) dbid (%d) tid (%d,%d) type (%s)",where, \ - getpid(),\ - tag->relId, tag->dbId, \ - ((tag->tupleId.ip_blkid.bi_hi<<16)+\ - tag->tupleId.ip_blkid.bi_lo),\ - tag->tupleId.ip_posid, \ - lock_types[type]) + if ((lockDebug >= 1) && (tag->relId >= lock_debug_oid_min)) \ + elog(DEBUG, \ + "%s: pid (%d) rel (%d) dbid (%d) tid (%d,%d) type (%s)",where, \ + getpid(),\ + tag->relId, tag->dbId, \ + ((tag->tupleId.ip_blkid.bi_hi<<16)+\ + tag->tupleId.ip_blkid.bi_lo),\ + tag->tupleId.ip_posid, \ + lock_types[type]) #define LOCK_DUMP(where,lock,type)\ - if ((lockDebug >= 1) && (lock->tag.relId >= lock_debug_oid_min)) \ - LOCK_DUMP_AUX(where,lock,type) + if ((lockDebug >= 1) && (lock->tag.relId >= lock_debug_oid_min)) \ + LOCK_DUMP_AUX(where,lock,type) #define LOCK_DUMP_AUX(where,lock,type)\ - elog(DEBUG, \ - "%s: pid (%d) rel (%d) dbid (%d) tid (%d,%d) nHolding (%d) "\ - "holders (%d,%d,%d,%d,%d) type (%s)",where, \ - getpid(),\ - lock->tag.relId, lock->tag.dbId, \ - ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+\ - lock->tag.tupleId.ip_blkid.bi_lo),\ - lock->tag.tupleId.ip_posid, \ - lock->nHolding,\ - lock->holders[1],\ - lock->holders[2],\ - lock->holders[3],\ - lock->holders[4],\ - lock->holders[5],\ - lock_types[type]) + elog(DEBUG, \ + "%s: pid (%d) rel (%d) dbid (%d) tid (%d,%d) nHolding (%d) "\ + "holders (%d,%d,%d,%d,%d) type (%s)",where, \ + getpid(),\ + lock->tag.relId, lock->tag.dbId, \ + ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+\ + lock->tag.tupleId.ip_blkid.bi_lo),\ + lock->tag.tupleId.ip_posid, \ + lock->nHolding,\ + lock->holders[1],\ + lock->holders[2],\ + lock->holders[3],\ + lock->holders[4],\ + lock->holders[5],\ + lock_types[type]) #define XID_PRINT(where,xidentP)\ - if ((lockDebug >= 2) && \ - (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \ - >= lock_debug_oid_min)) \ - elog(DEBUG,\ - "%s: pid (%d) xid (%d) pid (%d) lock (%x) nHolding (%d) "\ - "holders (%d,%d,%d,%d,%d)",\ - where,\ - getpid(),\ - xidentP->tag.xid,\ - xidentP->tag.pid,\ - xidentP->tag.lock,\ - xidentP->nHolding,\ - xidentP->holders[1],\ - xidentP->holders[2],\ - xidentP->holders[3],\ - xidentP->holders[4],\ - xidentP->holders[5]) - -#endif /* LOCK_MGR_DEBUG */ - -SPINLOCK LockMgrLock; /* in Shmem or created in CreateSpinlocks() */ + if ((lockDebug >= 2) && \ + (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \ + >= lock_debug_oid_min)) \ + elog(DEBUG,\ + "%s: pid (%d) xid (%d) pid (%d) lock (%x) nHolding (%d) "\ + "holders (%d,%d,%d,%d,%d)",\ + where,\ + getpid(),\ + xidentP->tag.xid,\ + xidentP->tag.pid,\ + xidentP->tag.lock,\ + xidentP->nHolding,\ + xidentP->holders[1],\ + xidentP->holders[2],\ + xidentP->holders[3],\ + xidentP->holders[4],\ + xidentP->holders[5]) + +#endif /* LOCK_MGR_DEBUG */ + +SPINLOCK LockMgrLock; /* in Shmem or created in + * CreateSpinlocks() */ /* This is to simplify/speed up some bit arithmetic */ -static MASK BITS_OFF[MAX_LOCKTYPES]; -static MASK BITS_ON[MAX_LOCKTYPES]; +static MASK BITS_OFF[MAX_LOCKTYPES]; +static MASK BITS_ON[MAX_LOCKTYPES]; /* ----------------- * XXX Want to move this to this file * ----------------- */ -static bool LockingIsDisabled; +static bool LockingIsDisabled; /* ------------------- * map from tableId to the lock table structure @@ -149,28 +151,28 @@ static LOCKTAB *AllTables[MAX_TABLES]; * no zero-th table * ------------------- */ -static int NumTables = 1; +static int NumTables = 1; /* ------------------- * InitLocks -- Init the lock module. Create a private data - * structure for constructing conflict masks. + * structure for constructing conflict masks. * ------------------- */ void InitLocks() { - int i; - int bit; - - bit = 1; - /* ------------------- - * remember 0th locktype is invalid - * ------------------- - */ - for (i=0;i<MAX_LOCKTYPES;i++,bit <<= 1) + int i; + int bit; + + bit = 1; + /* ------------------- + * remember 0th locktype is invalid + * ------------------- + */ + for (i = 0; i < MAX_LOCKTYPES; i++, bit <<= 1) { - BITS_ON[i] = bit; - BITS_OFF[i] = ~bit; + BITS_ON[i] = bit; + BITS_OFF[i] = ~bit; } } @@ -181,30 +183,30 @@ InitLocks() void LockDisable(int status) { - LockingIsDisabled = status; + LockingIsDisabled = status; } /* * LockTypeInit -- initialize the lock table's lock type - * structures + * structures * * Notes: just copying. Should only be called once. */ static void -LockTypeInit(LOCKTAB *ltable, - MASK *conflictsP, - int *prioP, - int ntypes) +LockTypeInit(LOCKTAB * ltable, + MASK * conflictsP, + int *prioP, + int ntypes) { - int i; - - ltable->ctl->nLockTypes = ntypes; - ntypes++; - for (i=0;i<ntypes;i++,prioP++,conflictsP++) + int i; + + ltable->ctl->nLockTypes = ntypes; + ntypes++; + for (i = 0; i < ntypes; i++, prioP++, conflictsP++) { - ltable->ctl->conflictTab[i] = *conflictsP; - ltable->ctl->prio[i] = *prioP; + ltable->ctl->conflictTab[i] = *conflictsP; + ltable->ctl->prio[i] = *prioP; } } @@ -212,873 +214,900 @@ LockTypeInit(LOCKTAB *ltable, * LockTabInit -- initialize a lock table structure * * Notes: - * (a) a lock table has four separate entries in the binding - * table. This is because every shared hash table and spinlock - * has its name stored in the binding table at its creation. It - * is wasteful, in this case, but not much space is involved. + * (a) a lock table has four separate entries in the binding + * table. This is because every shared hash table and spinlock + * has its name stored in the binding table at its creation. It + * is wasteful, in this case, but not much space is involved. * */ LockTableId LockTabInit(char *tabName, - MASK *conflictsP, - int *prioP, - int ntypes) + MASK * conflictsP, + int *prioP, + int ntypes) { - LOCKTAB *ltable; - char *shmemName; - HASHCTL info; - int hash_flags; - bool found; - int status = TRUE; - - if (ntypes > MAX_LOCKTYPES) + LOCKTAB *ltable; + char *shmemName; + HASHCTL info; + int hash_flags; + bool found; + int status = TRUE; + + if (ntypes > MAX_LOCKTYPES) { - elog(NOTICE,"LockTabInit: too many lock types %d greater than %d", - ntypes,MAX_LOCKTYPES); - return(INVALID_TABLEID); + elog(NOTICE, "LockTabInit: too many lock types %d greater than %d", + ntypes, MAX_LOCKTYPES); + return (INVALID_TABLEID); } - - if (NumTables > MAX_TABLES) + + if (NumTables > MAX_TABLES) { - elog(NOTICE, - "LockTabInit: system limit of MAX_TABLES (%d) lock tables", - MAX_TABLES); - return(INVALID_TABLEID); + elog(NOTICE, + "LockTabInit: system limit of MAX_TABLES (%d) lock tables", + MAX_TABLES); + return (INVALID_TABLEID); } - - /* allocate a string for the binding table lookup */ - shmemName = (char *) palloc((unsigned)(strlen(tabName)+32)); - if (! shmemName) + + /* allocate a string for the binding table lookup */ + shmemName = (char *) palloc((unsigned) (strlen(tabName) + 32)); + if (!shmemName) { - elog(NOTICE,"LockTabInit: couldn't malloc string %s \n",tabName); - return(INVALID_TABLEID); + elog(NOTICE, "LockTabInit: couldn't malloc string %s \n", tabName); + return (INVALID_TABLEID); } - - /* each lock table has a non-shared header */ - ltable = (LOCKTAB *) palloc((unsigned) sizeof(LOCKTAB)); - if (! ltable) + + /* each lock table has a non-shared header */ + ltable = (LOCKTAB *) palloc((unsigned) sizeof(LOCKTAB)); + if (!ltable) { - elog(NOTICE,"LockTabInit: couldn't malloc lock table %s\n",tabName); - pfree (shmemName); - return(INVALID_TABLEID); + elog(NOTICE, "LockTabInit: couldn't malloc lock table %s\n", tabName); + pfree(shmemName); + return (INVALID_TABLEID); } - - /* ------------------------ - * find/acquire the spinlock for the table - * ------------------------ - */ - SpinAcquire(LockMgrLock); - - - /* ----------------------- - * allocate a control structure from shared memory or attach to it - * if it already exists. - * ----------------------- - */ - sprintf(shmemName,"%s (ctl)",tabName); - ltable->ctl = (LOCKCTL *) - ShmemInitStruct(shmemName,(unsigned)sizeof(LOCKCTL),&found); - - if (! ltable->ctl) + + /* ------------------------ + * find/acquire the spinlock for the table + * ------------------------ + */ + SpinAcquire(LockMgrLock); + + + /* ----------------------- + * allocate a control structure from shared memory or attach to it + * if it already exists. + * ----------------------- + */ + sprintf(shmemName, "%s (ctl)", tabName); + ltable->ctl = (LOCKCTL *) + ShmemInitStruct(shmemName, (unsigned) sizeof(LOCKCTL), &found); + + if (!ltable->ctl) { - elog(FATAL,"LockTabInit: couldn't initialize %s",tabName); - status = FALSE; + elog(FATAL, "LockTabInit: couldn't initialize %s", tabName); + status = FALSE; } - - /* ---------------- - * we're first - initialize - * ---------------- - */ - if (! found) + + /* ---------------- + * we're first - initialize + * ---------------- + */ + if (!found) { - memset(ltable->ctl, 0, sizeof(LOCKCTL)); - ltable->ctl->masterLock = LockMgrLock; - ltable->ctl->tableId = NumTables; + memset(ltable->ctl, 0, sizeof(LOCKCTL)); + ltable->ctl->masterLock = LockMgrLock; + ltable->ctl->tableId = NumTables; } - - /* -------------------- - * other modules refer to the lock table by a tableId - * -------------------- - */ - AllTables[NumTables] = ltable; - NumTables++; - Assert(NumTables <= MAX_TABLES); - - /* ---------------------- - * allocate a hash table for the lock tags. This is used - * to find the different locks. - * ---------------------- - */ - info.keysize = sizeof(LOCKTAG); - info.datasize = sizeof(LOCK); - info.hash = tag_hash; - hash_flags = (HASH_ELEM | HASH_FUNCTION); - - sprintf(shmemName,"%s (lock hash)",tabName); - ltable->lockHash = (HTAB *) ShmemInitHash(shmemName, - INIT_TABLE_SIZE,MAX_TABLE_SIZE, - &info,hash_flags); - - Assert( ltable->lockHash->hash == tag_hash); - if (! ltable->lockHash) + + /* -------------------- + * other modules refer to the lock table by a tableId + * -------------------- + */ + AllTables[NumTables] = ltable; + NumTables++; + Assert(NumTables <= MAX_TABLES); + + /* ---------------------- + * allocate a hash table for the lock tags. This is used + * to find the different locks. + * ---------------------- + */ + info.keysize = sizeof(LOCKTAG); + info.datasize = sizeof(LOCK); + info.hash = tag_hash; + hash_flags = (HASH_ELEM | HASH_FUNCTION); + + sprintf(shmemName, "%s (lock hash)", tabName); + ltable->lockHash = (HTAB *) ShmemInitHash(shmemName, + INIT_TABLE_SIZE, MAX_TABLE_SIZE, + &info, hash_flags); + + Assert(ltable->lockHash->hash == tag_hash); + if (!ltable->lockHash) { - elog(FATAL,"LockTabInit: couldn't initialize %s",tabName); - status = FALSE; + elog(FATAL, "LockTabInit: couldn't initialize %s", tabName); + status = FALSE; } - - /* ------------------------- - * allocate an xid table. When different transactions hold - * the same lock, additional information must be saved (locks per tx). - * ------------------------- - */ - info.keysize = XID_TAGSIZE; - info.datasize = sizeof(XIDLookupEnt); - info.hash = tag_hash; - hash_flags = (HASH_ELEM | HASH_FUNCTION); - - sprintf(shmemName,"%s (xid hash)",tabName); - ltable->xidHash = (HTAB *) ShmemInitHash(shmemName, - INIT_TABLE_SIZE,MAX_TABLE_SIZE, - &info,hash_flags); - - if (! ltable->xidHash) + + /* ------------------------- + * allocate an xid table. When different transactions hold + * the same lock, additional information must be saved (locks per tx). + * ------------------------- + */ + info.keysize = XID_TAGSIZE; + info.datasize = sizeof(XIDLookupEnt); + info.hash = tag_hash; + hash_flags = (HASH_ELEM | HASH_FUNCTION); + + sprintf(shmemName, "%s (xid hash)", tabName); + ltable->xidHash = (HTAB *) ShmemInitHash(shmemName, + INIT_TABLE_SIZE, MAX_TABLE_SIZE, + &info, hash_flags); + + if (!ltable->xidHash) { - elog(FATAL,"LockTabInit: couldn't initialize %s",tabName); - status = FALSE; + elog(FATAL, "LockTabInit: couldn't initialize %s", tabName); + status = FALSE; } - - /* init ctl data structures */ - LockTypeInit(ltable, conflictsP, prioP, ntypes); - - SpinRelease(LockMgrLock); - - pfree (shmemName); - - if (status) - return(ltable->ctl->tableId); - else - return(INVALID_TABLEID); + + /* init ctl data structures */ + LockTypeInit(ltable, conflictsP, prioP, ntypes); + + SpinRelease(LockMgrLock); + + pfree(shmemName); + + if (status) + return (ltable->ctl->tableId); + else + return (INVALID_TABLEID); } /* * LockTabRename -- allocate another tableId to the same - * lock table. + * lock table. * * NOTES: Both the lock module and the lock chain (lchain.c) - * module use table id's to distinguish between different - * kinds of locks. Short term and long term locks look - * the same to the lock table, but are handled differently - * by the lock chain manager. This function allows the - * client to use different tableIds when acquiring/releasing - * short term and long term locks. + * module use table id's to distinguish between different + * kinds of locks. Short term and long term locks look + * the same to the lock table, but are handled differently + * by the lock chain manager. This function allows the + * client to use different tableIds when acquiring/releasing + * short term and long term locks. */ #ifdef NOT_USED LockTableId LockTabRename(LockTableId tableId) { - LockTableId newTableId; - - if (NumTables >= MAX_TABLES) + LockTableId newTableId; + + if (NumTables >= MAX_TABLES) { - return(INVALID_TABLEID); + return (INVALID_TABLEID); } - if (AllTables[tableId] == INVALID_TABLEID) + if (AllTables[tableId] == INVALID_TABLEID) { - return(INVALID_TABLEID); + return (INVALID_TABLEID); } - - /* other modules refer to the lock table by a tableId */ - newTableId = NumTables; - NumTables++; - - AllTables[newTableId] = AllTables[tableId]; - return(newTableId); + + /* other modules refer to the lock table by a tableId */ + newTableId = NumTables; + NumTables++; + + AllTables[newTableId] = AllTables[tableId]; + return (newTableId); } + #endif /* * LockAcquire -- Check for lock conflicts, sleep if conflict found, - * set lock if/when no conflicts. + * set lock if/when no conflicts. * * Returns: TRUE if parameters are correct, FALSE otherwise. * * Side Effects: The lock is always acquired. No way to abort - * a lock acquisition other than aborting the transaction. - * Lock is recorded in the lkchain. + * a lock acquisition other than aborting the transaction. + * Lock is recorded in the lkchain. #ifdef USER_LOCKS - * Note on User Locks: - * User locks are handled totally on the application side as - * long term cooperative locks which extend beyond the normal - * transaction boundaries. Their purpose is to indicate to an - * application that someone is `working' on an item. So it is - * possible to put an user lock on a tuple's oid, retrieve the - * tuple, work on it for an hour and then update it and remove - * the lock. While the lock is active other clients can still - * read and write the tuple but they can be aware that it has - * been locked at the application level by someone. - * User locks use lock tags made of an uint16 and an uint32, for - * example 0 and a tuple oid, or any other arbitrary pair of - * numbers following a convention established by the application. - * In this sense tags don't refer to tuples or database entities. - * User locks and normal locks are completely orthogonal and - * they don't interfere with each other, so it is possible - * to acquire a normal lock on an user-locked tuple or user-lock - * a tuple for which a normal write lock already exists. - * User locks are always non blocking, therefore they are never - * acquired if already held by another process. They must be - * released explicitly by the application but they are released - * automatically when a backend terminates. - * They are indicated by a dummy tableId 0 which doesn't have - * any table allocated but uses the normal lock table, and are - * distinguished from normal locks for the following differences: + * Note on User Locks: + * User locks are handled totally on the application side as + * long term cooperative locks which extend beyond the normal + * transaction boundaries. Their purpose is to indicate to an + * application that someone is `working' on an item. So it is + * possible to put an user lock on a tuple's oid, retrieve the + * tuple, work on it for an hour and then update it and remove + * the lock. While the lock is active other clients can still + * read and write the tuple but they can be aware that it has + * been locked at the application level by someone. + * User locks use lock tags made of an uint16 and an uint32, for + * example 0 and a tuple oid, or any other arbitrary pair of + * numbers following a convention established by the application. + * In this sense tags don't refer to tuples or database entities. + * User locks and normal locks are completely orthogonal and + * they don't interfere with each other, so it is possible + * to acquire a normal lock on an user-locked tuple or user-lock + * a tuple for which a normal write lock already exists. + * User locks are always non blocking, therefore they are never + * acquired if already held by another process. They must be + * released explicitly by the application but they are released + * automatically when a backend terminates. + * They are indicated by a dummy tableId 0 which doesn't have + * any table allocated but uses the normal lock table, and are + * distinguished from normal locks for the following differences: * - * normal lock user lock + * normal lock user lock * - * tableId 1 0 - * tag.relId rel oid 0 - * tag.ItemPointerData.ip_blkid block id lock id2 - * tag.ItemPointerData.ip_posid tuple offset lock id1 - * xid.pid 0 backend pid - * xid.xid current xid 0 - * persistence transaction user or backend + * tableId 1 0 + * tag.relId rel oid 0 + * tag.ItemPointerData.ip_blkid block id lock id2 + * tag.ItemPointerData.ip_posid tuple offset lock id1 + * xid.pid 0 backend pid + * xid.xid current xid 0 + * persistence transaction user or backend * - * The lockt parameter can have the same values for normal locks - * although probably only WRITE_LOCK can have some practical use. + * The lockt parameter can have the same values for normal locks + * although probably only WRITE_LOCK can have some practical use. * - * DZ - 4 Oct 1996 + * DZ - 4 Oct 1996 #endif */ bool -LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt) +LockAcquire(LockTableId tableId, LOCKTAG * lockName, LOCKT lockt) { - XIDLookupEnt *result,item; - HTAB *xidTable; - bool found; - LOCK *lock = NULL; - SPINLOCK masterLock; - LOCKTAB *ltable; - int status; - TransactionId myXid; - + XIDLookupEnt *result, + item; + HTAB *xidTable; + bool found; + LOCK *lock = NULL; + SPINLOCK masterLock; + LOCKTAB *ltable; + int status; + TransactionId myXid; + #ifdef USER_LOCKS - int is_user_lock; + int is_user_lock; - is_user_lock = (tableId == 0); - if (is_user_lock) { - tableId = 1; + is_user_lock = (tableId == 0); + if (is_user_lock) + { + tableId = 1; #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockAcquire: user lock tag [%u,%u] %d", - lockName->tupleId.ip_posid, - ((lockName->tupleId.ip_blkid.bi_hi<<16)+ - lockName->tupleId.ip_blkid.bi_lo), - lockt); + elog(NOTICE, "LockAcquire: user lock tag [%u,%u] %d", + lockName->tupleId.ip_posid, + ((lockName->tupleId.ip_blkid.bi_hi << 16) + + lockName->tupleId.ip_blkid.bi_lo), + lockt); #endif - } + } #endif - Assert (tableId < NumTables); - ltable = AllTables[tableId]; - if (!ltable) + Assert(tableId < NumTables); + ltable = AllTables[tableId]; + if (!ltable) { - elog(NOTICE,"LockAcquire: bad lock table %d",tableId); - return (FALSE); + elog(NOTICE, "LockAcquire: bad lock table %d", tableId); + return (FALSE); } - - if (LockingIsDisabled) + + if (LockingIsDisabled) { - return(TRUE); + return (TRUE); } - - LOCK_PRINT("Acquire",lockName,lockt); - masterLock = ltable->ctl->masterLock; - - SpinAcquire(masterLock); - - Assert( ltable->lockHash->hash == tag_hash); - lock = (LOCK *)hash_search(ltable->lockHash,(Pointer)lockName,HASH_ENTER,&found); - - if (! lock) + + LOCK_PRINT("Acquire", lockName, lockt); + masterLock = ltable->ctl->masterLock; + + SpinAcquire(masterLock); + + Assert(ltable->lockHash->hash == tag_hash); + lock = (LOCK *) hash_search(ltable->lockHash, (Pointer) lockName, HASH_ENTER, &found); + + if (!lock) { - SpinRelease(masterLock); - elog(FATAL,"LockAcquire: lock table %d is corrupted",tableId); - return(FALSE); + SpinRelease(masterLock); + elog(FATAL, "LockAcquire: lock table %d is corrupted", tableId); + return (FALSE); } - - /* -------------------- - * if there was nothing else there, complete initialization - * -------------------- - */ - if (! found) + + /* -------------------- + * if there was nothing else there, complete initialization + * -------------------- + */ + if (!found) { - lock->mask = 0; - ProcQueueInit(&(lock->waitProcs)); - memset((char *)lock->holders, 0, sizeof(int)*MAX_LOCKTYPES); - memset((char *)lock->activeHolders, 0, sizeof(int)*MAX_LOCKTYPES); - lock->nHolding = 0; - lock->nActive = 0; - - Assert(BlockIdEquals(&(lock->tag.tupleId.ip_blkid), - &(lockName->tupleId.ip_blkid))); - + lock->mask = 0; + ProcQueueInit(&(lock->waitProcs)); + memset((char *) lock->holders, 0, sizeof(int) * MAX_LOCKTYPES); + memset((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKTYPES); + lock->nHolding = 0; + lock->nActive = 0; + + Assert(BlockIdEquals(&(lock->tag.tupleId.ip_blkid), + &(lockName->tupleId.ip_blkid))); + } - - /* ------------------ - * add an element to the lock queue so that we can clear the - * locks at end of transaction. - * ------------------ - */ - xidTable = ltable->xidHash; - myXid = GetCurrentTransactionId(); - - /* ------------------ - * Zero out all of the tag bytes (this clears the padding bytes for long - * word alignment and ensures hashing consistency). - * ------------------ - */ - memset(&item, 0, XID_TAGSIZE); - TransactionIdStore(myXid, &item.tag.xid); - item.tag.lock = MAKE_OFFSET(lock); + + /* ------------------ + * add an element to the lock queue so that we can clear the + * locks at end of transaction. + * ------------------ + */ + xidTable = ltable->xidHash; + myXid = GetCurrentTransactionId(); + + /* ------------------ + * Zero out all of the tag bytes (this clears the padding bytes for long + * word alignment and ensures hashing consistency). + * ------------------ + */ + memset(&item, 0, XID_TAGSIZE); + TransactionIdStore(myXid, &item.tag.xid); + item.tag.lock = MAKE_OFFSET(lock); #if 0 - item.tag.pid = MyPid; + item.tag.pid = MyPid; #endif - + #ifdef USER_LOCKS - if (is_user_lock) { - item.tag.pid = getpid(); - item.tag.xid = myXid = 0; + if (is_user_lock) + { + item.tag.pid = getpid(); + item.tag.xid = myXid = 0; #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockAcquire: user lock xid [%d,%d,%d]", - item.tag.lock, item.tag.pid, item.tag.xid); + elog(NOTICE, "LockAcquire: user lock xid [%d,%d,%d]", + item.tag.lock, item.tag.pid, item.tag.xid); #endif - } + } #endif - result = (XIDLookupEnt *)hash_search(xidTable, (Pointer)&item, HASH_ENTER, &found); - if (!result) + result = (XIDLookupEnt *) hash_search(xidTable, (Pointer) & item, HASH_ENTER, &found); + if (!result) { - elog(NOTICE,"LockAcquire: xid table corrupted"); - return(STATUS_ERROR); + elog(NOTICE, "LockAcquire: xid table corrupted"); + return (STATUS_ERROR); } - if (!found) + if (!found) { - XID_PRINT("LockAcquire: queueing XidEnt", result); - ProcAddLock(&result->queue); - result->nHolding = 0; - memset((char *)result->holders, 0, sizeof(int)*MAX_LOCKTYPES); + XID_PRINT("LockAcquire: queueing XidEnt", result); + ProcAddLock(&result->queue); + result->nHolding = 0; + memset((char *) result->holders, 0, sizeof(int) * MAX_LOCKTYPES); } - - /* ---------------- - * lock->nholding tells us how many processes have _tried_ to - * acquire this lock, Regardless of whether they succeeded or - * failed in doing so. - * ---------------- - */ - lock->nHolding++; - lock->holders[lockt]++; - - /* -------------------- - * If I'm the only one holding a lock, then there - * cannot be a conflict. Need to subtract one from the - * lock's count since we just bumped the count up by 1 - * above. - * -------------------- - */ - if (result->nHolding == lock->nActive) + + /* ---------------- + * lock->nholding tells us how many processes have _tried_ to + * acquire this lock, Regardless of whether they succeeded or + * failed in doing so. + * ---------------- + */ + lock->nHolding++; + lock->holders[lockt]++; + + /* -------------------- + * If I'm the only one holding a lock, then there + * cannot be a conflict. Need to subtract one from the + * lock's count since we just bumped the count up by 1 + * above. + * -------------------- + */ + if (result->nHolding == lock->nActive) { - result->holders[lockt]++; - result->nHolding++; - GrantLock(lock, lockt); - SpinRelease(masterLock); - return(TRUE); + result->holders[lockt]++; + result->nHolding++; + GrantLock(lock, lockt); + SpinRelease(masterLock); + return (TRUE); } - - Assert(result->nHolding <= lock->nActive); - - status = LockResolveConflicts(ltable, lock, lockt, myXid); - - if (status == STATUS_OK) + + Assert(result->nHolding <= lock->nActive); + + status = LockResolveConflicts(ltable, lock, lockt, myXid); + + if (status == STATUS_OK) { - GrantLock(lock, lockt); + GrantLock(lock, lockt); } - else if (status == STATUS_FOUND) + else if (status == STATUS_FOUND) { #ifdef USER_LOCKS - /* - * User locks are non blocking. If we can't acquire a lock - * remove the xid entry and return FALSE without waiting. - */ - if (is_user_lock) { - if (!result->nHolding) { - SHMQueueDelete(&result->queue); - hash_search(xidTable, (Pointer)&item, HASH_REMOVE, &found); - } - lock->nHolding--; - lock->holders[lockt]--; - SpinRelease(masterLock); + + /* + * User locks are non blocking. If we can't acquire a lock remove + * the xid entry and return FALSE without waiting. + */ + if (is_user_lock) + { + if (!result->nHolding) + { + SHMQueueDelete(&result->queue); + hash_search(xidTable, (Pointer) & item, HASH_REMOVE, &found); + } + lock->nHolding--; + lock->holders[lockt]--; + SpinRelease(masterLock); #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockAcquire: user lock failed"); + elog(NOTICE, "LockAcquire: user lock failed"); #endif - return(FALSE); - } + return (FALSE); + } #endif - status = WaitOnLock(ltable, tableId, lock, lockt); - XID_PRINT("Someone granted me the lock", result); + status = WaitOnLock(ltable, tableId, lock, lockt); + XID_PRINT("Someone granted me the lock", result); } - - SpinRelease(masterLock); - - return(status == STATUS_OK); + + SpinRelease(masterLock); + + return (status == STATUS_OK); } /* ---------------------------- * LockResolveConflicts -- test for lock conflicts * * NOTES: - * Here's what makes this complicated: one transaction's + * Here's what makes this complicated: one transaction's * locks don't conflict with one another. When many processes * hold locks, each has to subtract off the other's locks when * determining whether or not any new lock acquired conflicts with * the old ones. * - * For example, if I am already holding a WRITE_INTENT lock, - * there will not be a conflict with my own READ_LOCK. If I - * don't consider the intent lock when checking for conflicts, - * I find no conflict. + * For example, if I am already holding a WRITE_INTENT lock, + * there will not be a conflict with my own READ_LOCK. If I + * don't consider the intent lock when checking for conflicts, + * I find no conflict. * ---------------------------- */ int -LockResolveConflicts(LOCKTAB *ltable, - LOCK *lock, - LOCKT lockt, - TransactionId xid) +LockResolveConflicts(LOCKTAB * ltable, + LOCK * lock, + LOCKT lockt, + TransactionId xid) { - XIDLookupEnt *result,item; - int *myHolders; - int nLockTypes; - HTAB *xidTable; - bool found; - int bitmask; - int i,tmpMask; - - nLockTypes = ltable->ctl->nLockTypes; - xidTable = ltable->xidHash; - - /* --------------------- - * read my own statistics from the xid table. If there - * isn't an entry, then we'll just add one. - * - * Zero out the tag, this clears the padding bytes for long - * word alignment and ensures hashing consistency. - * ------------------ - */ - memset(&item, 0, XID_TAGSIZE); - TransactionIdStore(xid, &item.tag.xid); - item.tag.lock = MAKE_OFFSET(lock); + XIDLookupEnt *result, + item; + int *myHolders; + int nLockTypes; + HTAB *xidTable; + bool found; + int bitmask; + int i, + tmpMask; + + nLockTypes = ltable->ctl->nLockTypes; + xidTable = ltable->xidHash; + + /* --------------------- + * read my own statistics from the xid table. If there + * isn't an entry, then we'll just add one. + * + * Zero out the tag, this clears the padding bytes for long + * word alignment and ensures hashing consistency. + * ------------------ + */ + memset(&item, 0, XID_TAGSIZE); + TransactionIdStore(xid, &item.tag.xid); + item.tag.lock = MAKE_OFFSET(lock); #if 0 - item.tag.pid = pid; + item.tag.pid = pid; #endif - - if (! (result = (XIDLookupEnt *) - hash_search(xidTable, (Pointer)&item, HASH_ENTER, &found))) + + if (!(result = (XIDLookupEnt *) + hash_search(xidTable, (Pointer) & item, HASH_ENTER, &found))) { - elog(NOTICE,"LockResolveConflicts: xid table corrupted"); - return(STATUS_ERROR); + elog(NOTICE, "LockResolveConflicts: xid table corrupted"); + return (STATUS_ERROR); } - myHolders = result->holders; - - if (! found) + myHolders = result->holders; + + if (!found) { - /* --------------- - * we're not holding any type of lock yet. Clear - * the lock stats. - * --------------- - */ - memset(result->holders, 0, nLockTypes * sizeof(*(lock->holders))); - result->nHolding = 0; + /* --------------- + * we're not holding any type of lock yet. Clear + * the lock stats. + * --------------- + */ + memset(result->holders, 0, nLockTypes * sizeof(*(lock->holders))); + result->nHolding = 0; } - - /* ---------------------------- - * first check for global conflicts: If no locks conflict - * with mine, then I get the lock. - * - * Checking for conflict: lock->mask represents the types of - * currently held locks. conflictTable[lockt] has a bit - * set for each type of lock that conflicts with mine. Bitwise - * compare tells if there is a conflict. - * ---------------------------- - */ - if (! (ltable->ctl->conflictTab[lockt] & lock->mask)) + + /* ---------------------------- + * first check for global conflicts: If no locks conflict + * with mine, then I get the lock. + * + * Checking for conflict: lock->mask represents the types of + * currently held locks. conflictTable[lockt] has a bit + * set for each type of lock that conflicts with mine. Bitwise + * compare tells if there is a conflict. + * ---------------------------- + */ + if (!(ltable->ctl->conflictTab[lockt] & lock->mask)) { - - result->holders[lockt]++; - result->nHolding++; - - XID_PRINT("Conflict Resolved: updated xid entry stats", result); - - return(STATUS_OK); + + result->holders[lockt]++; + result->nHolding++; + + XID_PRINT("Conflict Resolved: updated xid entry stats", result); + + return (STATUS_OK); } - - /* ------------------------ - * Rats. Something conflicts. But it could still be my own - * lock. We have to construct a conflict mask - * that does not reflect our own locks. - * ------------------------ - */ - bitmask = 0; - tmpMask = 2; - for (i=1;i<=nLockTypes;i++, tmpMask <<= 1) + + /* ------------------------ + * Rats. Something conflicts. But it could still be my own + * lock. We have to construct a conflict mask + * that does not reflect our own locks. + * ------------------------ + */ + bitmask = 0; + tmpMask = 2; + for (i = 1; i <= nLockTypes; i++, tmpMask <<= 1) { - if (lock->activeHolders[i] - myHolders[i]) + if (lock->activeHolders[i] - myHolders[i]) { - bitmask |= tmpMask; + bitmask |= tmpMask; } } - - /* ------------------------ - * now check again for conflicts. 'bitmask' describes the types - * of 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 (! (ltable->ctl->conflictTab[lockt] & bitmask)) + + /* ------------------------ + * now check again for conflicts. 'bitmask' describes the types + * of 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 (!(ltable->ctl->conflictTab[lockt] & bitmask)) { - - /* no conflict. Get the lock and go on */ - - result->holders[lockt]++; - result->nHolding++; - - XID_PRINT("Conflict Resolved: updated xid entry stats", result); - - return(STATUS_OK); - + + /* no conflict. Get the lock and go on */ + + result->holders[lockt]++; + result->nHolding++; + + XID_PRINT("Conflict Resolved: updated xid entry stats", result); + + return (STATUS_OK); + } - - return(STATUS_FOUND); + + return (STATUS_FOUND); } static int -WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock, LOCKT lockt) +WaitOnLock(LOCKTAB * ltable, LockTableId tableId, LOCK * lock, LOCKT lockt) { - PROC_QUEUE *waitQueue = &(lock->waitProcs); - - int prio = ltable->ctl->prio[lockt]; - - /* the waitqueue is ordered by priority. I insert myself - * according to the priority of the lock I am acquiring. - * - * SYNC NOTE: I am assuming that the lock table spinlock - * is sufficient synchronization for this queue. That - * will not be true if/when people can be deleted from - * the queue by a SIGINT or something. - */ - LOCK_DUMP_AUX("WaitOnLock: sleeping on lock", lock, lockt); - if (ProcSleep(waitQueue, - ltable->ctl->masterLock, - lockt, - prio, - lock) != NO_ERROR) + PROC_QUEUE *waitQueue = &(lock->waitProcs); + + int prio = ltable->ctl->prio[lockt]; + + /* + * the waitqueue is ordered by priority. I insert myself according to + * the priority of the lock I am acquiring. + * + * SYNC NOTE: I am assuming that the lock table spinlock is sufficient + * synchronization for this queue. That will not be true if/when + * people can be deleted from the queue by a SIGINT or something. + */ + LOCK_DUMP_AUX("WaitOnLock: sleeping on lock", lock, lockt); + if (ProcSleep(waitQueue, + ltable->ctl->masterLock, + lockt, + prio, + lock) != NO_ERROR) { - /* ------------------- - * This could have happend as a result of a deadlock, see HandleDeadLock() - * Decrement the lock nHolding and holders fields as we are no longer - * waiting on this lock. - * ------------------- - */ - lock->nHolding--; - lock->holders[lockt]--; - LOCK_DUMP_AUX("WaitOnLock: aborting on lock", lock, lockt); - SpinRelease(ltable->ctl->masterLock); - elog(WARN,"WaitOnLock: error on wakeup - Aborting this transaction"); + /* ------------------- + * This could have happend as a result of a deadlock, see HandleDeadLock() + * Decrement the lock nHolding and holders fields as we are no longer + * waiting on this lock. + * ------------------- + */ + lock->nHolding--; + lock->holders[lockt]--; + LOCK_DUMP_AUX("WaitOnLock: aborting on lock", lock, lockt); + SpinRelease(ltable->ctl->masterLock); + elog(WARN, "WaitOnLock: error on wakeup - Aborting this transaction"); } - - LOCK_DUMP_AUX("WaitOnLock: wakeup on lock", lock, lockt); - return(STATUS_OK); + + LOCK_DUMP_AUX("WaitOnLock: wakeup on lock", lock, lockt); + return (STATUS_OK); } /* * LockRelease -- look up 'lockName' in lock table 'tableId' and - * release it. + * release it. * * Side Effects: if the lock no longer conflicts with the highest - * priority waiting process, that process is granted the lock - * and awoken. (We have to grant the lock here to avoid a - * race between the waking process and any new process to - * come along and request the lock). + * priority waiting process, that process is granted the lock + * and awoken. (We have to grant the lock here to avoid a + * race between the waking process and any new process to + * come along and request the lock). */ bool -LockRelease(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt) +LockRelease(LockTableId tableId, LOCKTAG * lockName, LOCKT lockt) { - LOCK *lock = NULL; - SPINLOCK masterLock; - bool found; - LOCKTAB *ltable; - XIDLookupEnt *result,item; - HTAB *xidTable; - bool wakeupNeeded = true; - + LOCK *lock = NULL; + SPINLOCK masterLock; + bool found; + LOCKTAB *ltable; + XIDLookupEnt *result, + item; + HTAB *xidTable; + bool wakeupNeeded = true; + #ifdef USER_LOCKS - int is_user_lock; + int is_user_lock; - is_user_lock = (tableId == 0); - if (is_user_lock) { - tableId = 1; + is_user_lock = (tableId == 0); + if (is_user_lock) + { + tableId = 1; #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockRelease: user lock tag [%u,%u] %d", - lockName->tupleId.ip_posid, - ((lockName->tupleId.ip_blkid.bi_hi<<16)+ - lockName->tupleId.ip_blkid.bi_lo), - lockt); + elog(NOTICE, "LockRelease: user lock tag [%u,%u] %d", + lockName->tupleId.ip_posid, + ((lockName->tupleId.ip_blkid.bi_hi << 16) + + lockName->tupleId.ip_blkid.bi_lo), + lockt); #endif - } + } #endif - Assert (tableId < NumTables); - ltable = AllTables[tableId]; - if (!ltable) { - elog(NOTICE, "ltable is null in LockRelease"); - return (FALSE); - } - - if (LockingIsDisabled) + Assert(tableId < NumTables); + ltable = AllTables[tableId]; + if (!ltable) + { + elog(NOTICE, "ltable is null in LockRelease"); + return (FALSE); + } + + if (LockingIsDisabled) { - return(TRUE); + return (TRUE); } - - LOCK_PRINT("Release",lockName,lockt); - - masterLock = ltable->ctl->masterLock; - xidTable = ltable->xidHash; - - SpinAcquire(masterLock); - - Assert( ltable->lockHash->hash == tag_hash); - lock = (LOCK *) - hash_search(ltable->lockHash,(Pointer)lockName,HASH_FIND_SAVE,&found); - + + LOCK_PRINT("Release", lockName, lockt); + + masterLock = ltable->ctl->masterLock; + xidTable = ltable->xidHash; + + SpinAcquire(masterLock); + + Assert(ltable->lockHash->hash == tag_hash); + lock = (LOCK *) + hash_search(ltable->lockHash, (Pointer) lockName, HASH_FIND_SAVE, &found); + #ifdef USER_LOCKS - /* - * If the entry is not found hash_search returns TRUE - * instead of NULL, so we must check it explicitly. - */ - if ((is_user_lock) && (lock == (LOCK *)TRUE)) { - SpinRelease(masterLock); - elog(NOTICE,"LockRelease: there are no locks with this tag"); - return(FALSE); - } + + /* + * If the entry is not found hash_search returns TRUE instead of NULL, + * so we must check it explicitly. + */ + if ((is_user_lock) && (lock == (LOCK *) TRUE)) + { + SpinRelease(masterLock); + elog(NOTICE, "LockRelease: there are no locks with this tag"); + return (FALSE); + } #endif - /* let the caller print its own error message, too. - * Do not elog(WARN). - */ - if (! lock) + /* + * let the caller print its own error message, too. Do not elog(WARN). + */ + if (!lock) { - SpinRelease(masterLock); - elog(NOTICE,"LockRelease: locktable corrupted"); - return(FALSE); + SpinRelease(masterLock); + elog(NOTICE, "LockRelease: locktable corrupted"); + return (FALSE); } - - if (! found) + + if (!found) { - SpinRelease(masterLock); - elog(NOTICE,"LockRelease: locktable lookup failed, no lock"); - return(FALSE); + SpinRelease(masterLock); + elog(NOTICE, "LockRelease: locktable lookup failed, no lock"); + return (FALSE); } - - Assert(lock->nHolding > 0); - + + Assert(lock->nHolding > 0); + #ifdef USER_LOCKS - /* - * If this is an user lock it can be removed only after - * checking that it was acquired by the current process, - * so this code is skipped and executed later. - */ - if (!is_user_lock) { -#endif - /* - * fix the general lock stats - */ - lock->nHolding--; - lock->holders[lockt]--; - lock->nActive--; - lock->activeHolders[lockt]--; - - Assert(lock->nActive >= 0); - - if (! lock->nHolding) + + /* + * If this is an user lock it can be removed only after checking that + * it was acquired by the current process, so this code is skipped and + * executed later. + */ + if (!is_user_lock) { - /* ------------------ - * if there's no one waiting in the queue, - * we just released the last lock. - * Delete it from the lock table. - * ------------------ - */ - Assert( ltable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(ltable->lockHash, - (Pointer) &(lock->tag), - HASH_REMOVE_SAVED, - &found); - Assert(lock && found); - wakeupNeeded = false; - } +#endif + + /* + * fix the general lock stats + */ + lock->nHolding--; + lock->holders[lockt]--; + lock->nActive--; + lock->activeHolders[lockt]--; + + Assert(lock->nActive >= 0); + + if (!lock->nHolding) + { + /* ------------------ + * if there's no one waiting in the queue, + * we just released the last lock. + * Delete it from the lock table. + * ------------------ + */ + Assert(ltable->lockHash->hash == tag_hash); + lock = (LOCK *) hash_search(ltable->lockHash, + (Pointer) & (lock->tag), + HASH_REMOVE_SAVED, + &found); + Assert(lock && found); + wakeupNeeded = false; + } #ifdef USER_LOCKS - } + } #endif - - /* ------------------ - * Zero out all of the tag bytes (this clears the padding bytes for long - * word alignment and ensures hashing consistency). - * ------------------ - */ - memset(&item, 0, XID_TAGSIZE); - - TransactionIdStore(GetCurrentTransactionId(), &item.tag.xid); - item.tag.lock = MAKE_OFFSET(lock); + + /* ------------------ + * Zero out all of the tag bytes (this clears the padding bytes for long + * word alignment and ensures hashing consistency). + * ------------------ + */ + memset(&item, 0, XID_TAGSIZE); + + TransactionIdStore(GetCurrentTransactionId(), &item.tag.xid); + item.tag.lock = MAKE_OFFSET(lock); #if 0 - item.tag.pid = MyPid; + item.tag.pid = MyPid; #endif - + #ifdef USER_LOCKS - if (is_user_lock) { - item.tag.pid = getpid(); - item.tag.xid = 0; + if (is_user_lock) + { + item.tag.pid = getpid(); + item.tag.xid = 0; #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockRelease: user lock xid [%d,%d,%d]", - item.tag.lock, item.tag.pid, item.tag.xid); + elog(NOTICE, "LockRelease: user lock xid [%d,%d,%d]", + item.tag.lock, item.tag.pid, item.tag.xid); #endif - } + } #endif - if (! ( result = (XIDLookupEnt *) hash_search(xidTable, - (Pointer)&item, - HASH_FIND_SAVE, - &found) ) - || !found) + if (!(result = (XIDLookupEnt *) hash_search(xidTable, + (Pointer) & item, + HASH_FIND_SAVE, + &found)) + || !found) { - SpinRelease(masterLock); + SpinRelease(masterLock); #ifdef USER_LOCKS - if ((is_user_lock) && (result)) { - elog(NOTICE,"LockRelease: you don't have a lock on this tag"); - } else { - elog(NOTICE,"LockRelease: find xid, table corrupted"); - } + if ((is_user_lock) && (result)) + { + elog(NOTICE, "LockRelease: you don't have a lock on this tag"); + } + else + { + elog(NOTICE, "LockRelease: find xid, table corrupted"); + } #else - elog(NOTICE,"LockReplace: xid table corrupted"); + elog(NOTICE, "LockReplace: xid table corrupted"); #endif - return(FALSE); + return (FALSE); } - /* - * now check to see if I have any private locks. If I do, - * decrement the counts associated with them. - */ - result->holders[lockt]--; - result->nHolding--; - - XID_PRINT("LockRelease updated xid stats", result); - - /* - * If this was my last hold on this lock, delete my entry - * in the XID table. - */ - if (! result->nHolding) + + /* + * now check to see if I have any private locks. If I do, decrement + * the counts associated with them. + */ + result->holders[lockt]--; + result->nHolding--; + + XID_PRINT("LockRelease updated xid stats", result); + + /* + * If this was my last hold on this lock, delete my entry in the XID + * table. + */ + if (!result->nHolding) { #ifdef USER_LOCKS - if (result->queue.prev == INVALID_OFFSET) { - elog(NOTICE,"LockRelease: xid.prev == INVALID_OFFSET"); - } - if (result->queue.next == INVALID_OFFSET) { - elog(NOTICE,"LockRelease: xid.next == INVALID_OFFSET"); - } + if (result->queue.prev == INVALID_OFFSET) + { + elog(NOTICE, "LockRelease: xid.prev == INVALID_OFFSET"); + } + if (result->queue.next == INVALID_OFFSET) + { + elog(NOTICE, "LockRelease: xid.next == INVALID_OFFSET"); + } #endif - if (result->queue.next != INVALID_OFFSET) - SHMQueueDelete(&result->queue); - if (! (result = (XIDLookupEnt *) - hash_search(xidTable, (Pointer)&item, HASH_REMOVE_SAVED, &found)) || - ! found) + if (result->queue.next != INVALID_OFFSET) + SHMQueueDelete(&result->queue); + if (!(result = (XIDLookupEnt *) + hash_search(xidTable, (Pointer) & item, HASH_REMOVE_SAVED, &found)) || + !found) { - SpinRelease(masterLock); + SpinRelease(masterLock); #ifdef USER_LOCKS - elog(NOTICE,"LockRelease: remove xid, table corrupted"); + elog(NOTICE, "LockRelease: remove xid, table corrupted"); #else - elog(NOTICE,"LockReplace: xid table corrupted"); + elog(NOTICE, "LockReplace: xid table corrupted"); #endif - return(FALSE); + return (FALSE); } } - + #ifdef USER_LOCKS - /* - * If this is an user lock remove it now, after the - * corresponding xid entry has been found and deleted. - */ - if (is_user_lock) { - /* - * fix the general lock stats - */ - lock->nHolding--; - lock->holders[lockt]--; - lock->nActive--; - lock->activeHolders[lockt]--; - - Assert(lock->nActive >= 0); - - if (! lock->nHolding) + + /* + * If this is an user lock remove it now, after the corresponding xid + * entry has been found and deleted. + */ + if (is_user_lock) { - /* ------------------ - * if there's no one waiting in the queue, - * we just released the last lock. - * Delete it from the lock table. - * ------------------ - */ - Assert( ltable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(ltable->lockHash, - (Pointer) &(lock->tag), - HASH_REMOVE, - &found); - Assert(lock && found); - wakeupNeeded = false; + + /* + * fix the general lock stats + */ + lock->nHolding--; + lock->holders[lockt]--; + lock->nActive--; + lock->activeHolders[lockt]--; + + Assert(lock->nActive >= 0); + + if (!lock->nHolding) + { + /* ------------------ + * if there's no one waiting in the queue, + * we just released the last lock. + * Delete it from the lock table. + * ------------------ + */ + Assert(ltable->lockHash->hash == tag_hash); + lock = (LOCK *) hash_search(ltable->lockHash, + (Pointer) & (lock->tag), + HASH_REMOVE, + &found); + Assert(lock && found); + wakeupNeeded = false; + } } - } #endif - /* -------------------------- - * If there are still active locks of the type I just released, no one - * should be woken up. Whoever is asleep will still conflict - * with the remaining locks. - * -------------------------- - */ - if (! (lock->activeHolders[lockt])) + /* -------------------------- + * If there are still active locks of the type I just released, no one + * should be woken up. Whoever is asleep will still conflict + * with the remaining locks. + * -------------------------- + */ + if (!(lock->activeHolders[lockt])) { - /* change the conflict mask. No more of this lock type. */ - lock->mask &= BITS_OFF[lockt]; + /* change the conflict mask. No more of this lock type. */ + lock->mask &= BITS_OFF[lockt]; } - - if (wakeupNeeded) + + if (wakeupNeeded) { - /* -------------------------- - * Wake the first waiting process and grant him the lock if it - * doesn't conflict. The woken process must record the lock - * himself. - * -------------------------- - */ - ProcLockWakeup(&(lock->waitProcs), (char *) ltable, (char *) lock); + /* -------------------------- + * Wake the first waiting process and grant him the lock if it + * doesn't conflict. The woken process must record the lock + * himself. + * -------------------------- + */ + ProcLockWakeup(&(lock->waitProcs), (char *) ltable, (char *) lock); } - - SpinRelease(masterLock); - return(TRUE); + + SpinRelease(masterLock); + return (TRUE); } /* * GrantLock -- udpate the lock data structure to show - * the new lock holder. + * the new lock holder. */ void -GrantLock(LOCK *lock, LOCKT lockt) +GrantLock(LOCK * lock, LOCKT lockt) { - lock->nActive++; - lock->activeHolders[lockt]++; - lock->mask |= BITS_ON[lockt]; + lock->nActive++; + lock->activeHolders[lockt]++; + lock->mask |= BITS_ON[lockt]; } #ifdef USER_LOCKS @@ -1086,265 +1115,281 @@ GrantLock(LOCK *lock, LOCKT lockt) * LockReleaseAll -- Release all locks in a process lock queue. * * Note: This code is a little complicated by the presence in the - * same queue of user locks which can't be removed from the - * normal lock queue at the end of a transaction. They must - * however be removed when the backend exits. - * A dummy tableId 0 is used to indicate that we are releasing - * the user locks, from the code added to ProcKill(). + * same queue of user locks which can't be removed from the + * normal lock queue at the end of a transaction. They must + * however be removed when the backend exits. + * A dummy tableId 0 is used to indicate that we are releasing + * the user locks, from the code added to ProcKill(). */ #endif bool -LockReleaseAll(LockTableId tableId, SHM_QUEUE *lockQueue) +LockReleaseAll(LockTableId tableId, SHM_QUEUE * lockQueue) { - PROC_QUEUE *waitQueue; - int done; - XIDLookupEnt *xidLook = NULL; - XIDLookupEnt *tmp = NULL; - SHMEM_OFFSET end = MAKE_OFFSET(lockQueue); - SPINLOCK masterLock; - LOCKTAB *ltable; - int i,nLockTypes; - LOCK *lock; - bool found; - + PROC_QUEUE *waitQueue; + int done; + XIDLookupEnt *xidLook = NULL; + XIDLookupEnt *tmp = NULL; + SHMEM_OFFSET end = MAKE_OFFSET(lockQueue); + SPINLOCK masterLock; + LOCKTAB *ltable; + int i, + nLockTypes; + LOCK *lock; + bool found; + #ifdef USER_LOCKS - int is_user_lock_table, my_pid, count, nskip; + int is_user_lock_table, + my_pid, + count, + nskip; - is_user_lock_table = (tableId == 0); - my_pid = getpid(); + is_user_lock_table = (tableId == 0); + my_pid = getpid(); #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockReleaseAll: tableId=%d, pid=%d", tableId, my_pid); + elog(NOTICE, "LockReleaseAll: tableId=%d, pid=%d", tableId, my_pid); #endif - if (is_user_lock_table) { - tableId = 1; - } + if (is_user_lock_table) + { + tableId = 1; + } #endif - Assert (tableId < NumTables); - ltable = AllTables[tableId]; - if (!ltable) - return (FALSE); - - nLockTypes = ltable->ctl->nLockTypes; - masterLock = ltable->ctl->masterLock; - - if (SHMQueueEmpty(lockQueue)) - return TRUE; - + Assert(tableId < NumTables); + ltable = AllTables[tableId]; + if (!ltable) + return (FALSE); + + nLockTypes = ltable->ctl->nLockTypes; + masterLock = ltable->ctl->masterLock; + + if (SHMQueueEmpty(lockQueue)) + return TRUE; + #ifdef USER_LOCKS - SpinAcquire(masterLock); + SpinAcquire(masterLock); #endif - SHMQueueFirst(lockQueue,(Pointer*)&xidLook,&xidLook->queue); - - XID_PRINT("LockReleaseAll", xidLook); - + SHMQueueFirst(lockQueue, (Pointer *) & xidLook, &xidLook->queue); + + XID_PRINT("LockReleaseAll", xidLook); + #ifndef USER_LOCKS - SpinAcquire(masterLock); + SpinAcquire(masterLock); #else - count = nskip = 0; + count = nskip = 0; #endif - for (;;) + for (;;) { - /* --------------------------- - * XXX Here we assume the shared memory queue is circular and - * that we know its internal structure. Should have some sort of - * macros to allow one to walk it. mer 20 July 1991 - * --------------------------- - */ - done = (xidLook->queue.next == end); - lock = (LOCK *) MAKE_PTR(xidLook->tag.lock); - - LOCK_PRINT("ReleaseAll",(&lock->tag),0); - + /* --------------------------- + * XXX Here we assume the shared memory queue is circular and + * that we know its internal structure. Should have some sort of + * macros to allow one to walk it. mer 20 July 1991 + * --------------------------- + */ + done = (xidLook->queue.next == end); + lock = (LOCK *) MAKE_PTR(xidLook->tag.lock); + + LOCK_PRINT("ReleaseAll", (&lock->tag), 0); + #ifdef USER_LOCKS - /* - * Sometimes the queue appears to be messed up. - */ - if (count++ > 2000) { - elog(NOTICE,"LockReleaseAll: xid loop detected, giving up"); - nskip = 0; - break; - } - if (is_user_lock_table) { - if ((xidLook->tag.pid == 0) || (xidLook->tag.xid != 0)) { -#ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockReleaseAll: skip normal lock [%d,%d,%d]", - xidLook->tag.lock,xidLook->tag.pid,xidLook->tag.xid); -#endif - nskip++; - goto next_item; + + /* + * Sometimes the queue appears to be messed up. + */ + if (count++ > 2000) + { + elog(NOTICE, "LockReleaseAll: xid loop detected, giving up"); + nskip = 0; + break; } - if (xidLook->tag.pid != my_pid) { - /* This should never happen */ + if (is_user_lock_table) + { + if ((xidLook->tag.pid == 0) || (xidLook->tag.xid != 0)) + { #ifdef USER_LOCKS_DEBUG - elog(NOTICE, - "LockReleaseAll: skip other pid [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ - lock->tag.tupleId.ip_blkid.bi_lo), - xidLook->tag.lock,xidLook->tag.pid,xidLook->tag.xid); + elog(NOTICE, "LockReleaseAll: skip normal lock [%d,%d,%d]", + xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); #endif - nskip++; - goto next_item; - } + nskip++; + goto next_item; + } + if (xidLook->tag.pid != my_pid) + { + /* This should never happen */ #ifdef USER_LOCKS_DEBUG - elog(NOTICE, - "LockReleaseAll: release user lock [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ - lock->tag.tupleId.ip_blkid.bi_lo), - xidLook->tag.lock,xidLook->tag.pid,xidLook->tag.xid); + elog(NOTICE, + "LockReleaseAll: skip other pid [%u,%u] [%d,%d,%d]", + lock->tag.tupleId.ip_posid, + ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + + lock->tag.tupleId.ip_blkid.bi_lo), + xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); #endif - } else { - if ((xidLook->tag.pid != 0) || (xidLook->tag.xid == 0)) { + nskip++; + goto next_item; + } #ifdef USER_LOCKS_DEBUG - elog(NOTICE, - "LockReleaseAll: skip user lock [%u,%u] [%d,%d,%d]", - lock->tag.tupleId.ip_posid, - ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ - lock->tag.tupleId.ip_blkid.bi_lo), - xidLook->tag.lock,xidLook->tag.pid,xidLook->tag.xid); + elog(NOTICE, + "LockReleaseAll: release user lock [%u,%u] [%d,%d,%d]", + lock->tag.tupleId.ip_posid, + ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + + lock->tag.tupleId.ip_blkid.bi_lo), + xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); #endif - nskip++; - goto next_item; } + else + { + if ((xidLook->tag.pid != 0) || (xidLook->tag.xid == 0)) + { #ifdef USER_LOCKS_DEBUG - elog(NOTICE,"LockReleaseAll: release normal lock [%d,%d,%d]", - xidLook->tag.lock,xidLook->tag.pid,xidLook->tag.xid); + elog(NOTICE, + "LockReleaseAll: skip user lock [%u,%u] [%d,%d,%d]", + lock->tag.tupleId.ip_posid, + ((lock->tag.tupleId.ip_blkid.bi_hi << 16) + + lock->tag.tupleId.ip_blkid.bi_lo), + xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); #endif - } + nskip++; + goto next_item; + } +#ifdef USER_LOCKS_DEBUG + elog(NOTICE, "LockReleaseAll: release normal lock [%d,%d,%d]", + xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid); +#endif + } #endif - /* ------------------ - * fix the general lock stats - * ------------------ - */ - if (lock->nHolding != xidLook->nHolding) + /* ------------------ + * fix the general lock stats + * ------------------ + */ + if (lock->nHolding != xidLook->nHolding) { - lock->nHolding -= xidLook->nHolding; - lock->nActive -= xidLook->nHolding; - Assert(lock->nActive >= 0); - for (i=1; i<=nLockTypes; i++) + lock->nHolding -= xidLook->nHolding; + lock->nActive -= xidLook->nHolding; + Assert(lock->nActive >= 0); + for (i = 1; i <= nLockTypes; i++) { - lock->holders[i] -= xidLook->holders[i]; - lock->activeHolders[i] -= xidLook->holders[i]; - if (! lock->activeHolders[i]) - lock->mask &= BITS_OFF[i]; + lock->holders[i] -= xidLook->holders[i]; + lock->activeHolders[i] -= xidLook->holders[i]; + if (!lock->activeHolders[i]) + lock->mask &= BITS_OFF[i]; } } - else + else { - /* -------------- - * set nHolding to zero so that we can garbage collect the lock - * down below... - * -------------- - */ - lock->nHolding = 0; + /* -------------- + * set nHolding to zero so that we can garbage collect the lock + * down below... + * -------------- + */ + lock->nHolding = 0; } - /* ---------------- - * always remove the xidLookup entry, we're done with it now - * ---------------- - */ + /* ---------------- + * always remove the xidLookup entry, we're done with it now + * ---------------- + */ #ifdef USER_LOCKS - SHMQueueDelete(&xidLook->queue); + SHMQueueDelete(&xidLook->queue); #endif - if ((! hash_search(ltable->xidHash, (Pointer)xidLook, HASH_REMOVE, &found)) - || !found) + if ((!hash_search(ltable->xidHash, (Pointer) xidLook, HASH_REMOVE, &found)) + || !found) { - SpinRelease(masterLock); + SpinRelease(masterLock); #ifdef USER_LOCKS - elog(NOTICE,"LockReleaseAll: xid table corrupted"); + elog(NOTICE, "LockReleaseAll: xid table corrupted"); #else - elog(NOTICE,"LockReplace: xid table corrupted"); + elog(NOTICE, "LockReplace: xid table corrupted"); #endif - return(FALSE); + return (FALSE); } - - if (! lock->nHolding) + + if (!lock->nHolding) { - /* -------------------- - * if there's no one waiting in the queue, we've just released - * the last lock. - * -------------------- - */ - - Assert( ltable->lockHash->hash == tag_hash); - lock = (LOCK *) - hash_search(ltable->lockHash,(Pointer)&(lock->tag),HASH_REMOVE, &found); - if ((! lock) || (!found)) + /* -------------------- + * if there's no one waiting in the queue, we've just released + * the last lock. + * -------------------- + */ + + Assert(ltable->lockHash->hash == tag_hash); + lock = (LOCK *) + hash_search(ltable->lockHash, (Pointer) & (lock->tag), HASH_REMOVE, &found); + if ((!lock) || (!found)) { - SpinRelease(masterLock); + SpinRelease(masterLock); #ifdef USER_LOCKS - elog(NOTICE,"LockReleaseAll: cannot remove lock from HTAB"); + elog(NOTICE, "LockReleaseAll: cannot remove lock from HTAB"); #else - elog(NOTICE,"LockReplace: cannot remove lock from HTAB"); + elog(NOTICE, "LockReplace: cannot remove lock from HTAB"); #endif - return(FALSE); + return (FALSE); } } - else + else { - /* -------------------- - * Wake the first waiting process and grant him the lock if it - * doesn't conflict. The woken process must record the lock - * him/herself. - * -------------------- - */ - waitQueue = &(lock->waitProcs); - ProcLockWakeup(waitQueue, (char *) ltable, (char *) lock); + /* -------------------- + * Wake the first waiting process and grant him the lock if it + * doesn't conflict. The woken process must record the lock + * him/herself. + * -------------------- + */ + waitQueue = &(lock->waitProcs); + ProcLockWakeup(waitQueue, (char *) ltable, (char *) lock); } - + #ifdef USER_LOCKS - next_item: +next_item: #endif - if (done) - break; - SHMQueueFirst(&xidLook->queue,(Pointer*)&tmp,&tmp->queue); - xidLook = tmp; + if (done) + break; + SHMQueueFirst(&xidLook->queue, (Pointer *) & tmp, &tmp->queue); + xidLook = tmp; } - SpinRelease(masterLock); + SpinRelease(masterLock); #ifdef USER_LOCKS - /* - * Reinitialize the queue only if nothing has been left in. - */ - if (nskip == 0) + + /* + * Reinitialize the queue only if nothing has been left in. + */ + if (nskip == 0) #endif - SHMQueueInit(lockQueue); - return TRUE; + SHMQueueInit(lockQueue); + return TRUE; } int LockShmemSize() { - int size = 0; - int nLockBuckets, nLockSegs; - int nXidBuckets, nXidSegs; - - nLockBuckets = 1 << (int)my_log2((NLOCKENTS - 1) / DEF_FFACTOR + 1); - nLockSegs = 1 << (int)my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1); - - nXidBuckets = 1 << (int)my_log2((NLOCKS_PER_XACT-1) / DEF_FFACTOR + 1); - nXidSegs = 1 << (int)my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1); - - size += MAXALIGN(NBACKENDS * sizeof(PROC)); /* each MyProc */ - size += MAXALIGN(NBACKENDS * sizeof(LOCKCTL)); /* each ltable->ctl */ - size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ - - size += MAXALIGN(my_log2(NLOCKENTS) * sizeof(void *)); - size += MAXALIGN(sizeof(HHDR)); - size += nLockSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); - size += NLOCKENTS * /* XXX not multiple of BUCKET_ALLOC_INCR? */ - (MAXALIGN(sizeof(BUCKET_INDEX)) + - MAXALIGN(sizeof(LOCK))); /* contains hash key */ - - size += MAXALIGN(my_log2(NBACKENDS) * sizeof(void *)); - size += MAXALIGN(sizeof(HHDR)); - size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); - size += NBACKENDS * /* XXX not multiple of BUCKET_ALLOC_INCR? */ - (MAXALIGN(sizeof(BUCKET_INDEX)) + - MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */ - - return size; + int size = 0; + int nLockBuckets, + nLockSegs; + int nXidBuckets, + nXidSegs; + + nLockBuckets = 1 << (int) my_log2((NLOCKENTS - 1) / DEF_FFACTOR + 1); + nLockSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1); + + nXidBuckets = 1 << (int) my_log2((NLOCKS_PER_XACT - 1) / DEF_FFACTOR + 1); + nXidSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1); + + size += MAXALIGN(NBACKENDS * sizeof(PROC)); /* each MyProc */ + size += MAXALIGN(NBACKENDS * sizeof(LOCKCTL)); /* each ltable->ctl */ + size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ + + size += MAXALIGN(my_log2(NLOCKENTS) * sizeof(void *)); + size += MAXALIGN(sizeof(HHDR)); + size += nLockSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); + size += NLOCKENTS * /* XXX not multiple of BUCKET_ALLOC_INCR? */ + (MAXALIGN(sizeof(BUCKET_INDEX)) + + MAXALIGN(sizeof(LOCK))); /* contains hash key */ + + size += MAXALIGN(my_log2(NBACKENDS) * sizeof(void *)); + size += MAXALIGN(sizeof(HHDR)); + size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); + size += NBACKENDS * /* XXX not multiple of BUCKET_ALLOC_INCR? */ + (MAXALIGN(sizeof(BUCKET_INDEX)) + + MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */ + + return size; } /* ----------------- @@ -1354,7 +1399,7 @@ LockShmemSize() bool LockingDisabled() { - return LockingIsDisabled; + return LockingIsDisabled; } #ifdef DEADLOCK_DEBUG @@ -1364,67 +1409,71 @@ LockingDisabled() void DumpLocks() { - SHMEM_OFFSET location; - PROC *proc; - SHM_QUEUE *lockQueue; - int done; - XIDLookupEnt *xidLook = NULL; - XIDLookupEnt *tmp = NULL; - SHMEM_OFFSET end; - SPINLOCK masterLock; - int nLockTypes; - LOCK *lock; - int pid, count; - int tableId = 1; - LOCKTAB *ltable; - - pid = getpid(); - ShmemPIDLookup(pid,&location); - if (location == INVALID_OFFSET) - return; - proc = (PROC *) MAKE_PTR(location); - if (proc != MyProc) - return; - lockQueue = &proc->lockQueue; - - Assert (tableId < NumTables); - ltable = AllTables[tableId]; - if (!ltable) - return; - - nLockTypes = ltable->ctl->nLockTypes; - masterLock = ltable->ctl->masterLock; - - if (SHMQueueEmpty(lockQueue)) - return; - - SHMQueueFirst(lockQueue,(Pointer*)&xidLook,&xidLook->queue); - end = MAKE_OFFSET(lockQueue); - - LOCK_DUMP("DumpLocks", MyProc->waitLock, 0); - XID_PRINT("DumpLocks", xidLook); - - for (count=0;;) { - /* --------------------------- - * XXX Here we assume the shared memory queue is circular and - * that we know its internal structure. Should have some sort of - * macros to allow one to walk it. mer 20 July 1991 - * --------------------------- - */ - done = (xidLook->queue.next == end); - lock = (LOCK *) MAKE_PTR(xidLook->tag.lock); - - LOCK_DUMP("DumpLocks",lock,0); - - if (count++ > 2000) { - elog(NOTICE,"DumpLocks: xid loop detected, giving up"); - break; + SHMEM_OFFSET location; + PROC *proc; + SHM_QUEUE *lockQueue; + int done; + XIDLookupEnt *xidLook = NULL; + XIDLookupEnt *tmp = NULL; + SHMEM_OFFSET end; + SPINLOCK masterLock; + int nLockTypes; + LOCK *lock; + int pid, + count; + int tableId = 1; + LOCKTAB *ltable; + + pid = getpid(); + ShmemPIDLookup(pid, &location); + if (location == INVALID_OFFSET) + return; + proc = (PROC *) MAKE_PTR(location); + if (proc != MyProc) + return; + lockQueue = &proc->lockQueue; + + Assert(tableId < NumTables); + ltable = AllTables[tableId]; + if (!ltable) + return; + + nLockTypes = ltable->ctl->nLockTypes; + masterLock = ltable->ctl->masterLock; + + if (SHMQueueEmpty(lockQueue)) + return; + + SHMQueueFirst(lockQueue, (Pointer *) & xidLook, &xidLook->queue); + end = MAKE_OFFSET(lockQueue); + + LOCK_DUMP("DumpLocks", MyProc->waitLock, 0); + XID_PRINT("DumpLocks", xidLook); + + for (count = 0;;) + { + /* --------------------------- + * XXX Here we assume the shared memory queue is circular and + * that we know its internal structure. Should have some sort of + * macros to allow one to walk it. mer 20 July 1991 + * --------------------------- + */ + done = (xidLook->queue.next == end); + lock = (LOCK *) MAKE_PTR(xidLook->tag.lock); + + LOCK_DUMP("DumpLocks", lock, 0); + + if (count++ > 2000) + { + elog(NOTICE, "DumpLocks: xid loop detected, giving up"); + break; + } + + if (done) + break; + SHMQueueFirst(&xidLook->queue, (Pointer *) & tmp, &tmp->queue); + xidLook = tmp; } - - if (done) - break; - SHMQueueFirst(&xidLook->queue,(Pointer*)&tmp,&tmp->queue); - xidLook = tmp; - } } + #endif |