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
11int test;
12int done;
13int signals_handled;
14pthread_t main_thread;
15pthread_mutex_t mutex;
16pthread_cond_t cond;
17
18void timer_handler(int signum) {
19 write(fd: 2, buf: "timer_handler\n", n: strlen(s: "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(threadid: main_thread, SIGUSR1);
26 case 1:
27 if (pthread_mutex_trylock(mutex: &mutex) == 0) {
28 __atomic_store_n(&done, 1, __ATOMIC_RELEASE);
29 pthread_cond_signal(cond: &cond);
30 pthread_mutex_unlock(mutex: &mutex);
31 }
32 case 2:
33 __atomic_store_n(&done, 1, __ATOMIC_RELEASE);
34 }
35}
36
37int main(int argc, char **argv) {
38 main_thread = pthread_self();
39 pthread_mutex_init(mutex: &mutex, mutexattr: 0);
40 pthread_cond_init(cond: &cond, cond_attr: 0);
41
42 sigset_t sigset;
43 sigemptyset(set: &sigset);
44 sigaddset(set: &sigset, SIGUSR1);
45 if (sigprocmask(SIG_BLOCK, set: &sigset, NULL))
46 exit(status: (perror(s: "sigprocmask"), 1));
47
48 struct sigaction sa;
49 memset(s: &sa, c: 0, n: sizeof(sa));
50 sa.sa_handler = &timer_handler;
51 if (sigaction(SIGALRM, act: &sa, NULL))
52 exit(status: (perror(s: "setitimer"), 1));
53
54 for (test = 0; test < 3; test++) {
55 fprintf(stderr, format: "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, new: &timer, NULL))
61 exit(status: (perror(s: "setitimer"), 1));
62
63 switch (test) {
64 case 0:
65 while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
66 int signum;
67 sigwait(set: &sigset, sig: &signum);
68 write(fd: 2, buf: "sigwait\n", n: strlen(s: "sigwait\n"));
69 }
70 case 1:
71 pthread_mutex_lock(mutex: &mutex);
72 while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
73 pthread_cond_wait(cond: &cond, mutex: &mutex);
74 write(fd: 2, buf: "pthread_cond_wait\n", n: strlen(s: "pthread_cond_wait\n"));
75 }
76 pthread_mutex_unlock(mutex: &mutex);
77 case 2:
78 while (__atomic_load_n(&done, __ATOMIC_ACQUIRE) == 0) {
79 }
80 }
81
82 memset(s: &timer, c: 0, n: sizeof(timer));
83 if (setitimer(ITIMER_REAL, new: &timer, NULL))
84 exit(status: (perror(s: "setitimer"), 1));
85 done = 0;
86 signals_handled = 0;
87 }
88 fprintf(stderr, format: "DONE\n");
89}
90
91// CHECK: DONE
92

source code of compiler-rt/test/tsan/signal_block2.cpp