1 // RUN: %clang_tsan %s -o %t
2 // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
3 
4 #include <dispatch/dispatch.h>
5 
6 #include "../test.h"
7 
8 const size_t size = 2;
9 long global;
10 long array[size];
11 
callback(void * context,size_t i)12 void callback(void *context, size_t i) {
13   long n = global;
14   array[i] = n + i;
15   barrier_wait(&barrier);
16 }
17 
main(int argc,const char * argv[])18 int main(int argc, const char *argv[]) {
19   fprintf(stderr, "start\n");
20 
21   // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
22   dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
23 
24   dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
25 
26   global = 42;
27 
28   barrier_init(&barrier, size);
29   dispatch_apply(size, q, ^(size_t i) {
30     long n = global;
31     array[i] = n + i;
32     barrier_wait(&barrier);
33   });
34 
35   for (size_t i = 0; i < size; i++) {
36     fprintf(stderr, "array[%ld] = %ld\n", i, array[i]);
37   }
38 
39   global = 142;
40 
41   barrier_init(&barrier, size);
42   dispatch_apply_f(size, q, NULL, &callback);
43 
44   for (size_t i = 0; i < size; i++) {
45     fprintf(stderr, "array[%ld] = %ld\n", i, array[i]);
46   }
47 
48   fprintf(stderr, "done\n");
49   return 0;
50 }
51 
52 // CHECK: start
53 // CHECK: array[0] = 42
54 // CHECK: array[1] = 43
55 // CHECK: array[0] = 142
56 // CHECK: array[1] = 143
57 // CHECK: done
58