https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78158
Bug ID: 78158 Summary: Strange data race detection with thread sanitizer Product: gcc Version: 6.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: sanitizer Assignee: unassigned at gcc dot gnu.org Reporter: morandidodo at gmail dot com CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org, kcc at gcc dot gnu.org Target Milestone: --- I am having an issue with the following piece of code: #include <atomic> #include <thread> #include <cassert> #include <iostream> #include <chrono> #include <cmath> #include <vector> #include <mutex> using namespace std::chrono_literals; static std::atomic_bool writing_locked = {false}; static std::atomic_int readers = {0}; static std::mutex mutex; static std::atomic_bool loading = {false}; long double tester = 345.7654; void fun() { static constexpr unsigned iterations = 10000000; long double local_tester = 0.; for(unsigned iteration = 0;;) { if(not writing_locked) { int local_readers = readers; if(local_readers < 0) { std::lock_guard<std::mutex> lock(mutex); continue; } if(not readers.compare_exchange_weak(local_readers, local_readers + 1)) continue; } else { std::lock_guard<std::mutex> lock(mutex); continue; } assert(readers > 0); for(unsigned i = 0; i < 1000; ++i) local_tester += std::log(tester); /* This line is said to race... */ assert(readers > 0); --readers; if(static_cast<unsigned>(local_tester) % 500 == 0) { bool current_loading = false; if(loading.compare_exchange_strong(current_loading, true)) { std::lock_guard<std::mutex> lock(mutex); writing_locked = true; int zero_readers = 0; do { zero_readers = 0; } while(not readers.compare_exchange_weak(zero_readers, -1)); assert(readers == -1); for(unsigned i = 0; i < 100; ++i) tester = std::sqrt(std::pow(tester, 2) + 1); /* ...with this line */ assert(readers == -1); readers = 0; writing_locked = false; loading = false; } } else if(iteration++ >= iterations) return; } } int main() { static const unsigned max_threads = std::thread::hardware_concurrency(); std::vector<std::thread> threads(max_threads); for(unsigned i = 0; i < max_threads; ++i) threads[i] = std::thread(fun); for(unsigned i = 0; i < max_threads; ++i) threads[i].join(); } IMHO there should not be any race in this code, but if it is compiled with -fsanitize=thread, a data race is found between the two lines commented, but only when NDEBUG is defined. clang does not warn about any issue. I thought that it could be related to bug 68260, but I just compiled the last version from Git and the problem is still there.