1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2023 Free Software Foundation, Inc.
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.
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.
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/>. */
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. */
28 #define MAIN_THREAD_DELAY 2
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
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. */
38 #define SPIN_SIGNAL SIGUSR1
39 #define SYSCALL_SIGNAL SIGUSR2
41 /* Describe the final action that a thread should perform. */
45 /* Thread should spin in an infinite loop. */
48 /* Thread should block in a syscall. */
51 /* This is just a marker to allow for looping over the enum. */
55 /* Where should the thread perform this action? */
59 /* Just a normal thread, on a normal stack. */
62 /* In a signal handler, but use the normal stack. */
65 /* In a signal handler using an alternative stack. */
68 /* This is just a marker to allow for looping over the enum. */
72 /* A descriptor for a single thread job. We create a new thread for each
75 struct job_description
77 /* What action should this thread perform. */
78 enum final_action action
;
80 /* Where should the thread perform the action. */
81 enum exec_location location
;
83 /* The actual thread handle, so we can join with the thread. */
87 /* A pthread barrier, used to (try) and synchronise the threads. */
88 pthread_barrier_t global_barrier
;
90 /* Return a list of jobs, and place the length of the list in *COUNT. */
92 struct job_description
*
93 get_job_list (int *count
)
95 /* The number of jobs. */
96 int num
= LAST_ACTION
* LAST_LOCACTION
;
98 /* The uninitialised array of jobs. */
99 struct job_description
*list
100 = malloc (num
* sizeof (struct job_description
));
101 assert (list
!= NULL
);
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
)
107 int idx
= (i
* LAST_LOCACTION
) + j
;
108 list
[idx
].action
= (enum final_action
) i
;
109 list
[idx
].location
= (enum exec_location
) j
;
112 /* Return the array of jobs. */
117 /* This function should never be called. If it is then an assertion will
121 assert_not_reached (void)
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
131 do_spin_task (enum exec_location location
)
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);
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
150 do_syscall_task (enum exec_location location
)
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);
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. */
166 get_stack_size (void)
168 size_t size
= getpagesize (); /* Arbitrary starting size. */
171 if (size
< MINSIGSTKSZ
)
176 /* A descriptor for an alternative stack. */
178 struct stack_descriptor
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. */
184 /* The size of this alternative stack. Tracked just so we can query this
189 /* Install an alternative signal stack. Return a descriptor for the newly
190 allocated alternative stack. */
192 struct stack_descriptor
193 setup_alt_stack (void)
195 size_t stack_size
= get_stack_size ();
197 void *stack_area
= malloc (stack_size
);
200 stk
.ss_sp
= stack_area
;
202 stk
.ss_size
= stack_size
;
204 int res
= sigaltstack (&stk
, NULL
);
207 struct stack_descriptor desc
;
208 desc
.base
= stack_area
;
209 desc
.size
= stack_size
;
214 /* Return true (non-zero) if we are currently on the alternative stack,
215 otherwise, return false (zero). */
218 on_alt_stack_p (void)
221 int res
= sigaltstack (NULL
, &stk
);
224 return (stk
.ss_flags
& SS_ONSTACK
) != 0;
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
233 signal_handler (int signo
)
235 enum exec_location location
236 = on_alt_stack_p () ? SIGNAL_ALT_STACK
: SIGNAL_HANDLER
;
241 do_spin_task (location
);
245 do_syscall_task (location
);
249 assert_not_reached ();
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. */
258 thread_function (void *arg
)
260 struct job_description
*job
= (struct job_description
*) arg
;
261 struct stack_descriptor desc
= { NULL
, 0 };
264 switch (job
->location
)
267 /* This thread performs the worker action on the current thread,
268 select the correct worker function based on the requested
273 do_spin_task (NORMAL
);
277 do_syscall_task (NORMAL
);
281 assert_not_reached ();
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
;
297 /* This thread is to perform its action in a signal handler. We
298 might have just installed an alternative signal stack. */
301 /* Select the correct signal number so that the signal handler will
302 perform the required action. */
310 signo
= SYSCALL_SIGNAL
;
314 assert_not_reached ();
317 /* Now setup the signal handler. */
319 sa
.sa_handler
= signal_handler
;
320 sigfillset (&sa
.sa_mask
);
321 sa
.sa_flags
= sa_flags
;
322 res
= sigaction (signo
, &sa
, NULL
);
325 /* Send the signal to this thread. */
326 res
= pthread_kill (job
->thread
, signo
);
332 assert_not_reached ();
335 /* Free the alt-stack if we allocated one, if not DESC.BASE will be
336 NULL so this call is fine. */
339 /* Thread complete. */
344 start_job (struct job_description
*job
)
348 res
= pthread_create (&job
->thread
, NULL
, thread_function
, job
);
352 /* Join with the thread for JOB. This will block until the thread for JOB
356 finalise_job (struct job_description
*job
)
361 res
= pthread_join (job
->thread
, &retval
);
363 assert (retval
== NULL
);
366 /* Function that GDB can place a breakpoint on. */
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. */
378 crash_function (void)
391 struct job_description
*jobs
= get_job_list (&job_count
);
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
);
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);
403 /* Start all the jobs. */
404 for (int i
= 0; i
< job_count
; ++i
)
405 start_job (&jobs
[i
]);
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);
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.
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
);
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). */
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. */
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
]);
435 /* Cleanup the barrier. */
436 res
= pthread_barrier_destroy (&global_barrier
);
439 /* And clean up the jobs list. */