[TSAN] LLVM statistics and pass initialization trigger race detection

Hello,

I trying TSAN on Darwin on LLVM itself (sanitizing multi-threaded ThinLTO link).
However I see two main issues on my debug build:

  1. Statistics: the pre/post increment is not safe, it seems to be acknowledge in the code itself:

// FIXME: This function and all those that follow carefully use an
// atomic operation to update the value safely in the presence of
// concurrent accesses, but not to read the return value, so the
// return value is not thread safe.

Can we tell TSAN to ignore the statistics somehow? Alternatively, is there a fix someone can suggest?

  1. Pass initialization. This macro does not please TSAN (even though it seems written with TSAN in mind):

#define CALL_ONCE_INITIALIZATION(function)
static volatile sys::cas_flag initialized = 0;
sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0);
if (old_val == 0) {
function(Registry);
sys::MemoryFence();
TsanIgnoreWritesBegin();
TsanHappensBefore(&initialized);
initialized = 2;
TsanIgnoreWritesEnd();
} else {
sys::cas_flag tmp = initialized;
sys::MemoryFence();
while (tmp != 2) {
tmp = initialized;
sys::MemoryFence();
}
}
TsanHappensAfter(&initialized);

The failure looks like:

+dvyukov

Hi,

Thanks for the answers.

+dvyukov

Ok, will look into this!

Maybe some pre c++11 thing?
I’ll try to upgrade std::call_once.

I plan on adding a TSan bot on Green Dragon in the near future.
My idea is to perform a ThinLTO bootstrap of clang (i.e. stage 1 being a Release+Assert+TSAN and stage2 Release-ThinLTO). This involves running the optimizer and the codegen in multiple threads.