[compiler-rt] r277461 - [tsan] Fix the behavior of OSAtomicTestAndClear

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 2 07:30:52 PDT 2016


Author: kuba.brecka
Date: Tue Aug  2 09:30:52 2016
New Revision: 277461

URL: http://llvm.org/viewvc/llvm-project?rev=277461&view=rev
Log:
[tsan] Fix the behavior of OSAtomicTestAndClear

The system implementation of OSAtomicTestAndClear returns the original bit, but the TSan interceptor has a bug which always returns zero from the function. This patch fixes this and adds a test.

Differential Revision: https://reviews.llvm.org/D23061


Added:
    compiler-rt/trunk/test/tsan/Darwin/osatomics-bitops.mm
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc?rev=277461&r1=277460&r2=277461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc Tue Aug  2 09:30:52 2016
@@ -119,24 +119,23 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompar
 OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64,
                           int64_t)
 
-#define OSATOMIC_INTERCEPTOR_BITOP(f, op, m, mo)              \
+#define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo)          \
   TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \
     SCOPED_TSAN_INTERCEPTOR(f, n, ptr);                       \
     char *byte_ptr = ((char *)ptr) + (n >> 3);                \
-    char bit_index = n & 7;                                   \
-    char mask = m;                                            \
+    char bit = 0x80u >> (n & 7);                              \
+    char mask = clear ? ~bit : bit;                           \
     char orig_byte = op((a8 *)byte_ptr, mask, mo);            \
-    return orig_byte & mask;                                  \
+    return orig_byte & bit;                                   \
   }
 
-#define OSATOMIC_INTERCEPTORS_BITOP(f, op, m)                     \
-  OSATOMIC_INTERCEPTOR_BITOP(f, op, m, kMacOrderNonBarrier)       \
-  OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, m, kMacOrderBarrier)
+#define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear)               \
+  OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \
+  OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier)
 
-OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or,
-                            0x80u >> bit_index)
+OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false)
 OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and,
-                            ~(0x80u >> bit_index))
+                            true)
 
 TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
                  size_t offset) {

Added: compiler-rt/trunk/test/tsan/Darwin/osatomics-bitops.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/osatomics-bitops.mm?rev=277461&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/osatomics-bitops.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/osatomics-bitops.mm Tue Aug  2 09:30:52 2016
@@ -0,0 +1,34 @@
+// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+#import <libkern/OSAtomic.h>
+
+int main(int argc, const char *argv[]) {
+  int value = 1;
+  bool ret = OSAtomicTestAndClear(7, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 0, ret = 1
+
+  ret = OSAtomicTestAndSet(4, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 8, ret = 0
+
+  ret = OSAtomicTestAndClear(4, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 0, ret = 1
+
+  ret = OSAtomicTestAndSet(12, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 2048, ret = 0
+
+  ret = OSAtomicTestAndSet(13, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 3072, ret = 0
+
+  ret = OSAtomicTestAndClear(12, &value);
+  fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+  // CHECK: value = 1024, ret = 1
+
+  return 0;
+}




More information about the llvm-commits mailing list