xref: /netbsd-src/external/gpl3/gdb/dist/gdb/testsuite/gdb.rocm/multi-inferior-gpu.cpp (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1 /* This testcase is part of GDB, the GNU debugger.
2 
3    Copyright 2023-2024 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 <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <hip/hip_runtime.h>
22 
23 #define CHECK(cmd)                                                           \
24   {                                                                          \
25     hipError_t error = cmd;                                                  \
26     if (error != hipSuccess)                                                 \
27       {                                                                      \
28 	fprintf (stderr, "error: '%s'(%d) at %s:%d\n",                       \
29 		 hipGetErrorString (error), error, __FILE__, __LINE__);      \
30 	exit (EXIT_FAILURE);                                                 \
31       }                                                                      \
32   }
33 
34 __global__ void
35 kern ()
36 {
37   asm ("s_sleep 1");
38 }
39 
40 /* Spawn one child process per detected GPU.  */
41 
42 static int
43 parent (int argc, char **argv)
44 {
45   /* Identify how many GPUs we have, and spawn one child for each.  */
46   int num_devices;
47   CHECK (hipGetDeviceCount (&num_devices));
48 
49   /* Break here.  */
50 
51   for (int i = 0; i < num_devices; i++)
52     {
53       char n[32] = {};
54       snprintf (n, sizeof (n), "%d", i);
55       pid_t pid = fork ();
56       if (pid == -1)
57 	{
58 	  perror ("Fork failed");
59 	  return -1;
60 	}
61 
62       if (pid == 0)
63 	{
64 	  /* Exec to force the child to re-initialize the ROCm runtime.  */
65 	  if (execl (argv[0], argv[0], n, nullptr) == -1)
66 	    {
67 	      perror ("Failed to exec");
68 	      return -1;
69 	    }
70 	}
71     }
72 
73   /* Wait for all children.  */
74   while (true)
75     {
76       int ws;
77       pid_t ret = waitpid (-1, &ws, 0);
78       if (ret == -1 && errno == ECHILD)
79 	break;
80     }
81 
82   /* Last break here.  */
83   return 0;
84 }
85 
86 static int
87 child (int argc, char **argv)
88 {
89   int dev_number;
90   if (sscanf (argv[1], "%d", &dev_number) != 1)
91     {
92       fprintf (stderr, "Invalid argument \"%s\"\n", argv[1]);
93       return -1;
94     }
95 
96   CHECK (hipSetDevice (dev_number));
97   kern<<<1, 1>>> ();
98   CHECK (hipDeviceSynchronize ());
99   return 0;
100 }
101 
102 /* When called with no argument, identify how many AMDGPU devices are
103    available on the system and spawn one worker process per GPU.  If a
104    command-line argument is provided, it is the index of the GPU to use.  */
105 
106 int
107 main (int argc, char **argv)
108 {
109   if (argc <= 1)
110     return parent (argc, argv);
111   else
112     return child (argc, argv);
113 }
114