Skip to content

Commit fce3a71

Browse files
committed
Prevent potentially hazardous compiler/cpu reordering during lwlock release.
In LWLockRelease() (and in 9.4+ LWLockUpdateVar()) we release enqueued waiters using PGSemaphoreUnlock(). As there are other sources of such unlocks backends only wake up if MyProc->lwWaiting is set to false; which is only done in the aforementioned functions. Before this commit there were dangers because the store to lwWaitLink could become visible before the store to lwWaitLink. This could both happen due to compiler reordering (on most compilers) and on some platforms due to the CPU reordering stores. The possible consequence of this is that a backend stops waiting before lwWaitLink is set to NULL. If that backend then tries to acquire another lock and has to wait there the list could become corrupted once the lwWaitLink store is finally performed. Add a write memory barrier to prevent that issue. Unfortunately the barrier support has been only added in 9.2. Given that the issue has not knowingly been observed in praxis it seems sufficient to prohibit compiler reordering using volatile for 9.0 and 9.1. Actual problems due to compiler reordering are more likely anyway. Discussion: 20140210134625.GA15246@awork2.anarazel.de
1 parent 0c54cb0 commit fce3a71

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

src/backend/storage/lmgr/lwlock.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -643,12 +643,22 @@ LWLockRelease(LWLockId lockid)
643643
*/
644644
while (head != NULL)
645645
{
646+
/*
647+
* Try to guarantee that lwWaiting being unset only becomes visible
648+
* once the unlink from the link has completed. Otherwise the target
649+
* backend could be woken up for other reason and enqueue for a new
650+
* lock - if that happens before the list unlink happens, the list
651+
* would end up being corrupted. In later releases we can rely on
652+
* barriers, but < 9.2 doesn't yet have them - so just use volatile.
653+
*/
654+
volatile PGPROC *p;
655+
646656
LOG_LWDEBUG("LWLockRelease", lockid, "release waiter");
647-
proc = head;
648-
head = proc->lwWaitLink;
649-
proc->lwWaitLink = NULL;
650-
proc->lwWaiting = false;
651-
PGSemaphoreUnlock(&proc->sem);
657+
p = head;
658+
head = p->lwWaitLink;
659+
p->lwWaitLink = NULL;
660+
p->lwWaiting = false;
661+
PGSemaphoreUnlock((PGSemaphore) &p->sem);
652662
}
653663

654664
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy