2.9
[glibc/nacl-glibc.git] / manual / examples / swapcontext.c
blobf733510f8820dca69810e3140c079ab058a5079e
1 #include <signal.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <ucontext.h>
5 #include <sys/time.h>
7 /* Set by the signal handler. */
8 static volatile int expired;
10 /* The contexts. */
11 static ucontext_t uc[3];
13 /* We do only a certain number of switches. */
14 static int switches;
17 /* This is the function doing the work. It is just a
18 skeleton, real code has to be filled in. */
19 static void
20 f (int n)
22 int m = 0;
23 while (1)
25 /* This is where the work would be done. */
26 if (++m % 100 == 0)
28 putchar ('.');
29 fflush (stdout);
32 /* Regularly the @var{expire} variable must be checked. */
33 if (expired)
35 /* We do not want the program to run forever. */
36 if (++switches == 20)
37 return;
39 printf ("\nswitching from %d to %d\n", n, 3 - n);
40 expired = 0;
41 /* Switch to the other context, saving the current one. */
42 swapcontext (&uc[n], &uc[3 - n]);
47 /* This is the signal handler which simply set the variable. */
48 void
49 handler (int signal)
51 expired = 1;
55 int
56 main (void)
58 struct sigaction sa;
59 struct itimerval it;
60 char st1[8192];
61 char st2[8192];
63 /* Initialize the data structures for the interval timer. */
64 sa.sa_flags = SA_RESTART;
65 sigfillset (&sa.sa_mask);
66 sa.sa_handler = handler;
67 it.it_interval.tv_sec = 0;
68 it.it_interval.tv_usec = 1;
69 it.it_value = it.it_interval;
71 /* Install the timer and get the context we can manipulate. */
72 if (sigaction (SIGPROF, &sa, NULL) < 0
73 || setitimer (ITIMER_PROF, &it, NULL) < 0
74 || getcontext (&uc[1]) == -1
75 || getcontext (&uc[2]) == -1)
76 abort ();
78 /* Create a context with a separate stack which causes the
79 function @code{f} to be call with the parameter @code{1}.
80 Note that the @code{uc_link} points to the main context
81 which will cause the program to terminate once the function
82 return. */
83 uc[1].uc_link = &uc[0];
84 uc[1].uc_stack.ss_sp = st1;
85 uc[1].uc_stack.ss_size = sizeof st1;
86 makecontext (&uc[1], (void (*) (void)) f, 1, 1);
88 /* Similarly, but @code{2} is passed as the parameter to @code{f}. */
89 uc[2].uc_link = &uc[0];
90 uc[2].uc_stack.ss_sp = st2;
91 uc[2].uc_stack.ss_size = sizeof st2;
92 makecontext (&uc[2], (void (*) (void)) f, 1, 2);
94 /* Start running. */
95 swapcontext (&uc[0], &uc[1]);
96 putchar ('\n');
98 return 0;