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