diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-01-30 20:56:35 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-01-31 00:09:30 +0200 |
commit | 82d4b262d9614958da38003cdc9d56915d9bcda0 (patch) | |
tree | ccb9a1ba24174d444884fd35f979c8fca10dd1f6 /src | |
parent | 82e83f46a2ed311c6e7536f607f73a6f2a1d7dea (diff) | |
download | postgresql-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.c | 25 |
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; |