[compiler-rt] eeccdd3 - Revert "tsan: model atomic read for failing CAS"

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Mon May 2 22:28:34 PDT 2022


Author: Vitaly Buka
Date: 2022-05-02T22:26:56-07:00
New Revision: eeccdd318d25f68745cdf8199f7e8c251d0cf65e

URL: https://github.com/llvm/llvm-project/commit/eeccdd318d25f68745cdf8199f7e8c251d0cf65e
DIFF: https://github.com/llvm/llvm-project/commit/eeccdd318d25f68745cdf8199f7e8c251d0cf65e.diff

LOG: Revert "tsan: model atomic read for failing CAS"

https://lab.llvm.org/buildbot/#/builders/70/builds/21206 hangs.

This reverts commit 2fec52a40261ecab7fc621184159f464c67dcfa4.

Added: 
    

Modified: 
    compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp

Removed: 
    compiler-rt/test/tsan/atomic_norace3.cpp


################################################################################
diff  --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
index efa1ad2ecd822..f794a2fcdd0df 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
@@ -411,39 +411,14 @@ static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
   // (mo_relaxed) when those are used.
   DCHECK(IsLoadOrder(fmo));
 
+  MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
   if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
     T cc = *c;
     T pr = func_cas(a, cc, v);
-    bool success = pr == cc;
-    if (!success)
-      *c = pr;
-    // We used to always model a write and before the actual CAS.
-    // However, the standard 29.6.5/21 says:
-    // If the operation returns true, these operations are atomic
-    // read-modify-write operations (1.10). Otherwise, these operations
-    // are atomic load operations.
-    //
-    // And this 
diff erence can lead to false positive reports when
-    // a program uses __atomic builtins and one thread executes a failing CAS
-    // while another executes a non-atomic load. If we always model a write
-    // these operations will race.
-    //
-    // This leads to another subtle aspect:
-    // Atomics provide destruction-safety and can be used to synchronize
-    // own destruction/freeing of underlying memory.
-    // So one thread can do (a successful) CAS to signal to free the memory,
-    // and another thread do an atomic load, observe the CAS and free the
-    // memory. So modelling the memory access after the actual access is
-    // somewhat risky (can potentially lead to other false positive reports if
-    // the memory is already reused when we model the memory access). However,
-    // destruction signalling must use acquire/release memory ordering
-    // constraints. So we should lock s->mtx below and it should prevent the
-    // reuse race. If/when we support stand-alone memory fences, it's unclear
-    // how to handle this case. We could always lock s->mtx even for relaxed
-    // accesses, but it will have severe performance impact on relaxed loads.
-    MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
-                 kAccessAtomic | (success ? kAccessWrite : kAccessRead));
-    return success;
+    if (pr == cc)
+      return true;
+    *c = pr;
+    return false;
   }
   SlotLocker locker(thr);
   bool release = IsReleaseOrder(mo);
@@ -458,9 +433,6 @@ static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
       *c = pr;
       mo = fmo;
     }
-    // See the comment on the previous MemoryAccess.
-    MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
-                 kAccessAtomic | (success ? kAccessWrite : kAccessRead));
     if (success && IsAcqRelOrder(mo))
       thr->clock.ReleaseAcquire(&s->clock);
     else if (success && IsReleaseOrder(mo))

diff  --git a/compiler-rt/test/tsan/atomic_norace3.cpp b/compiler-rt/test/tsan/atomic_norace3.cpp
deleted file mode 100644
index 6ac2c9ea29d75..0000000000000
--- a/compiler-rt/test/tsan/atomic_norace3.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 | FileCheck %s
-
-#include "test.h"
-#include <thread>
-
-int main() {
-  barrier_init(&barrier, 2);
-  volatile int x = 0;
-  std::thread reader([&]() {
-    barrier_wait(&barrier);
-    int l = x;
-    (void)l;
-  });
-  int cmp = 1;
-  __atomic_compare_exchange_n(&x, &cmp, 1, 1, __ATOMIC_RELAXED,
-                              __ATOMIC_RELAXED);
-  barrier_wait(&barrier);
-  reader.join();
-  fprintf(stderr, "DONE\n");
-}
-
-// CHECK-NOT: ThreadSanitizer: data race
-// CHECK: DONE


        


More information about the llvm-commits mailing list