1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
2 // UNSUPPORTED: darwin
3 #include "test.h"
4 #include <errno.h>
5 #include <signal.h>
6 #include <sys/time.h>
7 #include <sys/types.h>
8 
9 // Test synchronization in signal handled within IgnoreSync region.
10 
11 const int kSignalCount = 500;
12 
13 __thread int process_signals;
14 int signals_handled;
15 int done;
16 int ready[kSignalCount];
17 long long data[kSignalCount];
18 
handler(int sig)19 static void handler(int sig) {
20   if (!__atomic_load_n(&process_signals, __ATOMIC_RELAXED))
21     return;
22   int pos = signals_handled++;
23   if (pos >= kSignalCount)
24     return;
25   data[pos] = pos;
26   __atomic_store_n(&ready[pos], 1, __ATOMIC_RELEASE);
27 }
28 
thr(void * p)29 static void* thr(void *p) {
30   AnnotateIgnoreSyncBegin(__FILE__, __LINE__);
31   __atomic_store_n(&process_signals, 1, __ATOMIC_RELAXED);
32   while (!__atomic_load_n(&done, __ATOMIC_RELAXED)) {
33   }
34   AnnotateIgnoreSyncEnd(__FILE__, __LINE__);
35   return 0;
36 }
37 
main()38 int main() {
39   struct sigaction act = {};
40   act.sa_handler = handler;
41   if (sigaction(SIGPROF, &act, 0)) {
42     perror("sigaction");
43     exit(1);
44   }
45   itimerval t;
46   t.it_value.tv_sec = 0;
47   t.it_value.tv_usec = 10;
48   t.it_interval = t.it_value;
49   if (setitimer(ITIMER_PROF, &t, 0)) {
50     perror("setitimer");
51     exit(1);
52   }
53 
54   pthread_t th;
55   pthread_create(&th, 0, thr, 0);
56   for (int pos = 0; pos < kSignalCount; pos++) {
57     while (__atomic_load_n(&ready[pos], __ATOMIC_ACQUIRE) == 0) {
58     }
59     if (data[pos] != pos) {
60       printf("at pos %d, expect %d, got %lld\n", pos, pos, data[pos]);
61       exit(1);
62     }
63   }
64   __atomic_store_n(&done, 1, __ATOMIC_RELAXED);
65   pthread_join(th, 0);
66   fprintf(stderr, "DONE\n");
67   return 0;
68 }
69 
70 // CHECK-NOT: WARNING: ThreadSanitizer:
71 // CHECK: DONE
72