summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-01-30 20:56:35 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-01-31 00:09:30 +0200
commit82d4b262d9614958da38003cdc9d56915d9bcda0 (patch)
treeccb9a1ba24174d444884fd35f979c8fca10dd1f6 /src
parent82e83f46a2ed311c6e7536f607f73a6f2a1d7dea (diff)
downloadpostgresql-82d4b262d9614958da38003cdc9d56915d9bcda0.tar.gz
Fix bug in the new wait-until-lwlock-is-free mechanism.
If there was a wait-until-free process in the head of the wait queue, followed by an exclusive locker, the exclusive locker was not be woken up as it should.
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/lwlock.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index bee35b8c1c..6511faf985 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -754,23 +754,31 @@ LWLockRelease(LWLockId lockid)
if (lock->exclusive == 0 && lock->shared == 0 && lock->releaseOK)
{
/*
- * Remove the to-be-awakened PGPROCs from the queue. If the front
- * waiter wants exclusive lock, awaken him only. Otherwise awaken
- * as many waiters as want shared access (or just want to be
- * woken up when the lock becomes free without acquiring it,
- * ie. LWLockWaitUntilFree).
+ * Remove the to-be-awakened PGPROCs from the queue.
*/
bool releaseOK = true;
proc = head;
+
+ /*
+ * First wake up any backends that want to be woken up without
+ * acquiring the lock.
+ */
+ while (proc->lwWaitMode == LW_WAIT_UNTIL_FREE && proc->lwWaitLink)
+ proc = proc->lwWaitLink;
+
+ /*
+ * If the front waiter wants exclusive lock, awaken him only.
+ * Otherwise awaken as many waiters as want shared access.
+ */
if (proc->lwWaitMode != LW_EXCLUSIVE)
{
while (proc->lwWaitLink != NULL &&
proc->lwWaitLink->lwWaitMode != LW_EXCLUSIVE)
{
- proc = proc->lwWaitLink;
if (proc->lwWaitMode != LW_WAIT_UNTIL_FREE)
releaseOK = false;
+ proc = proc->lwWaitLink;
}
}
/* proc is now the last PGPROC to be released */
@@ -778,9 +786,8 @@ LWLockRelease(LWLockId lockid)
proc->lwWaitLink = NULL;
/*
* Prevent additional wakeups until retryer gets to run. Backends
- * that are just waiting for the lock to become free don't prevent
- * wakeups, because they might decide that they don't want the
- * lock, after all.
+ * that are just waiting for the lock to become free don't retry
+ * automatically.
*/
if (proc->lwWaitMode != LW_WAIT_UNTIL_FREE)
releaseOK = false;