Commit e22d96d6 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Add a workaround for a TSAN atomics bug

Summary: https://github.com/google/sanitizers/issues/970

Reviewed By: yfeldblum

Differential Revision: D16037542

fbshipit-source-id: 8c2feb85454ae582498d38a474e8d5913c9438b1
parent 4df20672
......@@ -584,11 +584,8 @@ class DeferredExecutor final : public Executor {
}
DCHECK(state == State::EMPTY);
func_ = std::move(func);
if (state_.compare_exchange_strong(
state,
State::HAS_FUNCTION,
std::memory_order_release,
std::memory_order_acquire)) {
if (detail::compare_exchange_strong_release_acquire(
state_, state, State::HAS_FUNCTION)) {
return;
}
DCHECK(state == State::DETACHED || state == State::HAS_EXECUTOR);
......@@ -614,11 +611,8 @@ class DeferredExecutor final : public Executor {
executor_ = std::move(executor);
auto state = state_.load(std::memory_order_acquire);
if (state == State::EMPTY &&
state_.compare_exchange_strong(
state,
State::HAS_EXECUTOR,
std::memory_order_release,
std::memory_order_acquire)) {
detail::compare_exchange_strong_release_acquire(
state_, state, State::HAS_EXECUTOR)) {
return;
}
......@@ -636,11 +630,8 @@ class DeferredExecutor final : public Executor {
}
auto state = state_.load(std::memory_order_acquire);
if (state == State::EMPTY &&
state_.compare_exchange_strong(
state,
State::DETACHED,
std::memory_order_release,
std::memory_order_acquire)) {
detail::compare_exchange_strong_release_acquire(
state_, state, State::DETACHED)) {
return;
}
......
......@@ -72,6 +72,20 @@ struct SpinLock : private MicroSpinLock {
};
static_assert(sizeof(SpinLock) == 1, "missized");
template <typename T>
bool compare_exchange_strong_release_acquire(
std::atomic<T>& self,
T& expected,
T desired) {
if (kIsSanitizeThread) {
// Workaround for https://github.com/google/sanitizers/issues/970
return self.compare_exchange_strong(
expected, desired, std::memory_order_acq_rel);
}
return self.compare_exchange_strong(
expected, desired, std::memory_order_release, std::memory_order_acquire);
}
/// The shared state object for Future and Promise.
///
/// Nomenclature:
......@@ -330,11 +344,8 @@ class Core final {
: State::OnlyCallback;
if (state == State::Start) {
if (state_.compare_exchange_strong(
state,
nextState,
std::memory_order_release,
std::memory_order_acquire)) {
if (detail::compare_exchange_strong_release_acquire(
state_, state, nextState)) {
return;
}
assume(state == State::OnlyResult || state == State::Proxy);
......@@ -367,11 +378,8 @@ class Core final {
auto state = state_.load(std::memory_order_acquire);
switch (state) {
case State::Start:
if (state_.compare_exchange_strong(
state,
State::Proxy,
std::memory_order_release,
std::memory_order_acquire)) {
if (detail::compare_exchange_strong_release_acquire(
state_, state, State::Proxy)) {
break;
}
assume(
......@@ -420,11 +428,8 @@ class Core final {
auto state = state_.load(std::memory_order_acquire);
switch (state) {
case State::Start:
if (state_.compare_exchange_strong(
state,
State::OnlyResult,
std::memory_order_release,
std::memory_order_acquire)) {
if (detail::compare_exchange_strong_release_acquire(
state_, state, State::OnlyResult)) {
return;
}
assume(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment