1#include <pthread.h>
2#include <stdio.h>
3#include <unistd.h>
4
5int Global;
6
7void __attribute__((noinline)) foo1() {
8  Global = 42;
9}
10
11void __attribute__((noinline)) bar1() {
12  volatile int tmp = 42;
13  int tmp2 = tmp;
14  (void)tmp2;
15  foo1();
16}
17
18void __attribute__((noinline)) foo2() {
19  volatile int tmp = Global;
20  int tmp2 = tmp;
21  (void)tmp2;
22}
23
24void __attribute__((noinline)) bar2() {
25  volatile int tmp = 42;
26  int tmp2 = tmp;
27  (void)tmp2;
28  foo2();
29}
30
31void *Thread1(void *x) {
32  usleep(1000000);
33  bar1();
34  return NULL;
35}
36
37int main() {
38  pthread_t t;
39  pthread_create(&t, NULL, Thread1, NULL);
40  bar2();
41  pthread_join(t, NULL);
42}
43
44// CHECK:      WARNING: ThreadSanitizer: data race
45// CHECK-NEXT:   Write of size 4 at {{.*}} by thread 1:
46// CHECK-NEXT:     #0 foo1{{.*}} {{.*}}simple_stack2.cc:8{{(:3)?}} ({{.*}})
47// CHECK-NEXT:     #1 bar1{{.*}} {{.*}}simple_stack2.cc:15{{(:3)?}} ({{.*}})
48// CHECK-NEXT:     #2 Thread1{{.*}} {{.*}}simple_stack2.cc:33{{(:3)?}} ({{.*}})
49// CHECK:        Previous read of size 4 at {{.*}} by main thread:
50// CHECK-NEXT:     #0 foo2{{.*}} {{.*}}simple_stack2.cc:19{{(:28)?}} ({{.*}})
51// CHECK-NEXT:     #1 bar2{{.*}} {{.*}}simple_stack2.cc:28{{(:3)?}} ({{.*}})
52// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack2.cc:40{{(:3)?}} ({{.*}})
53