1 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
2 // The test was reported to hang sometimes on Darwin:
3 // https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20210517/917003.html
4 // UNSUPPORTED: darwin
5 
6 #include "test.h"
7 #include <signal.h>
8 #include <string.h>
9 #include <sys/time.h>
10 
11 int test;
12 int done;
13 int signals_handled;
14 pthread_t main_thread;
15 pthread_mutex_t mutex;
16 pthread_cond_t cond;
17 
timer_handler(int signum)18 void timer_handler(int signum) {
19   write(2, "timer_handler\n", strlen("timer_handler\n"));
20   if (++signals_handled < 10)
21     return;
22   switch (test) {
23   case 0:
24     __atomic_store_n(&done, 1, __ATOMIC_RELEASE);
25     (void)pthread_kill(main_thread, SIGUSR1);
26   case 1:
27     if (pthread_mutex_trylock(&mutex) == 0) {
28       __atomic_store_n(&done, 1, __ATOMIC_RELEASE);
29       pthread_cond_signal(&cond);
30       pthread_mutex_unlock(&mutex);
31     }
32   case 2:
33     __atomic_store_n(&done, 1, __ATOMIC_RELEASE);
34   }
35 }
36 
main(int argc,char ** argv)37 int main(int argc, char **argv) {
38   main_thread = pthread_self();
39   pthread_mutex_init(&mutex, 0);
40   pthread_cond_init(&cond, 0);
41 
42   sigset_t sigset;
43   sigemptyset(&sigset);
44   sigaddset(&sigset, SIGUSR1);
45   if (sigprocmask(SIG_BLOCK, &sigset, NULL))
46     exit((perror("sigprocmask"), 1));
47 
48   struct sigaction sa;
49   memset(&sa, 0, sizeof(sa));
50   sa.sa_handler = &timer_handler;
51   if (sigaction(SIGALRM, &sa, NULL))
52     exit((perror("setitimer"), 1));
53 
54   for (test = 0; test < 3; test++) {
55     fprintf(stderr, "test %d\n", test);
56     struct itimerval timer;
57     timer.it_value.tv_sec = 0;
58     timer.it_value.tv_usec = 50000;
59     timer.it_interval = timer.it_value;
60     if (setitimer(ITIMER_REAL, &timer, NULL))
61       exit((perror("setitimer"), 1));
62 
63     switch (test) {
64     case 0:
65       while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
66         int signum;
67         sigwait(&sigset, &signum);
68         write(2, "sigwait\n", strlen("sigwait\n"));
69       }
70     case 1:
71       pthread_mutex_lock(&mutex);
72       while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
73         pthread_cond_wait(&cond, &mutex);
74         write(2, "pthread_cond_wait\n", strlen("pthread_cond_wait\n"));
75       }
76       pthread_mutex_unlock(&mutex);
77     case 2:
78       while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
79       }
80     }
81 
82     memset(&timer, 0, sizeof(timer));
83     if (setitimer(ITIMER_REAL, &timer, NULL))
84       exit((perror("setitimer"), 1));
85     done = 0;
86     signals_handled = 0;
87   }
88   fprintf(stderr, "DONE\n");
89 }
90 
91 // CHECK: DONE
92