1 /* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2023 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include <pthread.h> 19 #include <assert.h> 20 #include <stdlib.h> 21 #include <signal.h> 22 #include <unistd.h> 23 24 /* The delay that the main thread gives once all the worker threads have 25 reached the barrier before the main thread enters the function on which 26 GDB will have placed a breakpoint. */ 27 28 #define MAIN_THREAD_DELAY 2 29 30 /* The maximum time we allow this test program to run for before an alarm 31 signal is sent and everything will exit. */ 32 #define WATCHDOG_ALARM_TIME 600 33 34 /* Aliases for the signals used within this script. Each signal 35 corresponds to an action (from the FINAL_ACTION enum) that the signal 36 handler will perform. */ 37 38 #define SPIN_SIGNAL SIGUSR1 39 #define SYSCALL_SIGNAL SIGUSR2 40 41 /* Describe the final action that a thread should perform. */ 42 43 enum final_action 44 { 45 /* Thread should spin in an infinite loop. */ 46 SPIN = 0, 47 48 /* Thread should block in a syscall. */ 49 SYSCALL, 50 51 /* This is just a marker to allow for looping over the enum. */ 52 LAST_ACTION 53 }; 54 55 /* Where should the thread perform this action? */ 56 57 enum exec_location 58 { 59 /* Just a normal thread, on a normal stack. */ 60 NORMAL = 0, 61 62 /* In a signal handler, but use the normal stack. */ 63 SIGNAL_HANDLER, 64 65 /* In a signal handler using an alternative stack. */ 66 SIGNAL_ALT_STACK, 67 68 /* This is just a marker to allow for looping over the enum. */ 69 LAST_LOCACTION 70 }; 71 72 /* A descriptor for a single thread job. We create a new thread for each 73 job_description. */ 74 75 struct job_description 76 { 77 /* What action should this thread perform. */ 78 enum final_action action; 79 80 /* Where should the thread perform the action. */ 81 enum exec_location location; 82 83 /* The actual thread handle, so we can join with the thread. */ 84 pthread_t thread; 85 }; 86 87 /* A pthread barrier, used to (try) and synchronise the threads. */ 88 pthread_barrier_t global_barrier; 89 90 /* Return a list of jobs, and place the length of the list in *COUNT. */ 91 92 struct job_description * 93 get_job_list (int *count) 94 { 95 /* The number of jobs. */ 96 int num = LAST_ACTION * LAST_LOCACTION; 97 98 /* The uninitialised array of jobs. */ 99 struct job_description *list 100 = malloc (num * sizeof (struct job_description)); 101 assert (list != NULL); 102 103 /* Fill the array with all possible jobs. */ 104 for (int i = 0; i < (int) LAST_ACTION; ++i) 105 for (int j = 0; j < (int) LAST_LOCACTION; ++j) 106 { 107 int idx = (i * LAST_LOCACTION) + j; 108 list[idx].action = (enum final_action) i; 109 list[idx].location = (enum exec_location) j; 110 } 111 112 /* Return the array of jobs. */ 113 *count = num; 114 return list; 115 } 116 117 /* This function should never be called. If it is then an assertion will 118 trigger. */ 119 120 void 121 assert_not_reached (void) 122 { 123 assert (0); 124 } 125 126 /* The function for a SPIN action. Just spins in a loop. The LOCATION 127 argument exists so GDB can identify the expected context for this 128 function. */ 129 130 void 131 do_spin_task (enum exec_location location) 132 { 133 (void) location; 134 135 /* Let everyone know that we're about to perform our action. */ 136 int res = pthread_barrier_wait (&global_barrier); 137 assert (res == PTHREAD_BARRIER_SERIAL_THREAD || res == 0); 138 139 while (1) 140 { 141 /* Nothing. */ 142 } 143 } 144 145 /* The function for a SYSCALL action. Just spins in a loop. The LOCATION 146 argument exists so GDB can identify the expected context for this 147 function. */ 148 149 void 150 do_syscall_task (enum exec_location location) 151 { 152 (void) location; 153 154 /* Let everyone know that we're about to perform our action. */ 155 int res = pthread_barrier_wait (&global_barrier); 156 assert (res == PTHREAD_BARRIER_SERIAL_THREAD || res == 0); 157 158 sleep (600); 159 } 160 161 /* Return the required size for a sigaltstack. We start with a single 162 page, but do check against the system defined minimums. We don't run 163 much on the alternative stacks, so we don't need a huge one. */ 164 165 size_t 166 get_stack_size (void) 167 { 168 size_t size = getpagesize (); /* Arbitrary starting size. */ 169 if (size < SIGSTKSZ) 170 size = SIGSTKSZ; 171 if (size < MINSIGSTKSZ) 172 size = MINSIGSTKSZ; 173 return size; 174 } 175 176 /* A descriptor for an alternative stack. */ 177 178 struct stack_descriptor 179 { 180 /* The base address of the alternative stack. This is the address that 181 must be freed to release the memory used by this stack. */ 182 void *base; 183 184 /* The size of this alternative stack. Tracked just so we can query this 185 from GDB. */ 186 size_t size; 187 }; 188 189 /* Install an alternative signal stack. Return a descriptor for the newly 190 allocated alternative stack. */ 191 192 struct stack_descriptor 193 setup_alt_stack (void) 194 { 195 size_t stack_size = get_stack_size (); 196 197 void *stack_area = malloc (stack_size); 198 199 stack_t stk; 200 stk.ss_sp = stack_area; 201 stk.ss_flags = 0; 202 stk.ss_size = stack_size; 203 204 int res = sigaltstack (&stk, NULL); 205 assert (res == 0); 206 207 struct stack_descriptor desc; 208 desc.base = stack_area; 209 desc.size = stack_size; 210 211 return desc; 212 } 213 214 /* Return true (non-zero) if we are currently on the alternative stack, 215 otherwise, return false (zero). */ 216 217 int 218 on_alt_stack_p (void) 219 { 220 stack_t stk; 221 int res = sigaltstack (NULL, &stk); 222 assert (res == 0); 223 224 return (stk.ss_flags & SS_ONSTACK) != 0; 225 } 226 227 /* The signal handler function. All signals call here, so we use SIGNO 228 (the signal that was delivered) to decide what action to perform. This 229 function might, or might not, have been called on an alternative signal 230 stack. */ 231 232 void 233 signal_handler (int signo) 234 { 235 enum exec_location location 236 = on_alt_stack_p () ? SIGNAL_ALT_STACK : SIGNAL_HANDLER; 237 238 switch (signo) 239 { 240 case SPIN_SIGNAL: 241 do_spin_task (location); 242 break; 243 244 case SYSCALL_SIGNAL: 245 do_syscall_task (location); 246 break; 247 248 default: 249 assert_not_reached (); 250 } 251 } 252 253 /* The thread worker function. ARG is a job_description pointer which 254 describes what this thread is expected to do. This function always 255 returns a NULL pointer. */ 256 257 void * 258 thread_function (void *arg) 259 { 260 struct job_description *job = (struct job_description *) arg; 261 struct stack_descriptor desc = { NULL, 0 }; 262 int sa_flags = 0; 263 264 switch (job->location) 265 { 266 case NORMAL: 267 /* This thread performs the worker action on the current thread, 268 select the correct worker function based on the requested 269 action. */ 270 switch (job->action) 271 { 272 case SPIN: 273 do_spin_task (NORMAL); 274 break; 275 276 case SYSCALL: 277 do_syscall_task (NORMAL); 278 break; 279 280 default: 281 assert_not_reached (); 282 } 283 break; 284 285 case SIGNAL_ALT_STACK: 286 /* This thread is to perform its action in a signal handler on the 287 alternative stack. Install the alternative stack now, and then 288 fall through to the normal signal handler location code. */ 289 desc = setup_alt_stack (); 290 assert (desc.base != NULL); 291 assert (desc.size > 0); 292 sa_flags = SA_ONSTACK; 293 294 /* Fall through. */ 295 case SIGNAL_HANDLER: 296 { 297 /* This thread is to perform its action in a signal handler. We 298 might have just installed an alternative signal stack. */ 299 int signo, res; 300 301 /* Select the correct signal number so that the signal handler will 302 perform the required action. */ 303 switch (job->action) 304 { 305 case SPIN: 306 signo = SPIN_SIGNAL; 307 break; 308 309 case SYSCALL: 310 signo = SYSCALL_SIGNAL; 311 break; 312 313 default: 314 assert_not_reached (); 315 } 316 317 /* Now setup the signal handler. */ 318 struct sigaction sa; 319 sa.sa_handler = signal_handler; 320 sigfillset (&sa.sa_mask); 321 sa.sa_flags = sa_flags; 322 res = sigaction (signo, &sa, NULL); 323 assert (res == 0); 324 325 /* Send the signal to this thread. */ 326 res = pthread_kill (job->thread, signo); 327 assert (res == 0); 328 } 329 break; 330 331 default: 332 assert_not_reached (); 333 }; 334 335 /* Free the alt-stack if we allocated one, if not DESC.BASE will be 336 NULL so this call is fine. */ 337 free (desc.base); 338 339 /* Thread complete. */ 340 return NULL; 341 } 342 343 void 344 start_job (struct job_description *job) 345 { 346 int res; 347 348 res = pthread_create (&job->thread, NULL, thread_function, job); 349 assert (res == 0); 350 } 351 352 /* Join with the thread for JOB. This will block until the thread for JOB 353 has finished. */ 354 355 void 356 finalise_job (struct job_description *job) 357 { 358 int res; 359 void *retval; 360 361 res = pthread_join (job->thread, &retval); 362 assert (res == 0); 363 assert (retval == NULL); 364 } 365 366 /* Function that GDB can place a breakpoint on. */ 367 368 void 369 breakpt (void) 370 { 371 /* Nothing. */ 372 } 373 374 /* Function that triggers a crash, if the user has setup their environment 375 correctly this will dump a core file, which GDB can then examine. */ 376 377 void 378 crash_function (void) 379 { 380 volatile int *p = 0; 381 volatile int n = *p; 382 (void) n; 383 } 384 385 /* Entry point. */ 386 387 int 388 main () 389 { 390 int job_count, res; 391 struct job_description *jobs = get_job_list (&job_count); 392 393 /* This test is going to park some threads inside infinite loops. Just 394 in case this program is left running, install an alarm that will cause 395 everything to exit. */ 396 alarm (WATCHDOG_ALARM_TIME); 397 398 /* We want each worker thread (of which there are JOB_COUNT) plus the 399 main thread (hence + 1) to wait at the barrier. */ 400 res = pthread_barrier_init (&global_barrier, NULL, job_count + 1); 401 assert (res == 0); 402 403 /* Start all the jobs. */ 404 for (int i = 0; i < job_count; ++i) 405 start_job (&jobs[i]); 406 407 /* Notify all the worker threads that we're waiting for them. */ 408 res = pthread_barrier_wait (&global_barrier); 409 assert (res == PTHREAD_BARRIER_SERIAL_THREAD || res == 0); 410 411 /* All we know at this point is that all the worker threads have reached 412 the barrier, which is just before they perform their action. But we 413 really want them to start their action. 414 415 There's really no way we can be 100% certain that the worker threads 416 have started their action, all we can do is wait for a short while and 417 hope that the machine we're running on is not too slow. */ 418 sleep (MAIN_THREAD_DELAY); 419 420 /* A function that GDB can place a breakpoint on. By the time we get 421 here we are as sure as we can be that all of the worker threads have 422 started and are in their worker action (spinning, or syscall). */ 423 breakpt (); 424 425 /* If GDB is not attached then this function will cause a crash, which 426 can be used to dump a core file, which GDB can then analyse. */ 427 crash_function (); 428 429 /* Due to the crash we never expect to get here. Plus the worker actions 430 never terminate. But for completeness, here's where we join with all 431 the worker threads. */ 432 for (int i = 0; i < job_count; ++i) 433 finalise_job (&jobs[i]); 434 435 /* Cleanup the barrier. */ 436 res = pthread_barrier_destroy (&global_barrier); 437 assert (res == 0); 438 439 /* And clean up the jobs list. */ 440 free (jobs); 441 442 return 0; 443 } 444