aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/lmgr.c83
-rw-r--r--src/backend/storage/lmgr/lock.c50
-rw-r--r--src/include/storage/lock.h13
3 files changed, 79 insertions, 67 deletions
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 716ccf29035..b7c5903c8a1 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.74 2005/05/19 21:35:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.75 2005/05/29 22:45:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,24 +136,28 @@ void
LockRelation(Relation relation, LOCKMODE lockmode)
{
LOCKTAG tag;
+ LockAcquireResult res;
SET_LOCKTAG_RELATION(tag,
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
/*
* Check to see if the relcache entry has been invalidated while we
* were waiting to lock it. If so, rebuild it, or ereport() trying.
* Increment the refcount to ensure that RelationFlushRelation will
- * rebuild it and not just delete it.
+ * rebuild it and not just delete it. We can skip this if the lock
+ * was already held, however.
*/
- RelationIncrementReferenceCount(relation);
- AcceptInvalidationMessages();
- RelationDecrementReferenceCount(relation);
+ if (res != LOCKACQUIRE_ALREADY_HELD)
+ {
+ RelationIncrementReferenceCount(relation);
+ AcceptInvalidationMessages();
+ RelationDecrementReferenceCount(relation);
+ }
}
/*
@@ -169,24 +173,31 @@ bool
ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
{
LOCKTAG tag;
+ LockAcquireResult res;
SET_LOCKTAG_RELATION(tag,
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, true))
+ res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, true);
+
+ if (res == LOCKACQUIRE_NOT_AVAIL)
return false;
/*
* Check to see if the relcache entry has been invalidated while we
* were waiting to lock it. If so, rebuild it, or ereport() trying.
* Increment the refcount to ensure that RelationFlushRelation will
- * rebuild it and not just delete it.
+ * rebuild it and not just delete it. We can skip this if the lock
+ * was already held, however.
*/
- RelationIncrementReferenceCount(relation);
- AcceptInvalidationMessages();
- RelationDecrementReferenceCount(relation);
+ if (res != LOCKACQUIRE_ALREADY_HELD)
+ {
+ RelationIncrementReferenceCount(relation);
+ AcceptInvalidationMessages();
+ RelationDecrementReferenceCount(relation);
+ }
return true;
}
@@ -225,9 +236,8 @@ LockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
- if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, InvalidTransactionId,
+ lockmode, false);
}
/*
@@ -262,9 +272,8 @@ LockRelationForExtension(Relation relation, LOCKMODE lockmode)
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
@@ -298,9 +307,8 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
relation->rd_lockInfo.lockRelId.relId,
blkno);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
@@ -319,8 +327,8 @@ ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
relation->rd_lockInfo.lockRelId.relId,
blkno);
- return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, true);
+ return (LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, true) != LOCKACQUIRE_NOT_AVAIL);
}
/*
@@ -357,9 +365,8 @@ LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
ItemPointerGetBlockNumber(tid),
ItemPointerGetOffsetNumber(tid));
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
@@ -393,9 +400,8 @@ XactLockTableInsert(TransactionId xid)
SET_LOCKTAG_TRANSACTION(tag, xid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- ExclusiveLock, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ ExclusiveLock, false);
}
/*
@@ -441,8 +447,9 @@ XactLockTableWait(TransactionId xid)
SET_LOCKTAG_TRANSACTION(tag, xid);
- if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, myxid,
+ ShareLock, false);
+
LockRelease(LockTableId, &tag, myxid, ShareLock);
if (!TransactionIdIsInProgress(xid))
@@ -479,9 +486,8 @@ LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
objid,
objsubid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
@@ -519,9 +525,8 @@ LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
objid,
objsubid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index d7180d7c1fd..6f02c0720e2 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.153 2005/05/29 04:23:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.154 2005/05/29 22:45:02 tgl Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
@@ -160,8 +160,8 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
static void RemoveLocalLock(LOCALLOCK *locallock);
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
-static int WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
- ResourceOwner owner);
+static void WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
+ ResourceOwner owner);
static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
int *myHolding);
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
@@ -377,11 +377,14 @@ LockMethodTableRename(LOCKMETHODID lockmethodid)
* LockAcquire -- Check for lock conflicts, sleep if conflict found,
* set lock if/when no conflicts.
*
- * Returns: TRUE if lock was acquired, FALSE otherwise. Note that
- * a FALSE return is to be expected if dontWait is TRUE;
- * but if dontWait is FALSE, only a parameter error can cause
- * a FALSE return. (XXX probably we should just ereport on parameter
- * errors, instead of conflating this with failure to acquire lock?)
+ * Returns one of:
+ * LOCKACQUIRE_NOT_AVAIL lock not available, and dontWait=true
+ * LOCKACQUIRE_OK lock successfully acquired
+ * LOCKACQUIRE_ALREADY_HELD incremented count for lock already held
+ *
+ * In the normal case where dontWait=false and the caller doesn't need to
+ * distinguish a freshly acquired lock from one already taken earlier in
+ * this same transaction, there is no need to examine the return value.
*
* Side Effects: The lock is acquired and recorded in lock tables.
*
@@ -416,8 +419,7 @@ LockMethodTableRename(LOCKMETHODID lockmethodid)
*
* DZ - 22 Nov 1997
*/
-
-bool
+LockAcquireResult
LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait)
{
@@ -447,10 +449,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- {
- elog(WARNING, "bad lock table id: %d", lockmethodid);
- return FALSE;
- }
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
/* Session locks and user locks are not transactional */
if (xid != InvalidTransactionId &&
@@ -507,7 +506,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
if (locallock->nLocks > 0)
{
GrantLockLocal(locallock, owner);
- return TRUE;
+ return LOCKACQUIRE_ALREADY_HELD;
}
/*
@@ -669,7 +668,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
GrantLockLocal(locallock, owner);
PROCLOCK_PRINT("LockAcquire: my other XID owning", proclock);
LWLockRelease(masterLock);
- return TRUE;
+ return LOCKACQUIRE_ALREADY_HELD;
}
/*
@@ -696,8 +695,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
/*
* We can't acquire the lock immediately. If caller specified no
- * blocking, remove useless table entries and return FALSE without
- * waiting.
+ * blocking, remove useless table entries and return NOT_AVAIL
+ * without waiting.
*/
if (dontWait)
{
@@ -720,7 +719,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
LWLockRelease(masterLock);
if (locallock->nLocks == 0)
RemoveLocalLock(locallock);
- return FALSE;
+ return LOCKACQUIRE_NOT_AVAIL;
}
/*
@@ -740,7 +739,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
/*
* Sleep till someone wakes me up.
*/
- status = WaitOnLock(lockmethodid, locallock, owner);
+ WaitOnLock(lockmethodid, locallock, owner);
/*
* NOTE: do not do any material change of state between here and
@@ -759,7 +758,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
/* Should we retry ? */
LWLockRelease(masterLock);
- return FALSE;
+ elog(ERROR, "LockAcquire failed");
}
PROCLOCK_PRINT("LockAcquire: granted", proclock);
LOCK_PRINT("LockAcquire: granted", lock, lockmode);
@@ -767,7 +766,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
LWLockRelease(masterLock);
- return status == STATUS_OK;
+ return LOCKACQUIRE_OK;
}
/*
@@ -1091,7 +1090,7 @@ GrantAwaitedLock(void)
*
* The locktable's masterLock must be held at entry.
*/
-static int
+static void
WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
ResourceOwner owner)
{
@@ -1159,7 +1158,6 @@ WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
LOCK_PRINT("WaitOnLock: wakeup on lock",
locallock->lock, locallock->tag.mode);
- return STATUS_OK;
}
/*
@@ -1247,7 +1245,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- elog(ERROR, "bad lock method: %d", lockmethodid);
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
/*
* Find the LOCALLOCK entry for this lock and lockmode
@@ -1397,7 +1395,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- elog(ERROR, "bad lock method: %d", lockmethodid);
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
numLockModes = lockMethodTable->numLockModes;
masterLock = lockMethodTable->masterLock;
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 7ee0bf310e9..63b69e41250 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.86 2005/05/19 23:30:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.87 2005/05/29 22:45:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -348,6 +348,15 @@ typedef struct
} LockData;
+/* Result codes for LockAcquire() */
+typedef enum
+{
+ LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
+ LOCKACQUIRE_OK, /* lock successfully acquired */
+ LOCKACQUIRE_ALREADY_HELD /* incremented count for lock already held */
+} LockAcquireResult;
+
+
/*
* function prototypes
*/
@@ -357,7 +366,7 @@ extern LOCKMETHODID LockMethodTableInit(const char *tabName,
const LOCKMASK *conflictsP,
int numModes, int maxBackends);
extern LOCKMETHODID LockMethodTableRename(LOCKMETHODID lockmethodid);
-extern bool LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
+extern LockAcquireResult LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait);
extern bool LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode);