Skip to content

Commit 5a0b205

Browse files
committed
gdb/testsuite/gdb.rocm: generalize the multi-inferior driver program
Generalize multi-inferior-gpu.cpp into a shared driver for the multi-inferior tests so the breakpoint markers the lib/rocm.exp helpers rely on live in one program instead of being duplicated. The child count is taken from argv when given and otherwise defaults to the number of GPU devices found at runtime, and each child re-execs itself through a "child" argv dispatch. Give rocm_multi_inferior_run_to_kernels default argument values so callers that want runtime discovery can omit them.
1 parent a746b09 commit 5a0b205

3 files changed

Lines changed: 79 additions & 41 deletions

File tree

gdb/testsuite/gdb.rocm/multi-inferior-gpu.cpp

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,28 @@
1515
You should have received a copy of the GNU General Public License
1616
along with this program. If not, see <http://www.gnu.org/licenses/>. */
1717

18+
/* Shared driver program for the gdb.rocm multi-inferior tests.
19+
20+
The parent process forks N children; each child re-execs itself so
21+
that its GPU runtime is initialized in a clean address space, then
22+
launches its own GPU kernel. Re-exec'ing makes each child a separate
23+
process from the operating system's point of view, which is what the
24+
multi-inferior tests debug concurrently.
25+
26+
N comes from argv[1] when given; otherwise it defaults to the number
27+
of GPU devices found at runtime (one child per device). The
28+
companion .exp helpers in lib/rocm.exp plant breakpoints on the
29+
pre-fork and post-join source markers and on the kernel. */
30+
1831
#include <sys/types.h>
1932
#include <sys/wait.h>
2033
#include <unistd.h>
2134
#include <hip/hip_runtime.h>
35+
#include <errno.h>
2236
#include <stdio.h>
2337
#include <stdlib.h>
38+
#include <string.h>
39+
#include <string>
2440

2541
#include "rocm-test-utils.h"
2642

@@ -30,77 +46,99 @@ kern ()
3046
asm ("s_sleep 1");
3147
}
3248

33-
/* Spawn one child process per detected GPU. */
49+
static int
50+
child (int argc, char **argv)
51+
{
52+
if (argc < 4)
53+
{
54+
fprintf (stderr, "%s: expected: child <idx> <num_devices>\n",
55+
argv[0]);
56+
return -1;
57+
}
58+
59+
int idx = atoi (argv[2]);
60+
int num_devices = atoi (argv[3]);
61+
if (num_devices <= 0)
62+
{
63+
fprintf (stderr, "child %d: invalid num_devices %d\n", idx,
64+
num_devices);
65+
return -1;
66+
}
67+
68+
CHECK (hipSetDevice (idx % num_devices));
69+
kern<<<1, 1>>> ();
70+
CHECK (hipDeviceSynchronize ());
71+
return 0;
72+
}
73+
74+
/* Spawn NUM_CHILDREN child processes. When NUM_CHILDREN is not
75+
positive, spawn one child per detected GPU device. */
3476

