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.