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
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 27, 2021 23:18 UTC (Sat) by randomguy3 (subscriber, #71063) [Link] (6 responses)
Lockless patterns: relaxed access and partial memory barriers
Posted Feb 28, 2021 4:08 UTC (Sun)
by PengZheng (subscriber, #108006)
[Link] (5 responses)
Posted Feb 28, 2021 4:08 UTC (Sun) by PengZheng (subscriber, #108006) [Link] (5 responses)
Because smp_store_release(&data.x, 567) is a stronger form of
smp_wmb();
WRITE_ONCE(data.x, 567);
copy.x = smp_load_acquire(&data.x) is a stronger form of
copy.x = READ_ONCE(data.x)
smp_rmb();
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.
Lockless patterns: relaxed access and partial memory barriers
Posted Feb 28, 2021 4:19 UTC (Sun)
by PengZheng (subscriber, #108006)
[Link]
Posted Feb 28, 2021 4:19 UTC (Sun) by PengZheng (subscriber, #108006) [Link]
In thread 1 we have
WRITE_ONCE(sc, sc + 1); // sc == 3
happens before
smp_wmb();
WRITE_ONCE(data.y, 890);
In thread 2 we have
copy.y = READ_ONCE(data.y);
smp_rmb();
happens before READ_ONCE(sc)
Thus WRITE_ONCE(sc, sc + 1); // sc == 3
happens before READ_ONCE(sc) in thread 2.
Uh-oh
Posted Feb 28, 2021 6:33 UTC (Sun)
by pbonzini (subscriber, #60935)
[Link] (3 responses)
> "smp_store_release(&data.x, 567)" is a stronger form of "smp_wmb(); WRITE_ONCE(data.x, 567);"
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:
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; }
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.
wmb, smp_wmb, and store-release
Posted Mar 1, 2021 3:00 UTC (Mon)
by PengZheng (subscriber, #108006)
[Link]
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:
http://bruceblinn.com/linuxinfo/MemoryBarriers.html