Relaxed C ++ 11 memory model ordering

I tested the relaxed semantics of ordering the C ++ 11 memory model on x64, and I was told that on x86 / 64 there is only save / reorder the load, so I wrote the following program to check relaxed ordering.

Ideally, if there is a reordering (what it does), then my program should fall into the case of getting "g_a == g_b == 0", but I tested it for a long time and never received the expected results, could someone help explain why? thanks.

[update]

Sorry to forget to mention the compiler I used, the following code will not work when compiling with g ++ 4.8.3 on Linux x86 / 64. thanks to @Mat reminder, I will then try to compile it with clang ++ 3.4.2, this time I saw reordering, so it could be a bug in g ++.

#include <iostream> #include <thread> #include <atomic> using namespace std; atomic<int> g_a, g_b; atomic<int> g_x, g_y; memory_order order = memory_order_relaxed; void bar1() { register int t = 0; g_x.store(42, order); t = g_y.load(order); g_a = t; } void bar2() { register int t = 0; g_y.store(24, order); t = g_x.load(order); g_b = t; } int main() { for (int i = 0; i < 1000000; ++i) { g_a = 0; g_b = 0; g_x = 0; g_y =0; thread t1(&bar1); thread t2(&bar2); t1.join(); t2.join(); if (g_a.load(order) == 0 && g_b.load(order) == 0) { cout << "g_a == g_b == 0" << endl; } } } 
+5
source share
1 answer

In order to be able to generate an assembly with the correct memory barriers, at compile time you need to know the C ++ order parameters.

The problem is the following statement:

 memory_order order = memory_order_relaxed; 

This is not a compile-time constant, so gcc is going to accept memory_order_seq_cst and insert the mfence :

 Dump of assembler code for function bar1(): 0x0000000000400fc0 <+0>: movl $0x2a,0x20128a(%rip) # 0x602254 <g_x> 0x0000000000400fca <+10>: mfence 0x0000000000400fcd <+13>: mov 0x20127d(%rip),%eax # 0x602250 <g_y> 

If you change it to:

 constexpr memory_order order = memory_order_relaxed; 

The relaxed parameter will take effect, and mfence will disappear:

 Dump of assembler code for function bar1(): 0x0000000000400fc0 <+0>: movl $0x2a,0x201286(%rip) # 0x602250 <g_x> 0x0000000000400fca <+10>: mov 0x20127c(%rip),%eax # 0x60224c <g_y> 

If you compile with -O3 optimization, running the binary now displays the reorder.

+3
source

Source: https://habr.com/ru/post/1207505/


All Articles