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