headers/bsd: Add sys/queue.h.
[haiku.git] / src / tests / system / libroot / posix / pthread_signal_test.cpp
blob014741f4699161c6f43b230ea678e8371b2cc0fe
1 #include <pthread.h>
2 #include <sched.h>
3 #include <setjmp.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
11 static pthread_attr_t attributes;
12 static int id[4] = {0, 1, 2, 3};
13 static pthread_t tid[4];
14 static bool state[4];
15 static bool blocking[4];
16 static pthread_key_t self;
19 static void
20 suspendLoop(int *i) {
21 sigjmp_buf env;
22 sigset_t mask;
24 sigsetjmp(env, false);
26 state[*i] = false;
28 sigfillset(&mask);
29 sigdelset(&mask, SIGUSR1);
30 sigdelset(&mask, SIGTERM);
32 while (state[*i] == false && blocking[*i] == false)
33 sigsuspend(&mask);
35 state[*i] = true;
39 static void
40 suspendHandler(int sig) {
41 int *i = (int*)pthread_getspecific(self);
42 suspendLoop(i);
46 static void
47 initialiseSignals()
49 struct sigaction act;
50 sigset_t mask;
52 act.sa_handler = suspendHandler;
53 sigemptyset(&act.sa_mask);
54 act.sa_flags = 0;
55 sigaction(SIGUSR1, &act, NULL);
57 sigemptyset(&mask);
58 sigaddset(&mask, SIGQUIT);
59 sigaddset(&mask, SIGINT);
60 sigaddset(&mask, SIGPIPE);
61 sigprocmask(SIG_BLOCK, &mask, NULL);
65 static void
66 self_suspend(int* i)
68 sigset_t mask;
70 blocking[*i] = false;
72 sigemptyset(&mask);
73 sigaddset(&mask, SIGUSR1);
74 pthread_sigmask(SIG_BLOCK, &mask, NULL);
76 printf("thread %d suspending\n", *i);
78 suspendLoop(i);
80 printf("thread %d suspend ended\n", *i);
82 pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
86 void *
87 threadStart(void *arg)
89 int i = *(int*)arg;
90 pthread_setspecific(self, &i);
92 state[i] = true;
93 blocking[i] = true;
95 printf("threadStart(%d)\n", i);
97 for (int j = 0; j < 10; j++) {
98 usleep(1000000);
99 self_suspend(&i);
102 printf("quitting %d\n", i);
103 return NULL;
107 /*void
108 suspendAllThreads()
110 for (int i = 0; i < 4; i++) {
111 blocking[i] = false;
112 if (state[i] == true)
113 pthread_kill(tid[i], SIGUSR1);
116 for (int i = 0; i < 4; i++) {
117 while(state[i] == true) {
118 sched_yield();
125 void
126 resumeAllThreads()
128 for (int i = 0; i < 4; i++) {
129 blocking[i] = true;
130 if (state[i] == false) {
131 printf("thread %d signaled for resume\n", i);
132 pthread_kill(tid[i], SIGUSR1);
136 int t = 50;
137 for (int i = 0; i < 4; i++) {
138 while(state[i] == false && t-- > 0) {
139 printf("thread %d still suspended, yielding\n", i);
140 sched_yield();
147 main(int argc, char **argv)
149 initialiseSignals();
151 pthread_key_create(&self, NULL);
153 pthread_attr_init(&attributes);
154 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
156 for (int i = 0; i < 4; i++) {
157 if (pthread_create(&tid[i], &attributes, threadStart, &id[i]) != 0)
158 fprintf(stderr, "couldn't create thread %d\n", i);
159 printf("thread %d created\n", i);
162 /*suspendAllThreads();*/
163 printf("snoozing\n");
164 usleep(3000000);
165 printf("resuming all threads\n");
166 resumeAllThreads();
167 printf("resuming all threads done\n");