From: Kuba Brecka Date: Tue, 2 Aug 2016 14:30:52 +0000 (+0000) Subject: [tsan] Fix the behavior of OSAtomicTestAndClear X-Git-Tag: llvmorg-4.0.0-rc1~13564 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3a748d60670c5dc81572ea680804b3e3486c20e0;p=platform%2Fupstream%2Fllvm.git [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 llvm-svn: 277461 --- diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc index 5939638..03cf54f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -119,24 +119,23 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32, 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) { diff --git a/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm b/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm new file mode 100644 index 0000000..68badb7 --- /dev/null +++ b/compiler-rt/test/tsan/Darwin/osatomics-bitops.mm @@ -0,0 +1,34 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11 +// RUN: %run %t 2>&1 | FileCheck %s + +#import +#import + +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; +}