Home | History | Annotate | Line # | Download | only in gdb.threads
      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