1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 #include "test.h" 3 4 const int kTestCount = 4; 5 typedef long long T; 6 T atomics[kTestCount * 2]; 7 8 void Test(int test, T *p, bool main_thread) { 9 volatile T sink; 10 if (test == 0) { 11 if (main_thread) 12 __atomic_fetch_add(p, 1, __ATOMIC_RELAXED); 13 else 14 __atomic_fetch_add(p, 1, __ATOMIC_RELAXED); 15 } else if (test == 1) { 16 if (main_thread) 17 __atomic_exchange_n(p, 1, __ATOMIC_ACQ_REL); 18 else 19 __atomic_exchange_n(p, 1, __ATOMIC_ACQ_REL); 20 } else if (test == 2) { 21 if (main_thread) 22 sink = __atomic_load_n(p, __ATOMIC_SEQ_CST); 23 else 24 __atomic_store_n(p, 1, __ATOMIC_SEQ_CST); 25 } else if (test == 3) { 26 if (main_thread) 27 sink = __atomic_load_n(p, __ATOMIC_SEQ_CST); 28 else 29 sink = *p; 30 } 31 } 32 33 void *Thread(void *p) { 34 for (int i = 0; i < kTestCount; i++) { 35 Test(i, &atomics[i], false); 36 } 37 barrier_wait(&barrier); 38 barrier_wait(&barrier); 39 for (int i = 0; i < kTestCount; i++) { 40 fprintf(stderr, "Test %d reverse\n", i); 41 Test(i, &atomics[kTestCount + i], false); 42 } 43 return 0; 44 } 45 46 int main() { 47 barrier_init(&barrier, 2); 48 pthread_t t; 49 pthread_create(&t, 0, Thread, 0); 50 barrier_wait(&barrier); 51 for (int i = 0; i < kTestCount; i++) { 52 fprintf(stderr, "Test %d\n", i); 53 Test(i, &atomics[i], true); 54 } 55 for (int i = 0; i < kTestCount; i++) { 56 Test(i, &atomics[kTestCount + i], true); 57 } 58 barrier_wait(&barrier); 59 pthread_join(t, 0); 60 } 61 62 // CHECK-NOT: ThreadSanitizer: data race 63