1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-13 16:22:44 +03:00

Modify sinval so that InvalidateSharedInvalid() does not hold

the SInval spinlock while it is calling the passed invalFunction or
resetFunction.  This is necessary to avoid deadlock with lmgr change;
InvalidateSharedInvalid can be called recursively now.  It should be
a good performance improvement anyway --- holding a spinlock for more
than a very short interval is a no-no.
This commit is contained in:
Tom Lane
1999-09-04 18:36:45 +00:00
parent ae01c7f5bb
commit 8add6d71cf
3 changed files with 114 additions and 93 deletions

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.16 1999/07/15 22:39:49 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.17 1999/09/04 18:36:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,9 +21,9 @@
#include "storage/sinval.h"
#include "storage/sinvaladt.h"
extern SISeg *shmInvalBuffer; /* the shared buffer segment, set by */
/* SISegmentAttach() */
extern SISeg *shmInvalBuffer; /* the shared buffer segment, set by
* SISegmentAttach()
*/
extern BackendId MyBackendId;
extern BackendTag MyBackendTag;
@@ -127,21 +127,20 @@ RegisterSharedInvalid(int cacheId, /* XXX */
ItemPointerSetInvalid(&newInvalid.pointerData);
SpinAcquire(SInvalLock);
if (!SISetDataEntry(shmInvalBuffer, &newInvalid))
while (!SISetDataEntry(shmInvalBuffer, &newInvalid))
{
/* buffer full */
/* release a message, mark process cache states to be invalid */
SISetProcStateInvalid(shmInvalBuffer);
if (!SIDelDataEntry(shmInvalBuffer))
if (!SIDelDataEntries(shmInvalBuffer, 1))
{
/* inconsistent buffer state -- shd never happen */
SpinRelease(SInvalLock);
elog(FATAL, "RegisterSharedInvalid: inconsistent buffer state");
}
/* write again */
SISetDataEntry(shmInvalBuffer, &newInvalid);
/* loop around to try write again */
}
SpinRelease(SInvalLock);
}
@@ -157,13 +156,41 @@ RegisterSharedInvalid(int cacheId, /* XXX */
/* should be called by a backend */
/****************************************************************************/
void
InvalidateSharedInvalid(void (*invalFunction) (),
void (*resetFunction) ())
InvalidateSharedInvalid(void (*invalFunction) (),
void (*resetFunction) ())
{
SpinAcquire(SInvalLock);
SIReadEntryData(shmInvalBuffer, MyBackendId,
invalFunction, resetFunction);
SharedInvalidData data;
int getResult;
bool gotMessage = false;
SIDelExpiredDataEntries(shmInvalBuffer);
SpinRelease(SInvalLock);
for (;;)
{
SpinAcquire(SInvalLock);
getResult = SIGetDataEntry(shmInvalBuffer, MyBackendId, &data);
SpinRelease(SInvalLock);
if (getResult == 0)
break; /* nothing more to do */
if (getResult < 0)
{
/* got a reset message */
elog(NOTICE, "InvalidateSharedInvalid: cache state reset");
resetFunction();
}
else
{
/* got a normal data message */
invalFunction(data.cacheId,
data.hashIndex,
&data.pointerData);
}
gotMessage = true;
}
/* If we got any messages, try to release dead messages */
if (gotMessage)
{
SpinAcquire(SInvalLock);
SIDelExpiredDataEntries(shmInvalBuffer);
SpinRelease(SInvalLock);
}
}