Lockless patterns: relaxed access and partial memory barriers
Lockless patterns: relaxed access and partial memory barriers
Posted Feb 27, 2021 23:11 UTC (Sat) by randomguy3 (subscriber, #71063)In reply to: Lockless patterns: relaxed access and partial memory barriers by PengZheng
Parent article: Lockless patterns: relaxed access and partial memory barriers
Posted Feb 27, 2021 23:18 UTC (Sat)
by randomguy3 (subscriber, #71063)
[Link] (6 responses)
Posted Feb 28, 2021 4:08 UTC (Sun)
by PengZheng (subscriber, #108006)
[Link] (5 responses)
smp_wmb();
copy.x = smp_load_acquire(&data.x) is a stronger form of
copy.x = READ_ONCE(data.x)
smp_wmb() makes both WRITE_ONCE(data.x, 567) and WRITE_ONCE(data.y, 890) into release operations, while smp_rmb() makes both READ_ONCE(data.y) and READ_ONCE(data.x) into acquire operations.
Posted Feb 28, 2021 4:19 UTC (Sun)
by PengZheng (subscriber, #108006)
[Link]
In thread 1 we have
In thread 2 we have
Thus WRITE_ONCE(sc, sc + 1); // sc == 3
Posted Feb 28, 2021 6:33 UTC (Sun)
by pbonzini (subscriber, #60935)
[Link] (3 responses)
This is not entirely correct, because barriers are bidirectional while store-release is unidirectional.
I tried putting this in CPPMEM:
and you are probably correct. The simplest fix is to use load-acquire/store-release for y as well. I'll write up a fix and ask our editor to update the article.
Posted Mar 1, 2021 3:00 UTC (Mon)
by PengZheng (subscriber, #108006)
[Link]
Thanks for correcting my misunderstanding. I read the following for a brief explanation of memory barriers:
Lockless patterns: relaxed access and partial memory barriers
Lockless patterns: relaxed access and partial memory barriers
Because smp_store_release(&data.x, 567) is a stronger form of
WRITE_ONCE(data.x, 567);
smp_rmb();
Lockless patterns: relaxed access and partial memory barriers
WRITE_ONCE(sc, sc + 1); // sc == 3
happens before
smp_wmb();
WRITE_ONCE(data.y, 890);
copy.y = READ_ONCE(data.y);
smp_rmb();
happens before READ_ONCE(sc)
happens before READ_ONCE(sc) in thread 2.
> "smp_store_release(&data.x, 567)" is a stronger form of "smp_wmb(); WRITE_ONCE(data.x, 567);"
Uh-oh
int main() {
atomic_int sc = 2;
atomic_int x = 123;
atomic_int y = 456;
{{{
{
sc.store(3, memory_order_relaxed);
x.store(567, memory_order_release);
y.store(890, memory_order_relaxed);
// sc.store(4, memory_order_release);
}
|||
{
sc.load(memory_order_acquire).readsvalue(2);
r1 = y.load(memory_order_relaxed);
r2 = x.load(memory_order_acquire).readsvalue(123);
}
}}};
return 0;
}
wmb, smp_wmb, and store-release
http://bruceblinn.com/linuxinfo/MemoryBarriers.html
