| /* This testcase is part of GDB, the GNU debugger. |
| |
| Copyright 2023-2024 Free Software Foundation, Inc. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include <unistd.h> |
| #include <hip/hip_runtime.h> |
| |
| #define CHECK(cmd) \ |
| { \ |
| hipError_t error = cmd; \ |
| if (error != hipSuccess) \ |
| { \ |
| fprintf (stderr, "error: '%s'(%d) at %s:%d\n", \ |
| hipGetErrorString (error), error, __FILE__, __LINE__); \ |
| exit (EXIT_FAILURE); \ |
| } \ |
| } |
| |
| __global__ void |
| kern () |
| { |
| asm ("s_sleep 1"); |
| } |
| |
| /* Spawn one child process per detected GPU. */ |
| |
| static int |
| parent (int argc, char **argv) |
| { |
| /* Identify how many GPUs we have, and spawn one child for each. */ |
| int num_devices; |
| CHECK (hipGetDeviceCount (&num_devices)); |
| |
| /* Break here. */ |
| |
| for (int i = 0; i < num_devices; i++) |
| { |
| char n[32] = {}; |
| snprintf (n, sizeof (n), "%d", i); |
| pid_t pid = fork (); |
| if (pid == -1) |
| { |
| perror ("Fork failed"); |
| return -1; |
| } |
| |
| if (pid == 0) |
| { |
| /* Exec to force the child to re-initialize the ROCm runtime. */ |
| if (execl (argv[0], argv[0], n, nullptr) == -1) |
| { |
| perror ("Failed to exec"); |
| return -1; |
| } |
| } |
| } |
| |
| /* Wait for all children. */ |
| while (true) |
| { |
| int ws; |
| pid_t ret = waitpid (-1, &ws, 0); |
| if (ret == -1 && errno == ECHILD) |
| break; |
| } |
| |
| /* Last break here. */ |
| return 0; |
| } |
| |
| static int |
| child (int argc, char **argv) |
| { |
| int dev_number; |
| if (sscanf (argv[1], "%d", &dev_number) != 1) |
| { |
| fprintf (stderr, "Invalid argument \"%s\"\n", argv[1]); |
| return -1; |
| } |
| |
| CHECK (hipSetDevice (dev_number)); |
| kern<<<1, 1>>> (); |
| CHECK (hipDeviceSynchronize ()); |
| return 0; |
| } |
| |
| /* When called with no argument, identify how many AMDGPU devices are |
| available on the system and spawn one worker process per GPU. If a |
| command-line argument is provided, it is the index of the GPU to use. */ |
| |
| int |
| main (int argc, char **argv) |
| { |
| if (argc <= 1) |
| return parent (argc, argv); |
| else |
| return child (argc, argv); |
| } |