xref: /haiku/src/tests/system/libroot/posix/pthread_signal_test.cpp (revision d13211ac40ebfae1eee4cc387b6fe3f2e2dde992)
192e68ec1SJérôme Duval #include <pthread.h>
292e68ec1SJérôme Duval #include <sched.h>
392e68ec1SJérôme Duval #include <setjmp.h>
492e68ec1SJérôme Duval #include <signal.h>
592e68ec1SJérôme Duval #include <stdio.h>
692e68ec1SJérôme Duval #include <stdlib.h>
792e68ec1SJérôme Duval #include <string.h>
892e68ec1SJérôme Duval #include <unistd.h>
992e68ec1SJérôme Duval 
1092e68ec1SJérôme Duval 
1192e68ec1SJérôme Duval static pthread_attr_t attributes;
1292e68ec1SJérôme Duval static pthread_t tid[4];
1392e68ec1SJérôme Duval static bool	state[4];
1492e68ec1SJérôme Duval static bool blocking[4];
1592e68ec1SJérôme Duval static pthread_key_t self;
1692e68ec1SJérôme Duval 
1792e68ec1SJérôme Duval 
18*d13211acSJérôme Duval static void
19*d13211acSJérôme Duval suspendLoop(int *i) {
2092e68ec1SJérôme Duval 	sigjmp_buf env;
2192e68ec1SJérôme Duval 	sigset_t mask;
2292e68ec1SJérôme Duval 
2392e68ec1SJérôme Duval 	sigsetjmp(env, false);
2492e68ec1SJérôme Duval 
2592e68ec1SJérôme Duval 	state[*i] = false;
2692e68ec1SJérôme Duval 
2792e68ec1SJérôme Duval 	sigfillset(&mask);
2892e68ec1SJérôme Duval 	sigdelset(&mask, SIGUSR1);
2992e68ec1SJérôme Duval 	sigdelset(&mask, SIGTERM);
3092e68ec1SJérôme Duval 
3192e68ec1SJérôme Duval 	while (state[*i] == false && blocking[*i] == false)
3292e68ec1SJérôme Duval 		sigsuspend(&mask);
3392e68ec1SJérôme Duval 
3492e68ec1SJérôme Duval 	state[*i] = true;
3592e68ec1SJérôme Duval }
3692e68ec1SJérôme Duval 
3792e68ec1SJérôme Duval 
38*d13211acSJérôme Duval static void
39*d13211acSJérôme Duval suspendHandler(int sig) {
4092e68ec1SJérôme Duval 	int *i = (int*)pthread_getspecific(self);
4192e68ec1SJérôme Duval 	suspendLoop(i);
4292e68ec1SJérôme Duval }
4392e68ec1SJérôme Duval 
44*d13211acSJérôme Duval 
45*d13211acSJérôme Duval static void
46*d13211acSJérôme Duval initialiseSignals()
4792e68ec1SJérôme Duval {
4892e68ec1SJérôme Duval 	struct sigaction act;
4992e68ec1SJérôme Duval 	sigset_t mask;
5092e68ec1SJérôme Duval 
5192e68ec1SJérôme Duval 	act.sa_handler = suspendHandler;
5292e68ec1SJérôme Duval 	sigemptyset(&act.sa_mask);
5392e68ec1SJérôme Duval 	act.sa_flags = 0;
5492e68ec1SJérôme Duval 	sigaction(SIGUSR1, &act, NULL);
5592e68ec1SJérôme Duval 
5692e68ec1SJérôme Duval 	sigemptyset(&mask);
5792e68ec1SJérôme Duval 	sigaddset(&mask, SIGQUIT);
5892e68ec1SJérôme Duval 	sigaddset(&mask, SIGINT);
5992e68ec1SJérôme Duval 	sigaddset(&mask, SIGPIPE);
6092e68ec1SJérôme Duval 	sigprocmask(SIG_BLOCK, &mask, NULL);
6192e68ec1SJérôme Duval }
6292e68ec1SJérôme Duval 
6392e68ec1SJérôme Duval 
64*d13211acSJérôme Duval static void
65*d13211acSJérôme Duval self_suspend(int* i)
6692e68ec1SJérôme Duval {
6792e68ec1SJérôme Duval 	sigset_t mask;
6892e68ec1SJérôme Duval 
6992e68ec1SJérôme Duval 	blocking[*i] = false;
7092e68ec1SJérôme Duval 
7192e68ec1SJérôme Duval 	sigemptyset(&mask);
7292e68ec1SJérôme Duval 	sigaddset(&mask, SIGUSR1);
7392e68ec1SJérôme Duval 	pthread_sigmask(SIG_BLOCK, &mask, NULL);
7492e68ec1SJérôme Duval 
7592e68ec1SJérôme Duval 	printf("thread %d suspending\n", *i);
7692e68ec1SJérôme Duval 
7792e68ec1SJérôme Duval 	suspendLoop(i);
7892e68ec1SJérôme Duval 
7992e68ec1SJérôme Duval 	printf("thread %d suspend ended\n", *i);
8092e68ec1SJérôme Duval 
8192e68ec1SJérôme Duval 	pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
8292e68ec1SJérôme Duval }
8392e68ec1SJérôme Duval 
8492e68ec1SJérôme Duval 
85*d13211acSJérôme Duval void *
86*d13211acSJérôme Duval threadStart(void *arg)
87*d13211acSJérôme Duval {
8892e68ec1SJérôme Duval 	int *i = (int*)arg;
8992e68ec1SJérôme Duval 	pthread_setspecific(self, i);
9092e68ec1SJérôme Duval 
9192e68ec1SJérôme Duval 	state[*i] = true;
9292e68ec1SJérôme Duval 	blocking[*i] = true;
9392e68ec1SJérôme Duval 
9492e68ec1SJérôme Duval 	for (int j = 0; j < 10; j++) {
9592e68ec1SJérôme Duval 		self_suspend(i);
9692e68ec1SJérôme Duval 		usleep(10000);
9792e68ec1SJérôme Duval 	}
9892e68ec1SJérôme Duval 
9992e68ec1SJérôme Duval 	printf("quitting %d\n", *i);
10092e68ec1SJérôme Duval 	return NULL;
10192e68ec1SJérôme Duval }
10292e68ec1SJérôme Duval 
10392e68ec1SJérôme Duval 
104*d13211acSJérôme Duval /*void
105*d13211acSJérôme Duval suspendAllThreads()
10692e68ec1SJérôme Duval {
10792e68ec1SJérôme Duval 	for (int i = 0; i < 4; i++) {
10892e68ec1SJérôme Duval 		blocking[i] = false;
10992e68ec1SJérôme Duval 		if (state[i] == true)
11092e68ec1SJérôme Duval 			pthread_kill(tid[i], SIGUSR1);
11192e68ec1SJérôme Duval 	}
11292e68ec1SJérôme Duval 
11392e68ec1SJérôme Duval 	for (int i = 0; i < 4; i++) {
11492e68ec1SJérôme Duval 		while(state[i] == true) {
11592e68ec1SJérôme Duval 			sched_yield();
11692e68ec1SJérôme Duval 		}
11792e68ec1SJérôme Duval 	}
11892e68ec1SJérôme Duval }*/
11992e68ec1SJérôme Duval 
12092e68ec1SJérôme Duval 
12192e68ec1SJérôme Duval 
122*d13211acSJérôme Duval void
123*d13211acSJérôme Duval resumeAllThreads()
12492e68ec1SJérôme Duval {
12592e68ec1SJérôme Duval 	for (int i = 0; i < 4; i++) {
12692e68ec1SJérôme Duval 		blocking[i] = true;
12792e68ec1SJérôme Duval 		if (state[i] == false) {
12892e68ec1SJérôme Duval 			printf("thread %d signaled for resume\n", i);
12992e68ec1SJérôme Duval 			pthread_kill(tid[i], SIGUSR1);
13092e68ec1SJérôme Duval 		}
13192e68ec1SJérôme Duval 	}
13292e68ec1SJérôme Duval 
13392e68ec1SJérôme Duval 	for (int i = 0; i < 4; i++) {
13492e68ec1SJérôme Duval 		while(state[i] == false) {
13592e68ec1SJérôme Duval 			printf("thread %d still suspended, yielding\n", i);
13692e68ec1SJérôme Duval 			sched_yield();
13792e68ec1SJérôme Duval 		}
13892e68ec1SJérôme Duval 	}
13992e68ec1SJérôme Duval }
14092e68ec1SJérôme Duval 
14192e68ec1SJérôme Duval 
142*d13211acSJérôme Duval int
143*d13211acSJérôme Duval main(int argc, char **argv)
14492e68ec1SJérôme Duval {
14592e68ec1SJérôme Duval 	initialiseSignals();
14692e68ec1SJérôme Duval 
14792e68ec1SJérôme Duval 	pthread_key_create(&self, NULL);
14892e68ec1SJérôme Duval 
14992e68ec1SJérôme Duval 	pthread_attr_init(&attributes);
15092e68ec1SJérôme Duval 	pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
15192e68ec1SJérôme Duval 
15292e68ec1SJérôme Duval 	for (int i = 0; i < 4; i++) {
15392e68ec1SJérôme Duval 		if (pthread_create(&tid[i], &attributes, threadStart, &i) != 0)
15492e68ec1SJérôme Duval 			fprintf(stderr, "couldn't create thread %d\n", i);
15592e68ec1SJérôme Duval 		printf("thread %d created\n", i);
15692e68ec1SJérôme Duval 	}
15792e68ec1SJérôme Duval 
15892e68ec1SJérôme Duval 	/*suspendAllThreads();*/
15992e68ec1SJérôme Duval 	printf("snoozing\n");
16092e68ec1SJérôme Duval 	usleep(2000000);
16192e68ec1SJérôme Duval 	printf("resuming all threads\n");
16292e68ec1SJérôme Duval 	resumeAllThreads();
16392e68ec1SJérôme Duval 	printf("resuming all threads done\n");
16492e68ec1SJérôme Duval }
165*d13211acSJérôme Duval 
166