title: C++11 (g++ thread sanitized) Ordering nonatomic operations with atomics (false positive?)
body: <p>I am experimenting with g++ and thread sanitizer and I think I am getting false positives. Is this true, or am I making some big mistake?</p>
  
  <p>Program (cut&amp;paste from Anthony Williams: C++ Concurrency in Action, page 145, listing 5.13)</p>
  
  <pre><code>#include &lt;atomic&gt;
  #include &lt;thread&gt;
  #include &lt;assert.h&gt;
  bool x=false;
  std::atomic&lt;bool&gt; y;
  std::atomic&lt;int&gt; z;
  void write_x_then_y()
  {
    x=true;
    std::atomic_thread_fence(std::memory_order_release);
    y.store(true,std::memory_order_relaxed);
  }
  void read_y_then_x()
  {
    while(!y.load(std::memory_order_relaxed));
    std::atomic_thread_fence(std::memory_order_acquire);
    if(x)
      ++z;
  }
  int main()
  {
    x=false;
    y=false;
    z=0;
    std::thread a(write_x_then_y);
    std::thread b(read_y_then_x);
    a.join();
    b.join();
    assert(z.load()!=0);
  }
  </code></pre>
  
  <p>Compiled with:</p>
  
  <pre><code>g++ -o a -g -Og -pthread a.cpp -fsanitize=thread
  </code></pre>
  
  <p>g++ version</p>
  
  <pre><code>~/build/px&gt; g++ -v
  Using built-in specs.
  COLLECT_GCC=g++
  COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.1.1/lto-wrapper
  Target: x86_64-redhat-linux
  Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
  Thread model: posix
  gcc version 6.1.1 20160621 (Red Hat 6.1.1-3) (GCC)
  </code></pre>
  
  <p>I am getting:</p>
  
  <pre><code>~/build/px&gt; ./a
  ==================
  WARNING: ThreadSanitizer: data race (pid=13794)
    Read of size 1 at 0x000000602151 by thread T2:
      #0 read_y_then_x() /home/ostri/build/px/a.cpp:17 (a+0x000000401014)
      #1 void std::_Bind_simple&lt;void (*())()&gt;::_M_invoke&lt;&gt;(std::_Index_tuple&lt;&gt;) /usr/include/c++/6.1.1/functional:1400 (a+0x000000401179)
      #2 std::_Bind_simple&lt;void (*())()&gt;::operator()() /usr/include/c++/6.1.1/functional:1389 (a+0x000000401179)
      #3 std::thread::_State_impl&lt;std::_Bind_simple&lt;void (*())()&gt; &gt;::_M_run() /usr/include/c++/6.1.1/thread:196 (a+0x000000401179)
      #4 &lt;null&gt; &lt;null&gt; (libstdc++.so.6+0x0000000baaae)
  
    Previous write of size 1 at 0x000000602151 by thread T1:
      #0 write_x_then_y() /home/ostri/build/px/a.cpp:9 (a+0x000000400fbd)
      #1 void std::_Bind_simple&lt;void (*())()&gt;::_M_invoke&lt;&gt;(std::_Index_tuple&lt;&gt;) /usr/include/c++/6.1.1/functional:1400 (a+0x000000401179)
      #2 std::_Bind_simple&lt;void (*())()&gt;::operator()() /usr/include/c++/6.1.1/functional:1389 (a+0x000000401179)
      #3 std::thread::_State_impl&lt;std::_Bind_simple&lt;void (*())()&gt; &gt;::_M_run() /usr/include/c++/6.1.1/thread:196 (a+0x000000401179)
      #4 &lt;null&gt; &lt;null&gt; (libstdc++.so.6+0x0000000baaae)
  
    Location is global 'x' of size 1 at 0x000000602151 (a+0x000000602151)
  
    Thread T2 (tid=13797, running) created by main thread at:
      #0 pthread_create &lt;null&gt; (libtsan.so.0+0x000000028380)
      #1 std::thread::_M_start_thread(std::unique_ptr&lt;std::thread::_State, std::default_delete&lt;std::thread::_State&gt; &gt;, void (*)()) &lt;null&gt; (libstdc++.so.6+0x0000000badc4)
      #2 main /home/ostri/build/px/a.cpp:26 (a+0x000000401097)
  
    Thread T1 (tid=13796, finished) created by main thread at:
      #0 pthread_create &lt;null&gt; (libtsan.so.0+0x000000028380)
      #1 std::thread::_M_start_thread(std::unique_ptr&lt;std::thread::_State, std::default_delete&lt;std::thread::_State&gt; &gt;, void (*)()) &lt;null&gt; (libstdc++.so.6+0x0000000badc4)
      #2 main /home/ostri/build/px/a.cpp:25 (a+0x00000040108a)
  
  SUMMARY: ThreadSanitizer: data race /home/ostri/build/px/a.cpp:17 in read_y_then_x()
  ==================
  ThreadSanitizer: reported 1 warnings
  </code></pre>
  
  <p>I got this warning in more complex program, and I've thought it is my bug, but now even a "school book program" displays the same behaviour.
  Is it (i.e. some compiler switch is missing) me or g++?</p>
  
  <p><strong>UPDATED</strong>
  Taken from <a href="https://stackoverflow.com/questions/37552866/why-does-threadsanitizer-report-a-race-with-this-lock-free-example">link</a></p>
  
  <pre><code>#if defined(__SANITIZE_THREAD__)
  #define TSAN_ENABLED
  #elif defined(__has_feature)
  #if __has_feature(thread_sanitizer)
  #define TSAN_ENABLED
  #endif
  #endif
  
  #ifdef TSAN_ENABLED
  #define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \
      AnnotateHappensBefore(__FILE__, __LINE__, (void*)(addr))
  #define TSAN_ANNOTATE_HAPPENS_AFTER(addr) \
      AnnotateHappensAfter(__FILE__, __LINE__, (void*)(addr))
  extern "C" void AnnotateHappensBefore(const char* f, int l, void* addr);
  extern "C" void AnnotateHappensAfter(const char* f, int l, void* addr);
  #else
  #define TSAN_ANNOTATE_HAPPENS_BEFORE(addr)
  #define TSAN_ANNOTATE_HAPPENS_AFTER(addr)
  #endif
  
  #include &lt;atomic&gt;
  #include &lt;thread&gt;
  #include &lt;assert.h&gt;
  bool x=false;
  std::atomic&lt;bool&gt; y;
  std::atomic&lt;int&gt; z;
  void write_x_then_y()
  {
    x=true;
    std::atomic_thread_fence(std::memory_order_release);
    TSAN_ANNOTATE_HAPPENS_BEFORE(&amp;x);
    y.store(true,std::memory_order_relaxed);
  }
  void read_y_then_x()
  {
    while(!y.load(std::memory_order_relaxed));
    std::atomic_thread_fence(std::memory_order_acquire);
    TSAN_ANNOTATE_HAPPENS_AFTER(&amp;x);
    if(x)
      ++z;
  }
  {
    x=false;
    y=false;
    z=0;
    std::thread a(write_x_then_y);
    std::thread b(read_y_then_x);
    a.join();
    b.join();
    assert(z.load()!=0);
  }
  </code></pre>
  
  <p>Compile command</p>
  
  <pre><code>g++ -o a -g -Og -pthread a.cpp -fsanitize=thread -D__SANITIZE_THREAD__
  </code></pre>