step-over-clone.c revision 1.1.1.6 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