Home | History | Annotate | Line # | Download | only in gdb.base
      1      1.1  christos /* This testcase is part of GDB, the GNU debugger.
      2      1.1  christos 
      3  1.1.1.6  christos    Copyright 2016-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This program is free software; you can redistribute it and/or modify
      6      1.1  christos    it under the terms of the GNU General Public License as published by
      7      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      8      1.1  christos    (at your option) any later version.
      9      1.1  christos 
     10      1.1  christos    This program is distributed in the hope that it will be useful,
     11      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos    GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos    You should have received a copy of the GNU General Public License
     16      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17      1.1  christos 
     18      1.1  christos #define _GNU_SOURCE
     19      1.1  christos #include <stdlib.h>
     20      1.1  christos #include <unistd.h>
     21      1.1  christos #include <sched.h>
     22  1.1.1.5  christos #include <pthread.h>
     23      1.1  christos 
     24      1.1  christos static void
     25      1.1  christos marker ()
     26      1.1  christos {}
     27      1.1  christos 
     28      1.1  christos #define STACK_SIZE 0x1000
     29      1.1  christos 
     30  1.1.1.5  christos /* These are used to signal that the threads have started correctly.  The
     31  1.1.1.5  christos    GLOBAL_THREAD_COUNT is set to the number of threads in main, then
     32  1.1.1.5  christos    decremented (under a lock) in each new thread.  */
     33  1.1.1.5  christos pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
     34  1.1.1.5  christos int global_thread_count = 0;
     35  1.1.1.5  christos 
     36      1.1  christos static int
     37      1.1  christos clone_fn (void *unused)
     38      1.1  christos {
     39  1.1.1.5  christos   /* Signal that this thread has started correctly.  */
     40  1.1.1.5  christos   if (pthread_mutex_lock (&global_lock) != 0)
     41  1.1.1.5  christos     abort ();
     42  1.1.1.5  christos   global_thread_count--;
     43  1.1.1.5  christos   if (pthread_mutex_unlock (&global_lock) != 0)
     44  1.1.1.5  christos     abort ();
     45  1.1.1.5  christos 
     46      1.1  christos   return 0;
     47      1.1  christos }
     48      1.1  christos 
     49      1.1  christos int
     50      1.1  christos main (void)
     51      1.1  christos {
     52      1.1  christos   int i, pid;
     53      1.1  christos   unsigned char *stack[6];
     54      1.1  christos 
     55  1.1.1.5  christos   /* Due to bug gdb/19675 the cloned thread _might_ try to reenter main
     56  1.1.1.5  christos      (this depends on where the displaced instruction is placed for
     57  1.1.1.5  christos      execution).  However, if we do reenter main then lets ensure we fail
     58  1.1.1.5  christos      hard rather then just silently executing the code below.  */
     59  1.1.1.5  christos   static int started = 0;
     60  1.1.1.5  christos   if (!started)
     61  1.1.1.5  christos     started = 1;
     62  1.1.1.5  christos   else
     63  1.1.1.5  christos     abort ();
     64  1.1.1.5  christos 
     65      1.1  christos   for (i = 0; i < (sizeof (stack) / sizeof (stack[0])); i++)
     66      1.1  christos     stack[i] = malloc (STACK_SIZE);
     67      1.1  christos 
     68  1.1.1.5  christos   global_thread_count = (sizeof (stack) / sizeof (stack[0]));
     69  1.1.1.5  christos 
     70      1.1  christos   for (i = 0; i < (sizeof (stack) / sizeof (stack[0])); i++)
     71      1.1  christos     {
     72      1.1  christos       pid = clone (clone_fn, stack[i] + STACK_SIZE, CLONE_FILES | CLONE_VM,
     73      1.1  christos 		   NULL);
     74      1.1  christos     }
     75      1.1  christos 
     76      1.1  christos   for (i = 0; i < (sizeof (stack) / sizeof (stack[0])); i++)
     77      1.1  christos     free (stack[i]);
     78      1.1  christos 
     79  1.1.1.5  christos   /* Set an alarm so we don't end up stuck waiting for threads that might
     80  1.1.1.5  christos      never start correctly.  */
     81  1.1.1.5  christos   alarm (120);
     82  1.1.1.5  christos 
     83  1.1.1.5  christos   /* Now wait for all the threads to start up.  */
     84  1.1.1.5  christos   while (global_thread_count != 0)
     85  1.1.1.5  christos     {
     86  1.1.1.5  christos       /* Force memory barrier so GLOBAL_THREAD_COUNT will be refetched.  */
     87  1.1.1.5  christos       asm volatile ("" ::: "memory");
     88  1.1.1.5  christos       sleep (1);
     89  1.1.1.5  christos     }
     90  1.1.1.5  christos 
     91  1.1.1.5  christos   /* Call marker, this is what GDB is waiting for.  */
     92      1.1  christos   marker ();
     93      1.1  christos }
     94