1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 #include "test.h" 3 4 const int kTestCount = 3; 5 typedef long long T; 6 T data[kTestCount]; 7 T atomics[kTestCount]; 8 9 void *Thread(void *p) { 10 for (int i = 0; i < kTestCount; i++) { 11 barrier_wait(&barrier); 12 while (__atomic_load_n(&atomics[i], __ATOMIC_ACQUIRE) == 0) { 13 } 14 data[i]++; 15 } 16 return 0; 17 } 18 19 int main() { 20 barrier_init(&barrier, 2); 21 pthread_t t; 22 pthread_create(&t, 0, Thread, 0); 23 for (int i = 0; i < kTestCount; i++) { 24 barrier_wait(&barrier); 25 // We want the release to happen while the other thread 26 // spins calling load-acquire. This can expose some 27 // interesting interleavings of release and acquire. 28 usleep(100 * 1000); 29 data[i] = 1; 30 switch (i) { 31 case 0: 32 __atomic_store_n(&atomics[i], 1, __ATOMIC_RELEASE); 33 break; 34 case 1: 35 __atomic_fetch_add(&atomics[1], 1, __ATOMIC_RELEASE); 36 break; 37 case 2: 38 T cmp = 0; 39 __atomic_compare_exchange_n(&atomics[2], &cmp, 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED); 40 break; 41 } 42 } 43 pthread_join(t, 0); 44 fprintf(stderr, "DONE\n"); 45 } 46 47 // CHECK-NOT: ThreadSanitizer: data race 48 // CHECK: DONE 49