Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 14e8803

Browse files
committed
Add barriers to the latch code.
Since their introduction latches have required barriers in SetLatch and ResetLatch - but when they were introduced there wasn't any barrier abstraction. Instead latches were documented to rely on the callsites to provide barrier semantics. Now that the barrier support looks halfway complete, add the necessary barriers to both latch implementations. Also remove a now superflous lock acquisition from syncrep.c and a superflous (and insufficient) barrier from freelist.c. There might be other cases that can now be simplified, but those are the only ones I've seen on a quick scan. We might want to backpatch this at some later point, but right now the barrier infrastructure in the backbranches isn't totally on par with master. Discussion: 20150112154026.GB2092@awork2.anarazel.de
1 parent 4bad60e commit 14e8803

File tree

5 files changed

+23
-27
lines changed

5 files changed

+23
-27
lines changed

src/backend/port/unix_latch.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "miscadmin.h"
5252
#include "portability/instr_time.h"
5353
#include "postmaster/postmaster.h"
54+
#include "storage/barrier.h"
5455
#include "storage/latch.h"
5556
#include "storage/pmsignal.h"
5657
#include "storage/shmem.h"
@@ -515,12 +516,11 @@ SetLatch(volatile Latch *latch)
515516
pid_t owner_pid;
516517

517518
/*
518-
* XXX there really ought to be a memory barrier operation right here, to
519-
* ensure that any flag variables we might have changed get flushed to
520-
* main memory before we check/set is_set. Without that, we have to
521-
* require that callers provide their own synchronization for machines
522-
* with weak memory ordering (see latch.h).
519+
* The memory barrier has be to be placed here to ensure that any flag
520+
* variables possibly changed by this process have been flushed to main
521+
* memory, before we check/set is_set.
523522
*/
523+
pg_memory_barrier();
524524

525525
/* Quick exit if already set */
526526
if (latch->is_set)
@@ -574,14 +574,12 @@ ResetLatch(volatile Latch *latch)
574574
latch->is_set = false;
575575

576576
/*
577-
* XXX there really ought to be a memory barrier operation right here, to
578-
* ensure that the write to is_set gets flushed to main memory before we
577+
* Ensure that the write to is_set gets flushed to main memory before we
579578
* examine any flag variables. Otherwise a concurrent SetLatch might
580579
* falsely conclude that it needn't signal us, even though we have missed
581580
* seeing some flag updates that SetLatch was supposed to inform us of.
582-
* For the moment, callers must supply their own synchronization of flag
583-
* variables (see latch.h).
584581
*/
582+
pg_memory_barrier();
585583
}
586584

587585
/*

src/backend/port/win32_latch.c

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "miscadmin.h"
2828
#include "portability/instr_time.h"
2929
#include "postmaster/postmaster.h"
30+
#include "storage/barrier.h"
3031
#include "storage/latch.h"
3132
#include "storage/pmsignal.h"
3233
#include "storage/shmem.h"
@@ -293,6 +294,13 @@ SetLatch(volatile Latch *latch)
293294
{
294295
HANDLE handle;
295296

297+
/*
298+
* The memory barrier has be to be placed here to ensure that any flag
299+
* variables possibly changed by this process have been flushed to main
300+
* memory, before we check/set is_set.
301+
*/
302+
pg_memory_barrier();
303+
296304
/* Quick exit if already set */
297305
if (latch->is_set)
298306
return;
@@ -325,4 +333,12 @@ ResetLatch(volatile Latch *latch)
325333
Assert(latch->owner_pid == MyProcPid);
326334

327335
latch->is_set = false;
336+
337+
/*
338+
* Ensure that the write to is_set gets flushed to main memory before we
339+
* examine any flag variables. Otherwise a concurrent SetLatch might
340+
* falsely conclude that it needn't signal us, even though we have missed
341+
* seeing some flag updates that SetLatch was supposed to inform us of.
342+
*/
343+
pg_memory_barrier();
328344
}

src/backend/replication/syncrep.c

-10
Original file line numberDiff line numberDiff line change
@@ -172,20 +172,10 @@ SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
172172
* walsender changes the state to SYNC_REP_WAIT_COMPLETE, it will
173173
* never update it again, so we can't be seeing a stale value in that
174174
* case.
175-
*
176-
* Note: on machines with weak memory ordering, the acquisition of the
177-
* lock is essential to avoid race conditions: we cannot be sure the
178-
* sender's state update has reached main memory until we acquire the
179-
* lock. We could get rid of this dance if SetLatch/ResetLatch
180-
* contained memory barriers.
181175
*/
182176
syncRepState = MyProc->syncRepState;
183177
if (syncRepState == SYNC_REP_WAITING)
184-
{
185-
LWLockAcquire(SyncRepLock, LW_SHARED);
186178
syncRepState = MyProc->syncRepState;
187-
LWLockRelease(SyncRepLock);
188-
}
189179
if (syncRepState == SYNC_REP_WAIT_COMPLETE)
190180
break;
191181

src/backend/storage/buffer/freelist.c

-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ StrategyGetBuffer(BufferAccessStrategy strategy)
214214
{
215215
/* reset bgwprocno first, before setting the latch */
216216
StrategyControl->bgwprocno = -1;
217-
pg_write_barrier();
218217

219218
/*
220219
* Not acquiring ProcArrayLock here which is slightly icky. It's

src/include/storage/latch.h

-7
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@
5757
* SetLatch *after* that. SetLatch is designed to return quickly if the
5858
* latch is already set.
5959
*
60-
* Presently, when using a shared latch for interprocess signalling, the
61-
* flag variable(s) set by senders and inspected by the wait loop must
62-
* be protected by spinlocks or LWLocks, else it is possible to miss events
63-
* on machines with weak memory ordering (such as PPC). This restriction
64-
* will be lifted in future by inserting suitable memory barriers into
65-
* SetLatch and ResetLatch.
66-
*
6760
* On some platforms, signals will not interrupt the latch wait primitive
6861
* by themselves. Therefore, it is critical that any signal handler that
6962
* is meant to terminate a WaitLatch wait calls SetLatch.

0 commit comments

Comments
 (0)