sinval-fastpath.patch
application/octet-stream
Filename: sinval-fastpath.patch
Type: application/octet-stream
Part: 0
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index 4f446aa..7d60f31 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -499,11 +499,31 @@ SIGetDataEntries(SharedInvalidationMessage *data, int datasize)
int max;
int n;
- LWLockAcquire(SInvalReadLock, LW_SHARED);
-
segP = shmInvalBuffer;
stateP = &segP->procState[MyBackendId - 1];
+ /*
+ * Before starting to take locks, do a quick, unlocked test to see whether
+ * there can possibly be anything to read. On a multiprocessor system,
+ * it's possible these loads could migrate backwards and occur before we
+ * actually enter this function, so we might miss a sinval message that
+ * was just added by some other processor. But they can't migrate
+ * backwards over a preceding lock acquisition, so it should be OK. If
+ * we haven't acquired a lock preventing against further relevant
+ * invalidations, any such occurrence is not much different than if the
+ * invalidation had arrived slightly later in the first place.
+ *
+ * It's important that we don't use the value read here to actually
+ * read from the queue. On machines with weak memory ordering, the
+ * maxMsgNum bump could become visible before the queue entries themselves.
+ * But the locking below will take care of that before rereading the
+ * value.
+ */
+ if (stateP->nextMsgNum == segP->maxMsgNum && !stateP->resetState)
+ return 0;
+
+ LWLockAcquire(SInvalReadLock, LW_SHARED);
+
/* Fetch current value of maxMsgNum using spinlock */
{
/* use volatile pointer to prevent code rearrangement */