1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 // Regression test for https://github.com/golang/go/issues/39186 3 #include "java.h" 4 #include <string.h> 5 6 struct Heap { 7 uint64_t data; 8 uint64_t ready; 9 uint64_t finalized; 10 uint64_t wg; 11 pthread_barrier_t barrier_finalizer; 12 pthread_barrier_t barrier_ballast; 13 }; 14 15 void *Thread1(void *p) { 16 Heap* heap = (Heap*)p; 17 pthread_barrier_wait(&heap->barrier_finalizer); 18 __tsan_java_finalize(); 19 __atomic_fetch_add(&heap->wg, 1, __ATOMIC_RELEASE); 20 __atomic_store_n(&heap->finalized, 1, __ATOMIC_RELAXED); 21 return 0; 22 } 23 24 void *Thread2(void *p) { 25 Heap* heap = (Heap*)p; 26 pthread_barrier_wait(&heap->barrier_finalizer); 27 heap->data = 1; 28 __atomic_store_n(&heap->ready, 1, __ATOMIC_RELEASE); 29 return 0; 30 } 31 32 void *Thread3(void *p) { 33 Heap* heap = (Heap*)p; 34 pthread_barrier_wait(&heap->barrier_finalizer); 35 while (__atomic_load_n(&heap->ready, __ATOMIC_ACQUIRE) != 1) 36 pthread_yield(); 37 while (__atomic_load_n(&heap->finalized, __ATOMIC_RELAXED) != 1) 38 pthread_yield(); 39 __atomic_fetch_add(&heap->wg, 1, __ATOMIC_RELEASE); 40 return 0; 41 } 42 43 void *Ballast(void *p) { 44 Heap* heap = (Heap*)p; 45 pthread_barrier_wait(&heap->barrier_ballast); 46 return 0; 47 } 48 49 int main() { 50 Heap* heap = (Heap*)calloc(sizeof(Heap), 1); 51 __tsan_java_init((jptr)heap, sizeof(*heap)); 52 __tsan_java_alloc((jptr)heap, sizeof(*heap)); 53 // Ballast threads merely make the bug a bit easier to trigger. 54 const int kBallastThreads = 100; 55 pthread_barrier_init(&heap->barrier_finalizer, 0, 4); 56 pthread_barrier_init(&heap->barrier_ballast, 0, kBallastThreads + 1); 57 pthread_t th[3]; 58 pthread_create(&th[0], 0, Thread1, heap); 59 pthread_create(&th[1], 0, Thread2, heap); 60 pthread_t ballast[kBallastThreads]; 61 for (int i = 0; i < kBallastThreads; i++) 62 pthread_create(&ballast[i], 0, Ballast, heap); 63 pthread_create(&th[2], 0, Thread3, heap); 64 pthread_barrier_wait(&heap->barrier_ballast); 65 for (int i = 0; i < kBallastThreads; i++) 66 pthread_join(ballast[i], 0); 67 pthread_barrier_wait(&heap->barrier_finalizer); 68 while (__atomic_load_n(&heap->wg, __ATOMIC_ACQUIRE) != 2) 69 pthread_yield(); 70 if (heap->data != 1) 71 exit(printf("no data\n")); 72 for (int i = 0; i < 3; i++) 73 pthread_join(th[i], 0); 74 pthread_barrier_destroy(&heap->barrier_ballast); 75 pthread_barrier_destroy(&heap->barrier_finalizer); 76 __tsan_java_free((jptr)heap, sizeof(*heap)); 77 fprintf(stderr, "DONE\n"); 78 return __tsan_java_fini(); 79 } 80 81 // CHECK-NOT: WARNING: ThreadSanitizer: data race 82 // CHECK: DONE 83