]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 2001-2019 Free Software Foundation, Inc. |
92505456 MR |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
92505456 MR |
17 | |
18 | #include <errno.h> | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <ucontext.h> | |
23 | #include <unistd.h> | |
24 | ||
25 | static ucontext_t ctx[3]; | |
26 | ||
27 | static int was_in_f1; | |
28 | static int was_in_f2; | |
29 | ||
30 | static char st2[32768]; | |
31 | ||
32 | static volatile int flag; | |
33 | ||
34 | static void | |
35 | f1 (int a00, int a01, int a02, int a03, int a04, int a05, int a06, int a07, | |
36 | int a08, int a09, int a10, int a11, int a12, int a13, int a14, int a15, | |
37 | int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, | |
38 | int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, | |
39 | int a32) | |
40 | { | |
41 | printf ("start f1(a00=%08x,a01=%08x,a02=%08x,a03=%08x,\n" | |
42 | " a04=%08x,a05=%08x,a06=%08x,a07=%08x,\n" | |
43 | " a08=%08x,a09=%08x,a10=%08x,a11=%08x,\n" | |
44 | " a12=%08x,a13=%08x,a14=%08x,a15=%08x,\n" | |
45 | " a16=%08x,a17=%08x,a18=%08x,a19=%08x,\n" | |
46 | " a20=%08x,a21=%08x,a22=%08x,a23=%08x,\n" | |
47 | " a24=%08x,a25=%08x,a26=%08x,a27=%08x,\n" | |
48 | " a28=%08x,a29=%08x,a30=%08x,a31=%08x,\n" | |
49 | " a32=%08x) [%d]\n", | |
50 | a00, a01, a02, a03, a04, a05, a06, a07, | |
51 | a08, a09, a10, a11, a12, a13, a14, a15, | |
52 | a16, a17, a18, a19, a20, a21, a22, a23, | |
53 | a24, a25, a26, a27, a28, a29, a30, a31, | |
54 | a32, flag); | |
55 | ||
56 | if (a00 != (0x00000001 << flag) || a01 != (0x00000004 << flag) | |
57 | || a02 != (0x00000012 << flag) || a03 != (0x00000048 << flag) | |
58 | || a04 != (0x00000123 << flag) || a05 != (0x0000048d << flag) | |
59 | || a06 != (0x00001234 << flag) || a07 != (0x000048d1 << flag) | |
60 | || a08 != (0x00012345 << flag) || a09 != (0x00048d15 << flag) | |
61 | || a10 != (0x00123456 << flag) || a11 != (0x0048d159 << flag) | |
62 | || a12 != (0x01234567 << flag) || a13 != (0x048d159e << flag) | |
63 | || a14 != (0x12345678 << flag) || a15 != (0x48d159e2 << flag) | |
64 | || a16 != (0x23456789 << flag) || a17 != (0x8d159e26 << flag) | |
65 | || a18 != (0x3456789a << flag) || a19 != (0xd159e26a << flag) | |
66 | || a20 != (0x456789ab << flag) || a21 != (0x159e26af << flag) | |
67 | || a22 != (0x56789abc << flag) || a23 != (0x59e26af3 << flag) | |
68 | || a24 != (0x6789abcd << flag) || a25 != (0x9e26af37 << flag) | |
69 | || a26 != (0x789abcde << flag) || a27 != (0xe26af37b << flag) | |
70 | || a28 != (0x89abcdef << flag) || a29 != (0x26af37bc << flag) | |
71 | || a30 != (0x9abcdef0 << flag) || a31 != (0x6af37bc3 << flag) | |
72 | || a32 != (0xabcdef0f << flag)) | |
73 | { | |
74 | puts ("arg mismatch"); | |
75 | exit (-1); | |
76 | } | |
77 | ||
78 | if (flag && swapcontext (&ctx[1], &ctx[2]) != 0) | |
79 | { | |
80 | printf ("%s: swapcontext: %m\n", __FUNCTION__); | |
81 | exit (1); | |
82 | } | |
83 | printf ("finish f1 [%d]\n", flag); | |
84 | flag++; | |
85 | was_in_f1++; | |
86 | } | |
87 | ||
88 | static void | |
89 | f2 (void) | |
90 | { | |
91 | puts ("start f2"); | |
92 | if (swapcontext (&ctx[2], &ctx[1]) != 0) | |
93 | { | |
94 | printf ("%s: swapcontext: %m\n", __FUNCTION__); | |
95 | exit (1); | |
96 | } | |
97 | puts ("finish f2"); | |
98 | was_in_f2 = 1; | |
99 | } | |
100 | ||
101 | volatile int global; | |
102 | ||
103 | ||
104 | static int back_in_main; | |
105 | ||
106 | ||
107 | static void | |
108 | check_called (void) | |
109 | { | |
110 | if (back_in_main == 0) | |
111 | { | |
112 | puts ("program did not reach main again"); | |
113 | _exit (1); | |
114 | } | |
115 | } | |
116 | ||
117 | ||
118 | int | |
119 | main (void) | |
120 | { | |
121 | atexit (check_called); | |
122 | ||
123 | char st1[32768]; | |
124 | ||
125 | puts ("making contexts"); | |
126 | if (getcontext (&ctx[0]) != 0) | |
127 | { | |
128 | if (errno == ENOSYS) | |
129 | { | |
130 | back_in_main = 1; | |
131 | exit (0); | |
132 | } | |
133 | ||
134 | printf ("%s: getcontext: %m\n", __FUNCTION__); | |
135 | exit (1); | |
136 | } | |
137 | ||
ef634a94 AS |
138 | if (getcontext (&ctx[1]) != 0) |
139 | { | |
140 | printf ("%s: getcontext: %m\n", __FUNCTION__); | |
141 | exit (1); | |
142 | } | |
143 | ||
92505456 MR |
144 | ctx[1].uc_stack.ss_sp = st1; |
145 | ctx[1].uc_stack.ss_size = sizeof st1; | |
146 | ctx[1].uc_link = &ctx[0]; | |
ef634a94 AS |
147 | errno = 0; |
148 | makecontext (&ctx[1], (void (*) (void)) f1, 33, | |
149 | 0x00000001 << flag, 0x00000004 << flag, | |
150 | 0x00000012 << flag, 0x00000048 << flag, | |
151 | 0x00000123 << flag, 0x0000048d << flag, | |
152 | 0x00001234 << flag, 0x000048d1 << flag, | |
153 | 0x00012345 << flag, 0x00048d15 << flag, | |
154 | 0x00123456 << flag, 0x0048d159 << flag, | |
155 | 0x01234567 << flag, 0x048d159e << flag, | |
156 | 0x12345678 << flag, 0x48d159e2 << flag, | |
157 | 0x23456789 << flag, 0x8d159e26 << flag, | |
158 | 0x3456789a << flag, 0xd159e26a << flag, | |
159 | 0x456789ab << flag, 0x159e26af << flag, | |
160 | 0x56789abc << flag, 0x59e26af3 << flag, | |
161 | 0x6789abcd << flag, 0x9e26af37 << flag, | |
162 | 0x789abcde << flag, 0xe26af37b << flag, | |
163 | 0x89abcdef << flag, 0x26af37bc << flag, | |
164 | 0x9abcdef0 << flag, 0x6af37bc3 << flag, | |
165 | 0xabcdef0f << flag); | |
166 | ||
167 | /* Without this check, a stub makecontext can make us spin forever. */ | |
168 | if (errno == ENOSYS) | |
169 | { | |
170 | puts ("makecontext not implemented"); | |
171 | back_in_main = 1; | |
172 | return 0; | |
173 | } | |
92505456 MR |
174 | |
175 | /* Play some tricks with this context. */ | |
176 | if (++global == 1) | |
177 | if (setcontext (&ctx[1]) != 0) | |
178 | { | |
179 | printf ("%s: setcontext: %m\n", __FUNCTION__); | |
180 | exit (1); | |
181 | } | |
182 | if (global != 2) | |
183 | { | |
184 | printf ("%s: 'global' not incremented twice\n", __FUNCTION__); | |
185 | exit (1); | |
186 | } | |
187 | ||
188 | if (getcontext (&ctx[2]) != 0) | |
189 | { | |
190 | printf ("%s: second getcontext: %m\n", __FUNCTION__); | |
191 | exit (1); | |
192 | } | |
193 | ctx[2].uc_stack.ss_sp = st2; | |
194 | ctx[2].uc_stack.ss_size = sizeof st2; | |
195 | ctx[2].uc_link = &ctx[1]; | |
196 | makecontext (&ctx[2], f2, 0); | |
197 | ||
198 | puts ("swapping contexts"); | |
199 | if (swapcontext (&ctx[0], &ctx[2]) != 0) | |
200 | { | |
201 | printf ("%s: swapcontext: %m\n", __FUNCTION__); | |
202 | exit (1); | |
203 | } | |
204 | puts ("back at main program"); | |
205 | back_in_main = 1; | |
206 | ||
207 | if (was_in_f1 < 2) | |
208 | { | |
209 | puts ("didn't reach f1 twice"); | |
210 | exit (1); | |
211 | } | |
212 | if (was_in_f2 == 0) | |
213 | { | |
214 | puts ("didn't reach f2"); | |
215 | exit (1); | |
216 | } | |
217 | ||
218 | puts ("test succeeded"); | |
219 | return 0; | |
220 | } |