| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <ucontext.h> |
| #include <sys/time.h> |
| |
| /* Set by the signal handler. */ |
| static volatile int expired; |
| |
| /* The contexts. */ |
| static ucontext_t uc[3]; |
| |
| /* We do only a certain number of switches. */ |
| static int switches; |
| |
| |
| /* This is the function doing the work. It is just a |
| skeleton, real code has to be filled in. */ |
| static void |
| f (int n) |
| { |
| int m = 0; |
| while (1) |
| { |
| /* This is where the work would be done. */ |
| if (++m % 100 == 0) |
| { |
| putchar ('.'); |
| fflush (stdout); |
| } |
| |
| /* Regularly the @var{expire} variable must be checked. */ |
| if (expired) |
| { |
| /* We do not want the program to run forever. */ |
| if (++switches == 20) |
| return; |
| |
| printf ("\nswitching from %d to %d\n", n, 3 - n); |
| expired = 0; |
| /* Switch to the other context, saving the current one. */ |
| swapcontext (&uc[n], &uc[3 - n]); |
| } |
| } |
| } |
| |
| /* This is the signal handler which simply set the variable. */ |
| void |
| handler (int signal) |
| { |
| expired = 1; |
| } |
| |
| |
| int |
| main (void) |
| { |
| struct sigaction sa; |
| struct itimerval it; |
| char st1[8192]; |
| char st2[8192]; |
| |
| /* Initialize the data structures for the interval timer. */ |
| sa.sa_flags = SA_RESTART; |
| sigfillset (&sa.sa_mask); |
| sa.sa_handler = handler; |
| it.it_interval.tv_sec = 0; |
| it.it_interval.tv_usec = 1; |
| it.it_value = it.it_interval; |
| |
| /* Install the timer and get the context we can manipulate. */ |
| if (sigaction (SIGPROF, &sa, NULL) < 0 |
| || setitimer (ITIMER_PROF, &it, NULL) < 0 |
| || getcontext (&uc[1]) == -1 |
| || getcontext (&uc[2]) == -1) |
| abort (); |
| |
| /* Create a context with a separate stack which causes the |
| function @code{f} to be call with the parameter @code{1}. |
| Note that the @code{uc_link} points to the main context |
| which will cause the program to terminate once the function |
| return. */ |
| uc[1].uc_link = &uc[0]; |
| uc[1].uc_stack.ss_sp = st1; |
| uc[1].uc_stack.ss_size = sizeof st1; |
| makecontext (&uc[1], (void (*) (void)) f, 1, 1); |
| |
| /* Similarly, but @code{2} is passed as the parameter to @code{f}. */ |
| uc[2].uc_link = &uc[0]; |
| uc[2].uc_stack.ss_sp = st2; |
| uc[2].uc_stack.ss_size = sizeof st2; |
| makecontext (&uc[2], (void (*) (void)) f, 1, 2); |
| |
| /* Start running. */ |
| swapcontext (&uc[0], &uc[1]); |
| putchar ('\n'); |
| |
| return 0; |
| } |