, .
, , , - ( , , - , ). , /, Jeff Preshing.
check-then-fence №2 , . .
, g++ 4.8.1 x64 (Linux) , , . , , x86 (-64) , (x86 ).
ARM, , ( gcc.godbolt.com -O3 -DNDEBUG
):
while (!poll1());
:
.L25:
ldr r0, [r2]
movw r3, #:lower16:.LANCHOR0
dmb sy
movt r3, #:upper16:.LANCHOR0
cmp r0, #1
bne .L25
while (!poll2());
:
.L29:
ldr r0, [r2]
movw r3, #:lower16:.LANCHOR0
movt r3, #:upper16:.LANCHOR0
cmp r0, #1
bne .L29
dmb sy
, , (dmb
) - poll1
, - poll2
. , poll2
:-) ( , , , , .)
ARM64 , /, (ldar
→ load-).
while (!poll1());
:
.L16:
ldar w0, [x1]
cmp w0, 1
bne .L16
while (!poll2());
:
.L24:
ldr w0, [x1]
cmp w0, 1
bne .L24
dmb ishld
, poll2
, , , poll1
.
, , , , , . poll1
poll2
, -, , , , (.. , , , () poll1
, poll2
). , , - poll1
, poll2
.
, , , poll2
, poll1
, , , (, , ).
( ) :
#include <atomic>
#include <thread>
#include <cstdio>
int sharedState;
std::atomic<int> flag(0);
bool poll1() {
return (flag.load(std::memory_order_acquire) == 1);
}
bool poll2() {
int snapshot = flag.load(std::memory_order_relaxed);
if (snapshot == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
return false;
}
void __attribute__((noinline)) threadFunc()
{
while (!poll2());
std::printf("%d\n", sharedState);
}
int main(int argc, char** argv)
{
std::thread t(threadFunc);
sharedState = argc;
flag.store(1, std::memory_order_release);
t.join();
return 0;
}