xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame^] | 1 | /* Copyright (C) 2001-2016 Free Software Foundation, Inc. |
| 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 |
| 15 | License along with the GNU C Library; if not, see |
| 16 | <http://www.gnu.org/licenses/>. */ |
| 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 | |
| 138 | if (getcontext (&ctx[1]) != 0) |
| 139 | { |
| 140 | printf ("%s: getcontext: %m\n", __FUNCTION__); |
| 141 | exit (1); |
| 142 | } |
| 143 | |
| 144 | ctx[1].uc_stack.ss_sp = st1; |
| 145 | ctx[1].uc_stack.ss_size = sizeof st1; |
| 146 | ctx[1].uc_link = &ctx[0]; |
| 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 | } |
| 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 | } |