xref: /minix3/minix/tests/test51.c (revision cbc8a0df90ec437bc4bf50316f902f29128579e1)
1433d6423SLionel Sambuc /* Test51.c
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * Test getcontext, setcontext, makecontext, and swapcontext system calls.
4433d6423SLionel Sambuc  *
5433d6423SLionel Sambuc  * Part of this test is somewhat based on the GNU GCC ucontext test set.
6433d6423SLionel Sambuc  *
7433d6423SLionel Sambuc  */
8433d6423SLionel Sambuc 
9433d6423SLionel Sambuc #include <stdio.h>
10433d6423SLionel Sambuc #include <stdlib.h>
11433d6423SLionel Sambuc #include <unistd.h>
12433d6423SLionel Sambuc #include <errno.h>
13433d6423SLionel Sambuc #include <string.h>
14433d6423SLionel Sambuc #include <ucontext.h>
15433d6423SLionel Sambuc #include <math.h>
16433d6423SLionel Sambuc #include <fenv.h>
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc #include <sys/signal.h>
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc /* We can't use a global subtest variable reliably, because threads might
21433d6423SLionel Sambuc    change the value when we reenter a thread (i.e., report wrong subtest
22433d6423SLionel Sambuc    number). */
23433d6423SLionel Sambuc #define err(st, en) do { subtest = st; e(en); } while(0)
24433d6423SLionel Sambuc 
25433d6423SLionel Sambuc void do_calcs(void);
26433d6423SLionel Sambuc void do_child(void);
27433d6423SLionel Sambuc void do_parent(void);
28433d6423SLionel Sambuc void func1(int a, int b, int c, int d, int e, int f, int g, int h, int
29433d6423SLionel Sambuc 	i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s,
30433d6423SLionel Sambuc 	int t, int u, int v, int w, int x, int y, int z, int aa, int bb);
31433d6423SLionel Sambuc void func2(void);
32433d6423SLionel Sambuc void just_exit(void);
33433d6423SLionel Sambuc void test_brk(void);
34433d6423SLionel Sambuc void verify_main_reenter(void);
35433d6423SLionel Sambuc 
36433d6423SLionel Sambuc int max_error = 5;
37433d6423SLionel Sambuc #include "common.h"
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc #define SSIZE 32768
40433d6423SLionel Sambuc #define ROUNDS 10
41433d6423SLionel Sambuc #define SWAPS 10
42433d6423SLionel Sambuc 
43433d6423SLionel Sambuc 
44433d6423SLionel Sambuc int subtest;
45433d6423SLionel Sambuc ucontext_t ctx[3];
46433d6423SLionel Sambuc int entered_func1, entered_func2, reentered_main, entered_overflow;
47433d6423SLionel Sambuc 
48433d6423SLionel Sambuc static char st_stack[SSIZE];
49433d6423SLionel Sambuc static volatile int shift, global;
50433d6423SLionel Sambuc 
do_calcs(void)51433d6423SLionel Sambuc void do_calcs(void)
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc   float a, b, c, d, e;
54433d6423SLionel Sambuc   float foo, bar;
55433d6423SLionel Sambuc   int i;
56433d6423SLionel Sambuc 
57433d6423SLionel Sambuc   a = 1.1;
58433d6423SLionel Sambuc   b = 2.2;
59433d6423SLionel Sambuc   c = 3.3;
60433d6423SLionel Sambuc   d = 4.4;
61433d6423SLionel Sambuc   e = 5.5;
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc   foo = a * b; /* 2.42 */
64433d6423SLionel Sambuc   bar = c * d; /* 14.52 */
65433d6423SLionel Sambuc 
66433d6423SLionel Sambuc   i = 0;
67433d6423SLionel Sambuc   while(i < ROUNDS) {
68433d6423SLionel Sambuc 	foo += c; /* 5.72 */
69433d6423SLionel Sambuc 	foo *= d; /* 25.168 */
70433d6423SLionel Sambuc 	foo /= e; /* 4.5760 */
71433d6423SLionel Sambuc 	bar -= a; /* 13.42 */
72433d6423SLionel Sambuc 	bar *= b; /* 29.524 */
73433d6423SLionel Sambuc 	bar /= e; /* 5.3680 */
74433d6423SLionel Sambuc 
75433d6423SLionel Sambuc 	/* Undo */
76433d6423SLionel Sambuc 	foo *= e;
77433d6423SLionel Sambuc 	foo /= d;
78433d6423SLionel Sambuc 	foo -= c;
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc 	bar *= e;
81433d6423SLionel Sambuc 	bar /= b;
82433d6423SLionel Sambuc 	bar += a;
83433d6423SLionel Sambuc 
84433d6423SLionel Sambuc 	i++;
85433d6423SLionel Sambuc   }
86433d6423SLionel Sambuc   if(fabs(foo - (a * b)) > 0.0001) err(8, 1);
87433d6423SLionel Sambuc   if(fabs(bar - (c * d)) > 0.0001) err(8, 2);
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc 
do_child(void)90433d6423SLionel Sambuc void do_child(void)
91433d6423SLionel Sambuc {
92433d6423SLionel Sambuc   int s;
93433d6423SLionel Sambuc   s = 1;
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc   /* Initialize FPU context and verify it's set to round to nearest. */
96433d6423SLionel Sambuc   if (fegetround() != FE_TONEAREST) err(9, 1);
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc   /* Now we change the rounding to something else, and this should be preserved
99433d6423SLionel Sambuc      between context swaps. */
100433d6423SLionel Sambuc   if (fesetround(FE_DOWNWARD) != 0) err(9, 2);
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc   while(s < SWAPS) {
103433d6423SLionel Sambuc 	s++;
104433d6423SLionel Sambuc 	if (swapcontext(&ctx[2], &ctx[1]) == -1) err(9, 2);
105433d6423SLionel Sambuc 	do_calcs();
106433d6423SLionel Sambuc 	if (fegetround() != FE_DOWNWARD) err(9, 4);
107433d6423SLionel Sambuc   }
108433d6423SLionel Sambuc   quit();
109433d6423SLionel Sambuc }
110433d6423SLionel Sambuc 
do_parent(void)111433d6423SLionel Sambuc void do_parent(void)
112433d6423SLionel Sambuc {
113433d6423SLionel Sambuc   ucontext_t dummy;
114433d6423SLionel Sambuc   int s;
115433d6423SLionel Sambuc   s = 1;
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc   /* Initialize FPU context and verify it's set to round to nearest. */
118433d6423SLionel Sambuc   if (fegetround() != FE_TONEAREST) err(10, 1);
119433d6423SLionel Sambuc 
120433d6423SLionel Sambuc   /* Now we change the rounding to something else, and this should be preserved
121433d6423SLionel Sambuc      between context swaps. */
122433d6423SLionel Sambuc   if (fesetround(FE_UPWARD) != 0) err(10, 2);
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc   /* Quick check to make sure that getcontext does not reset the FPU state. */
125433d6423SLionel Sambuc   getcontext(&dummy);
126433d6423SLionel Sambuc 
127433d6423SLionel Sambuc   if (fegetround() != FE_UPWARD) err(10, 3);
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   while(s < SWAPS) {
130433d6423SLionel Sambuc 	do_calcs();
131433d6423SLionel Sambuc 	if (fegetround() != FE_UPWARD) err(10, 4);
132433d6423SLionel Sambuc 	s++;
133433d6423SLionel Sambuc 	if (swapcontext(&ctx[1], &ctx[2]) == -1) err(10, 5);
134433d6423SLionel Sambuc   }
135433d6423SLionel Sambuc   /* Returning to main thread through uc_link */
136433d6423SLionel Sambuc }
137433d6423SLionel Sambuc 
fail(void)138433d6423SLionel Sambuc static void fail(void)
139433d6423SLionel Sambuc {
140433d6423SLionel Sambuc   /* Shouldn't get here */
141433d6423SLionel Sambuc   err(5, 1);
142433d6423SLionel Sambuc }
143433d6423SLionel Sambuc 
func1(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j,int k,int l,int m,int n,int o,int p,int q,int r,int s,int t,int u,int v,int w,int x,int y,int z,int aa,int bb)144433d6423SLionel Sambuc void func1(int a, int b, int c, int d, int e, int f, int g,
145433d6423SLionel Sambuc 	   int h, int i, int j, int k, int l, int m, int n,
146433d6423SLionel Sambuc 	   int o, int p, int q, int r, int s, int t, int u,
147433d6423SLionel Sambuc 	   int v, int w, int x, int y, int z, int aa, int bb)
148433d6423SLionel Sambuc {
149433d6423SLionel Sambuc   if ( a != (0x0000001 << shift) ||  b != (0x0000004 << shift) ||
150433d6423SLionel Sambuc        c != (0x0000010 << shift) ||  d != (0x0000040 << shift) ||
151433d6423SLionel Sambuc        e != (0x0000100 << shift) ||  f != (0x0000400 << shift) ||
152433d6423SLionel Sambuc        g != (0x0001000 << shift) ||  h != (0x0004000 << shift) ||
153433d6423SLionel Sambuc        i != (0x0010000 << shift) ||  j != (0x0040000 << shift) ||
154433d6423SLionel Sambuc        k != (0x0100000 << shift) ||  l != (0x0400000 << shift) ||
155433d6423SLionel Sambuc        m != (0x1000000 << shift) ||  n != (0x4000000 << shift) ||
156433d6423SLionel Sambuc        o != (0x0000002 << shift) ||  p != (0x0000008 << shift) ||
157433d6423SLionel Sambuc        q != (0x0000020 << shift) ||  r != (0x0000080 << shift) ||
158433d6423SLionel Sambuc        s != (0x0000200 << shift) ||  t != (0x0000800 << shift) ||
159433d6423SLionel Sambuc        u != (0x0002000 << shift) ||  v != (0x0008000 << shift) ||
160433d6423SLionel Sambuc        w != (0x0020000 << shift) ||  x != (0x0080000 << shift) ||
161433d6423SLionel Sambuc        y != (0x0200000 << shift) ||  z != (0x0800000 << shift) ||
162433d6423SLionel Sambuc       aa != (0x2000000 << shift) || bb != (0x8000000 << shift) ) {
163433d6423SLionel Sambuc 	err(2, 1);
164433d6423SLionel Sambuc   }
165433d6423SLionel Sambuc 
166433d6423SLionel Sambuc   if (shift && swapcontext (&ctx[1], &ctx[2]) != 0) err(2, 2);
167433d6423SLionel Sambuc   shift++;
168433d6423SLionel Sambuc   entered_func1++;
169433d6423SLionel Sambuc }
170433d6423SLionel Sambuc 
func2(void)171433d6423SLionel Sambuc void func2(void)
172433d6423SLionel Sambuc {
173433d6423SLionel Sambuc   if (swapcontext(&ctx[2], &ctx[1]) != 0) err(3, 1);
174433d6423SLionel Sambuc   entered_func2++;
175433d6423SLionel Sambuc }
176433d6423SLionel Sambuc 
just_exit(void)177433d6423SLionel Sambuc void just_exit(void)
178433d6423SLionel Sambuc {
179433d6423SLionel Sambuc   if (errct == 0) printf("ok\n");
180433d6423SLionel Sambuc   _exit(1);
181433d6423SLionel Sambuc }
182433d6423SLionel Sambuc 
test_brk(void)183433d6423SLionel Sambuc void test_brk(void)
184433d6423SLionel Sambuc {
185433d6423SLionel Sambuc   char *big_stack;
186433d6423SLionel Sambuc 
187433d6423SLionel Sambuc   big_stack = malloc(16 * 1024 * 1024); /* 16 MB */
188433d6423SLionel Sambuc   /* If this fails, it is likely brk system call failed due stack/data segments
189433d6423SLionel Sambuc      collision detection. Unless the system really is low on memory, this is an
190433d6423SLionel Sambuc      error. */
191433d6423SLionel Sambuc   if (big_stack == NULL) err(7, 1);
192433d6423SLionel Sambuc }
193433d6423SLionel Sambuc 
verify_main_reenter(void)194433d6423SLionel Sambuc void verify_main_reenter(void)
195433d6423SLionel Sambuc {
196433d6423SLionel Sambuc   if (reentered_main == 0) err(4, 1);
197433d6423SLionel Sambuc }
198433d6423SLionel Sambuc 
199433d6423SLionel Sambuc int set_context_test_value;
set_context_test_thread1(void)200*cbc8a0dfSDavid van Moolenbroek static void set_context_test_thread1(void){
201433d6423SLionel Sambuc 	set_context_test_value |= 0x1;
202433d6423SLionel Sambuc 	setcontext(&ctx[2]);
203433d6423SLionel Sambuc 	err(1, 24);
204433d6423SLionel Sambuc 
205433d6423SLionel Sambuc }
206433d6423SLionel Sambuc 
set_context_test_thread2(void)207*cbc8a0dfSDavid van Moolenbroek static void set_context_test_thread2(void){
208433d6423SLionel Sambuc 	set_context_test_value |= 0x1 << 1;
209433d6423SLionel Sambuc 	setcontext(&ctx[0]);
210433d6423SLionel Sambuc 	err(1, 23);
211433d6423SLionel Sambuc }
212433d6423SLionel Sambuc 
main(void)213433d6423SLionel Sambuc int main(void)
214433d6423SLionel Sambuc {
215433d6423SLionel Sambuc   start(51);
216433d6423SLionel Sambuc 
217433d6423SLionel Sambuc   atexit(verify_main_reenter);
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc   /* Save current context in ctx[0] */
220433d6423SLionel Sambuc   if (getcontext(&ctx[0]) != 0) {
221433d6423SLionel Sambuc 	/* Don't verify reentering main, not going to happen */
222433d6423SLionel Sambuc 	atexit(just_exit);
223433d6423SLionel Sambuc 	err(1, 1);
224433d6423SLionel Sambuc   }
225433d6423SLionel Sambuc 
226433d6423SLionel Sambuc   ctx[1] = ctx[0];
227433d6423SLionel Sambuc   ctx[1].uc_stack.ss_sp = st_stack;
228433d6423SLionel Sambuc   ctx[1].uc_stack.ss_size = SSIZE;
229433d6423SLionel Sambuc   ctx[1].uc_link = &ctx[0]; /* When done running, return here */
230433d6423SLionel Sambuc 
231433d6423SLionel Sambuc   /* ctx[1] is going to run func1 and then return here (uc_link). */
232433d6423SLionel Sambuc   /* We'll see later on whether makecontext worked. */
233433d6423SLionel Sambuc   makecontext(&ctx[1], (void (*) (void)) func1, 28,
234433d6423SLionel Sambuc   	      (0x0000001 << shift), (0x0000004 << shift),
235433d6423SLionel Sambuc 	      (0x0000010 << shift), (0x0000040 << shift),
236433d6423SLionel Sambuc 	      (0x0000100 << shift), (0x0000400 << shift),
237433d6423SLionel Sambuc 	      (0x0001000 << shift), (0x0004000 << shift),
238433d6423SLionel Sambuc 	      (0x0010000 << shift), (0x0040000 << shift),
239433d6423SLionel Sambuc 	      (0x0100000 << shift), (0x0400000 << shift),
240433d6423SLionel Sambuc 	      (0x1000000 << shift), (0x4000000 << shift),
241433d6423SLionel Sambuc 	      (0x0000002 << shift), (0x0000008 << shift),
242433d6423SLionel Sambuc 	      (0x0000020 << shift), (0x0000080 << shift),
243433d6423SLionel Sambuc 	      (0x0000200 << shift), (0x0000800 << shift),
244433d6423SLionel Sambuc 	      (0x0002000 << shift), (0x0008000 << shift),
245433d6423SLionel Sambuc 	      (0x0020000 << shift), (0x0080000 << shift),
246433d6423SLionel Sambuc 	      (0x0200000 << shift), (0x0800000 << shift),
247433d6423SLionel Sambuc 	      (0x2000000 << shift), (0x8000000 << shift));
248433d6423SLionel Sambuc 
249433d6423SLionel Sambuc   if (++global == 1) {
250433d6423SLionel Sambuc 	/* First time we're here. Let's run ctx[1] and return to ctx[0] when
251433d6423SLionel Sambuc 	 * we're done. Note that we return to above the 'makecontext' call. */
252433d6423SLionel Sambuc 	if (setcontext(&ctx[1]) != 0) err(1, 2);
253433d6423SLionel Sambuc   }
254433d6423SLionel Sambuc   if (global != 2) {
255433d6423SLionel Sambuc 	/* When ++global was 1 we let ctx[1] run and returned to ctx[0], so
256433d6423SLionel Sambuc 	   above ++global is executed again and should've become 2. */
257433d6423SLionel Sambuc 	err(1, 3);
258433d6423SLionel Sambuc   }
259433d6423SLionel Sambuc 
260433d6423SLionel Sambuc   /* Setup ctx[2] to run func2 */
261433d6423SLionel Sambuc   if (getcontext(&ctx[2]) != 0) err(1, 4);
262433d6423SLionel Sambuc   ctx[2].uc_stack.ss_sp = malloc(SSIZE);
263433d6423SLionel Sambuc   ctx[2].uc_stack.ss_size = SSIZE;
264433d6423SLionel Sambuc   ctx[2].uc_link = &ctx[1];
265433d6423SLionel Sambuc   makecontext(&ctx[2], (void (*) (void)) func2, 0);
266433d6423SLionel Sambuc 
267433d6423SLionel Sambuc   /* Now things become tricky. ctx[2] is set up such that when it finishes
268433d6423SLionel Sambuc      running, and starts ctx[1] again. However, func1 swaps back to func2. Then,
269433d6423SLionel Sambuc      when func2 has finished running, we continue with ctx[1] and, finally, we
270433d6423SLionel Sambuc      return to ctx[0]. */
271433d6423SLionel Sambuc   if (swapcontext(&ctx[0], &ctx[2]) != 0) err(1, 5); /* makecontext failed? */
272433d6423SLionel Sambuc   reentered_main = 1;
273433d6423SLionel Sambuc 
274433d6423SLionel Sambuc   /* The call graph is as follows:
275433d6423SLionel Sambuc    *
276433d6423SLionel Sambuc    *                       ########
277433d6423SLionel Sambuc    *             /--------># main #
278433d6423SLionel Sambuc    *             7    /----########----\
279433d6423SLionel Sambuc    *             |    |    ^           |
280433d6423SLionel Sambuc    *             |    1    2           3
281433d6423SLionel Sambuc    *             |    V    |           V
282433d6423SLionel Sambuc    *          #########----/           #########
283433d6423SLionel Sambuc    *          # func1 #<-------4-------# func2 #
284433d6423SLionel Sambuc    *          #########--------5------>#########
285433d6423SLionel Sambuc    *                 ^                  |
286433d6423SLionel Sambuc    *                 |                  |
287433d6423SLionel Sambuc    *                 \---------6--------/
288433d6423SLionel Sambuc    *
289433d6423SLionel Sambuc    * Main calls func1, func1 increases entered_func1, and returns to main. Main
290433d6423SLionel Sambuc    * calls func2, swaps to func1, swaps to func2, which increases entered_func2,
291433d6423SLionel Sambuc    * continues with func1, which increases entered_func1 again, continues to
292433d6423SLionel Sambuc    * main, where reentered_main is set to 1. In effect, entered_func1 == 2,
293433d6423SLionel Sambuc    * entered_func2 == 1, reentered_main == 1. Verify that. */
294433d6423SLionel Sambuc 
295433d6423SLionel Sambuc   if (entered_func1 != 2) err(1, 6);
296433d6423SLionel Sambuc   if (entered_func2 != 1) err(1, 7);
297433d6423SLionel Sambuc   /* reentered_main == 1 is verified upon exit */
298433d6423SLionel Sambuc 
299433d6423SLionel Sambuc   /* Try to allocate too small a stack */
300433d6423SLionel Sambuc   free(ctx[2].uc_stack.ss_sp); /* Deallocate stack space first */
301433d6423SLionel Sambuc   if (getcontext(&ctx[2]) != 0) err(1, 8);
302433d6423SLionel Sambuc   ctx[2].uc_stack.ss_sp = malloc(MINSIGSTKSZ-1);
303433d6423SLionel Sambuc   ctx[2].uc_stack.ss_size = MINSIGSTKSZ-1;
304433d6423SLionel Sambuc   ctx[2].uc_link = &ctx[0];
305433d6423SLionel Sambuc   makecontext(&ctx[2], (void (*) (void)) fail, 0);
306433d6423SLionel Sambuc   /* Because makecontext is void, we can only detect an error by trying to use
307433d6423SLionel Sambuc      the invalid context */
308433d6423SLionel Sambuc   if (swapcontext(&ctx[0], &ctx[2]) == 0) err(1, 9);
309433d6423SLionel Sambuc 
310433d6423SLionel Sambuc   /* Try to allocate a huge stack to force the usage of brk/sbrk system call
311433d6423SLionel Sambuc      to enlarge the data segment. Because we are fiddling with the stack
312433d6423SLionel Sambuc      pointer, the OS might think the stack segment and data segment have
313433d6423SLionel Sambuc      collided and kill us. This is wrong and therefore the following should
314433d6423SLionel Sambuc      work. */
315433d6423SLionel Sambuc   free(ctx[2].uc_stack.ss_sp); /* Deallocate stack space first */
316433d6423SLionel Sambuc   if (getcontext(&ctx[2]) != 0) err(1, 14);
317433d6423SLionel Sambuc   ctx[2].uc_stack.ss_sp = malloc(8 * 1024 * 1024); /* 8 MB */
318433d6423SLionel Sambuc   ctx[2].uc_stack.ss_size = 8 * 1024 * 1024;
319433d6423SLionel Sambuc   ctx[2].uc_link = &ctx[0];
320433d6423SLionel Sambuc   makecontext(&ctx[2], (void (*) (void)) test_brk, 0);
321433d6423SLionel Sambuc   if (swapcontext(&ctx[0], &ctx[2]) != 0) err(1, 15);
322433d6423SLionel Sambuc 
323433d6423SLionel Sambuc   ctx[1].uc_link = &ctx[0];
324433d6423SLionel Sambuc   ctx[2].uc_link = NULL;
325433d6423SLionel Sambuc   makecontext(&ctx[1], (void (*) (void)) do_parent, 0);
326433d6423SLionel Sambuc   makecontext(&ctx[2], (void (*) (void)) do_child, 0);
327433d6423SLionel Sambuc   if (swapcontext(&ctx[0], &ctx[2]) == -1) err(1, 16);
328433d6423SLionel Sambuc 
329433d6423SLionel Sambuc   /* test setcontext  first do some cleanup */
330433d6423SLionel Sambuc 
331433d6423SLionel Sambuc   free(ctx[1].uc_stack.ss_sp);
332433d6423SLionel Sambuc   free(ctx[2].uc_stack.ss_sp);
333433d6423SLionel Sambuc 
334433d6423SLionel Sambuc   memset(&ctx[0],0,sizeof(ucontext_t));
335433d6423SLionel Sambuc   memset(&ctx[1],0,sizeof(ucontext_t));
336433d6423SLionel Sambuc   memset(&ctx[2],0,sizeof(ucontext_t));
337433d6423SLionel Sambuc 
338433d6423SLionel Sambuc 
339433d6423SLionel Sambuc   /* create 3 new contexts */
340433d6423SLionel Sambuc   volatile int cb =1;
341433d6423SLionel Sambuc 
342433d6423SLionel Sambuc   /* control will be returned here */
343433d6423SLionel Sambuc   set_context_test_value  = 0;
344433d6423SLionel Sambuc   if (getcontext(&ctx[0]) != 0) err(1, 17);
345433d6423SLionel Sambuc   if (set_context_test_value != 0x3) err(1, 20);
346433d6423SLionel Sambuc   if (cb == 1) {
347433d6423SLionel Sambuc     cb =0;
348433d6423SLionel Sambuc     if (getcontext(&ctx[1]) != 0) err(1, 18);
349433d6423SLionel Sambuc     if (getcontext(&ctx[2]) != 0) err(1, 19);
350433d6423SLionel Sambuc 
351433d6423SLionel Sambuc     // allocate new stacks */
352433d6423SLionel Sambuc     ctx[1].uc_stack.ss_sp = malloc(SSIZE);
353433d6423SLionel Sambuc     ctx[1].uc_stack.ss_size = SSIZE;
354433d6423SLionel Sambuc     ctx[2].uc_stack.ss_sp = malloc(SSIZE);
355433d6423SLionel Sambuc     ctx[2].uc_stack.ss_size = SSIZE;
356433d6423SLionel Sambuc 
357433d6423SLionel Sambuc     makecontext(&ctx[1],set_context_test_thread1,0);
358433d6423SLionel Sambuc     makecontext(&ctx[2],set_context_test_thread2,0);
359433d6423SLionel Sambuc     if( setcontext(&ctx[1]) != 0){
360433d6423SLionel Sambuc       err(1, 21);
361433d6423SLionel Sambuc     }
362433d6423SLionel Sambuc     err(1, 22);
363433d6423SLionel Sambuc   }
364433d6423SLionel Sambuc 
365433d6423SLionel Sambuc   quit();
366433d6423SLionel Sambuc   return(-1);
367433d6423SLionel Sambuc }
368433d6423SLionel Sambuc 
369