summaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/sinval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc/sinval.c')
-rw-r--r--src/backend/storage/ipc/sinval.c65
1 files changed, 38 insertions, 27 deletions
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c
index 1d43b1ead4..24506b9729 100644
--- a/src/backend/storage/ipc/sinval.c
+++ b/src/backend/storage/ipc/sinval.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.40 2001/08/26 16:56:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.41 2001/09/29 04:02:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,8 +23,6 @@
#include "miscadmin.h"
-SPINLOCK SInvalLock = (SPINLOCK) NULL;
-
/****************************************************************************/
/* CreateSharedInvalidationState() Initialize SI buffer */
/* */
@@ -33,7 +31,7 @@ SPINLOCK SInvalLock = (SPINLOCK) NULL;
void
CreateSharedInvalidationState(int maxBackends)
{
- /* SInvalLock must be initialized already, during spinlock init */
+ /* SInvalLock must be initialized already, during LWLock init */
SIBufferInit(maxBackends);
}
@@ -46,9 +44,9 @@ InitBackendSharedInvalidationState(void)
{
int flag;
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
flag = SIBackendInit(shmInvalBuffer);
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
if (flag < 0) /* unexpected problem */
elog(FATAL, "Backend cache invalidation initialization failed");
if (flag == 0) /* expected problem: MaxBackends exceeded */
@@ -64,9 +62,9 @@ SendSharedInvalidMessage(SharedInvalidationMessage *msg)
{
bool insertOK;
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
insertOK = SIInsertDataEntry(shmInvalBuffer, msg);
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
if (!insertOK)
elog(DEBUG, "SendSharedInvalidMessage: SI buffer overflow");
}
@@ -86,9 +84,25 @@ ReceiveSharedInvalidMessages(
for (;;)
{
- SpinAcquire(SInvalLock);
+ /*
+ * We can run SIGetDataEntry in parallel with other backends running
+ * SIGetDataEntry for themselves, since each instance will modify
+ * only fields of its own backend's ProcState, and no instance will
+ * look at fields of other backends' ProcStates. We express this
+ * by grabbing SInvalLock in shared mode. Note that this is not
+ * exactly the normal (read-only) interpretation of a shared lock!
+ * Look closely at the interactions before allowing SInvalLock to
+ * be grabbed in shared mode for any other reason!
+ *
+ * The routines later in this file that use shared mode are okay
+ * with this, because they aren't looking at the ProcState fields
+ * associated with SI message transfer; they only use the ProcState
+ * array as an easy way to find all the PROC structures.
+ */
+ LWLockAcquire(SInvalLock, LW_SHARED);
getResult = SIGetDataEntry(shmInvalBuffer, MyBackendId, &data);
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
+
if (getResult == 0)
break; /* nothing more to do */
if (getResult < 0)
@@ -108,9 +122,9 @@ ReceiveSharedInvalidMessages(
/* If we got any messages, try to release dead messages */
if (gotMessage)
{
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
SIDelExpiredDataEntries(shmInvalBuffer);
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
}
}
@@ -149,7 +163,7 @@ DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
ProcState *stateP = segP->procState;
int index;
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_SHARED);
for (index = 0; index < segP->lastBackend; index++)
{
@@ -170,7 +184,7 @@ DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
}
}
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
return result;
}
@@ -186,7 +200,7 @@ TransactionIdIsInProgress(TransactionId xid)
ProcState *stateP = segP->procState;
int index;
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_SHARED);
for (index = 0; index < segP->lastBackend; index++)
{
@@ -206,7 +220,7 @@ TransactionIdIsInProgress(TransactionId xid)
}
}
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
return result;
}
@@ -237,7 +251,7 @@ GetOldestXmin(bool allDbs)
result = GetCurrentTransactionId();
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_SHARED);
for (index = 0; index < segP->lastBackend; index++)
{
@@ -265,7 +279,7 @@ GetOldestXmin(bool allDbs)
}
}
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
return result;
}
@@ -298,7 +312,7 @@ GetSnapshotData(bool serializable)
snapshot->xmin = GetCurrentTransactionId();
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_SHARED);
/*
* There can be no more than lastBackend active transactions, so this
@@ -307,15 +321,12 @@ GetSnapshotData(bool serializable)
snapshot->xip = (TransactionId *)
malloc(segP->lastBackend * sizeof(TransactionId));
if (snapshot->xip == NULL)
- {
- SpinRelease(SInvalLock);
elog(ERROR, "Memory exhausted in GetSnapshotData");
- }
/*--------------------
* Unfortunately, we have to call ReadNewTransactionId() after acquiring
* SInvalLock above. It's not good because ReadNewTransactionId() does
- * SpinAcquire(XidGenLockId), but *necessary*. We need to be sure that
+ * LWLockAcquire(XidGenLock), but *necessary*. We need to be sure that
* no transactions exit the set of currently-running transactions
* between the time we fetch xmax and the time we finish building our
* snapshot. Otherwise we could have a situation like this:
@@ -373,7 +384,7 @@ GetSnapshotData(bool serializable)
if (serializable)
MyProc->xmin = snapshot->xmin;
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
/* Serializable snapshot must be computed before any other... */
Assert(TransactionIdIsValid(MyProc->xmin));
@@ -439,7 +450,7 @@ GetUndoRecPtr(void)
XLogRecPtr tempr;
int index;
- SpinAcquire(SInvalLock);
+ LWLockAcquire(SInvalLock, LW_SHARED);
for (index = 0; index < segP->lastBackend; index++)
{
@@ -458,7 +469,7 @@ GetUndoRecPtr(void)
}
}
- SpinRelease(SInvalLock);
+ LWLockRelease(SInvalLock);
return (urec);
}
@@ -470,7 +481,7 @@ GetUndoRecPtr(void)
* knows that the backend isn't going to go away, so we do not bother with
* locking.
*/
-struct proc *
+struct PROC *
BackendIdGetProc(BackendId procId)
{
SISeg *segP = shmInvalBuffer;