3577
static int
36-
parent (int argc, char **argv)
78+
parent (const char *argv0, int num_children)
3779
{
38-
/* Identify how many GPUs we have, and spawn one child for each. */
3980
int num_devices;
4081
CHECK (hipGetDeviceCount (&num_devices));
82+
if (num_devices <= 0)
83+
{
84+
fprintf (stderr, "no GPU devices available\n");
85+
return -1;
86+
}
87+
88+
if (num_children <= 0)
89+
num_children = num_devices;
4190

4291
/* Break here. */
4392

44-
for (int i = 0; i < num_devices; i++)
93+
for (int i = 0; i < num_children; i++)
4594
{
46-
char n[32] = {};
47-
snprintf (n, sizeof (n), "%d", i);
95+
std::string idx_str = std::to_string (i);
96+
std::string ndev_str = std::to_string (num_devices);
97+
4898
pid_t pid = fork ();
4999
if (pid == -1)
50100
{
51-
perror ("Fork failed");
101+
perror ("fork");
52102
return -1;
53103
}
54104

55105
if (pid == 0)
56106
{
57-
/* Exec to force the child to re-initialize the ROCm runtime. */
58-
if (execl (argv[0], argv[0], n, nullptr) == -1)
107+
if (execl (argv0, argv0, "child", idx_str.c_str (),
108+
ndev_str.c_str (), (char *) nullptr) == -1)
59109
{
60-
perror ("Failed to exec");
61-
return -1;
110+
perror ("execl");
111+
_exit (127);
62112
}
63113
}
64114
}
65115

66-
/* Wait for all children. */
116+
/* Reap every child. Any non-zero exit from a child is a failure
117+
(e.g. a runtime initialization failure under contention). */
118+
int failed = 0;
67119
while (true)
68120
{
69121
int ws;
70122
pid_t ret = waitpid (-1, &ws, 0);
71123
if (ret == -1 && errno == ECHILD)
72124
break;
125+
if (ret > 0 && (!WIFEXITED (ws) || WEXITSTATUS (ws) != 0))
126+
failed++;
73127
}
74128

75129
/* Last break here. */
76-
return 0;
77-
}
78-
79-
static int
80-
child (int argc, char **argv)
81-
{
82-
int dev_number;
83-
if (sscanf (argv[1], "%d", &dev_number) != 1)
84-
{
85-
fprintf (stderr, "Invalid argument \"%s\"\n", argv[1]);
86-
return -1;
87-
}
88-
89-
CHECK (hipSetDevice (dev_number));
90-
kern<<<1, 1>>> ();
91-
CHECK (hipDeviceSynchronize ());
92-
return 0;
130+
return failed == 0 ? 0 : 1;
93131
}
94132

95-
/* When called with no argument, identify how many AMDGPU devices are
96-
available on the system and spawn one worker process per GPU. If a
97-
command-line argument is provided, it is the index of the GPU to use. */
98-
99133
int
100134
main (int argc, char **argv)
101135
{
102-
if (argc <= 1)
103-
return parent (argc, argv);
104-
else
136+
if (argc >= 2 && strcmp (argv[1], "child") == 0)
105137
return child (argc, argv);
138+
139+
int num_children = 0;
140+
if (argc >= 2)
141+
num_children = atoi (argv[1]);
142+
143+
return parent (argv[0], num_children);
106144
}

gdb/testsuite/gdb.rocm/multi-inferior-gpu.exp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ proc do_test {} {
3232
with_rocm_gpu_lock {
3333
# Spawn one child inferior per detected GPU. The child count
3434
# is discovered from "num_devices" at the pre-fork stop.
35-
set threads [rocm_multi_inferior_run_to_kernels "" ""]
35+
set threads [rocm_multi_inferior_run_to_kernels]
3636
rocm_multi_inferior_drain $threads
3737
}
3838
}

gdb/testsuite/lib/rocm.exp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -686,21 +686,21 @@ gdb_caching_proc compiler_dwarf_language {} {
686686
# run the parent to the pre-fork breakpoint, resume everything in the
687687
# background, and wait for one "kern" breakpoint stop per child.
688688
#
689-
# args_list - arguments passed via "set args" ("" for none).
689+
# arg_list - arguments passed via "set args" ("" for none).
690690
# expected - number of child stops to wait for. If "", it is read
691691
# from the "num_devices" value at the pre-fork stop.
692692
#
693693
# Return the list of stopped GPU thread ids (one per child).
694694

695-
proc rocm_multi_inferior_run_to_kernels { args_list expected } {
695+
proc rocm_multi_inferior_run_to_kernels { {arg_list ""} {expected ""} } {
696696
clean_restart
697697
gdb_load $::binfile
698698

699699
gdb_test_no_output "set non-stop on"
700700
gdb_test_no_output "set detach-on-fork off"
701701
gdb_test_no_output "set follow-fork parent"
702-
if { $args_list ne "" } {
703-
gdb_test_no_output "set args $args_list"
702+
if { $arg_list ne "" } {
703+
gdb_test_no_output "set args $arg_list"
704704
}
705705

706706
gdb_breakpoint [gdb_get_line_number "Break here"]

0 commit comments

Comments
 (0)