[PATCH 2/3] lib/amdgpu: Introduce process spawning with synchronization
vitaly.prosyak at amd.com
vitaly.prosyak at amd.com
Tue Nov 26 17:29:22 UTC 2024
From: Vitaly Prosyak <vitaly.prosyak at amd.com>
Added functions to spawn new processes with synchronization capabilities.
This feature enables execution synchronization between processes using
shared memory and semaphores, allowing for flexible and dynamic process
management.
Cc: Jesse Zhang <jesse.zhang at amd.com>
Cc: Christian Koenig <christian.koenig at amd.com>
Cc: Alexander Deucher <alexander.deucher at amd.com>
Cc: Leo Liu <leo.liu at amd.com>
Cc: Boyuan Zhang <boyuan.zhang at amd.com>
Signed-off-by: Vitaly Prosyak <vitaly.prosyak at amd.com>
---
lib/amdgpu/amd_shared_process.c | 289 ++++++++++++++++++++++++++++++++
lib/amdgpu/amd_shared_process.h | 63 +++++++
lib/meson.build | 1 +
3 files changed, 353 insertions(+)
create mode 100644 lib/amdgpu/amd_shared_process.c
create mode 100644 lib/amdgpu/amd_shared_process.h
diff --git a/lib/amdgpu/amd_shared_process.c b/lib/amdgpu/amd_shared_process.c
new file mode 100644
index 000000000..243c4e3f4
--- /dev/null
+++ b/lib/amdgpu/amd_shared_process.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: MIT
+// Copyright 2024 Advanced Micro Devices, Inc.
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <spawn.h>
+#include <sys/types.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "igt.h"
+#include "amd_shared_process.h"
+
+static void
+sync_point_signal(sem_t *psem, int num_signals)
+{
+ int i;
+
+ for (i = 0; i < num_signals; i++)
+ sem_post(psem);
+}
+
+int
+shared_mem_destroy(struct shmbuf *shmp, int shm_fd, int unmap, const char *shm_name)
+{
+ int ret = 0;
+
+ if (shmp && unmap) {
+ munmap(shmp, sizeof(struct shmbuf));
+ sem_destroy(&shmp->sem_mutex);
+ sem_destroy(&shmp->sync_sem_enter);
+ sem_destroy(&shmp->sync_sem_exit);
+ }
+ if (shm_fd > 0)
+ close(shm_fd);
+
+ shm_unlink(shm_name);
+
+ return ret;
+}
+
+int
+shared_mem_create(struct shmbuf **ppbuf, char shm_name[256])
+{
+ int shm_fd = -1;
+ struct shmbuf *shmp = NULL;
+ bool unmap = false;
+
+ // Create a shared memory object
+ shm_fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
+ if (shm_fd == -1)
+ goto error;
+
+
+ // Configure the size of the shared memory object
+ if (ftruncate(shm_fd, sizeof(struct shmbuf)) == -1)
+ goto error;
+
+ // Map the shared memory object
+ shmp = mmap(0, sizeof(struct shmbuf), PROT_WRITE, MAP_SHARED, shm_fd, 0);
+ if (shmp == MAP_FAILED)
+ goto error;
+
+ unmap = true;
+ if (sem_init(&shmp->sem_mutex, 1, 1) == -1) {
+ unmap = true;
+ goto error;
+ }
+ if (sem_init(&shmp->sync_sem_enter, 1, 0) == -1)
+ goto error;
+
+ if (sem_init(&shmp->sync_sem_exit, 1, 0) == -1)
+ goto error;
+
+ shmp->count = 0;
+ *ppbuf = shmp;
+ return shm_fd;
+
+error:
+ shared_mem_destroy(shmp, shm_fd, unmap, shm_name);
+ return shm_fd;
+}
+
+int
+shared_mem_open(struct shmbuf **ppbuf)
+{
+ int shm_fd = -1;
+ struct shmbuf *shmp = NULL;
+
+ shmp = mmap(NULL, sizeof(*shmp), PROT_READ | PROT_WRITE, MAP_SHARED,
+ SHARED_BROTHER_DESCRIPTOR, 0);
+ if (shmp == MAP_FAILED)
+ goto error;
+ else
+ shm_fd = SHARED_BROTHER_DESCRIPTOR;
+
+ *ppbuf = shmp;
+
+ return shm_fd;
+error:
+ return shm_fd;
+}
+
+void
+sync_point_enter(struct shmbuf *sh_mem)
+{
+
+ sem_wait(&sh_mem->sem_mutex);
+ sh_mem->count++;
+ sem_post(&sh_mem->sem_mutex);
+
+ if (sh_mem->count == NUM_BROTHER_PROCESSES)
+ sync_point_signal(&sh_mem->sync_sem_enter, NUM_BROTHER_PROCESSES);
+
+ sem_wait(&sh_mem->sync_sem_enter);
+}
+
+void
+sync_point_exit(struct shmbuf *sh_mem)
+{
+ sem_wait(&sh_mem->sem_mutex);
+ sh_mem->count--;
+ sem_post(&sh_mem->sem_mutex);
+
+ if (sh_mem->count == 0)
+ sync_point_signal(&sh_mem->sync_sem_exit, NUM_BROTHER_PROCESSES);
+
+ sem_wait(&sh_mem->sync_sem_exit);
+}
+
+int
+get_command_line(char cmdline[2048], int *pargc, char ***pppargv, char **ppath)
+{
+ ssize_t total_length = 0;
+ char *tmpline;
+ char **argv = NULL;
+ char *path = NULL;
+ int length_cmd[16] = {0};
+ int i, argc = 0;
+ ssize_t num_read;
+
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+
+ if (fd == -1) {
+ igt_info("**** Error opening /proc/self/cmdline");
+ return -1;
+ }
+
+ num_read = read(fd, cmdline, 2048 - 1);
+ close(fd);
+
+ if (num_read == -1) {
+ igt_info("*** Error reading /proc/self/cmdline");
+ return -1;
+ }
+ cmdline[num_read] = '\0';
+
+ tmpline = cmdline;
+ memset(length_cmd, 0, sizeof(length_cmd));
+
+ /*assumption that last parameter has 2 '\0' at the end*/
+ for (i = 0; total_length < num_read - 2; i++) {
+ length_cmd[i] = strlen(tmpline);
+ total_length += length_cmd[i];
+ tmpline += length_cmd[i] + 1;
+ argc++;
+ }
+ *pargc = argc;
+ if (argc == 0 || argc > 20) {
+ /* not support yet fancy things */
+ return -1;
+ }
+ /* always do 2 extra for additional parameter */
+ argv = (char **)malloc(sizeof(argv) * (argc + 2));
+ memset(argv, 0, sizeof(argv) * (argc + 2));
+ tmpline = cmdline;
+ for (i = 0; i < argc; i++) {
+ argv[i] = (char *)malloc(sizeof(char) * length_cmd[i] + 1);
+ memcpy(argv[i], tmpline, length_cmd[i]);
+ argv[i][length_cmd[i]] = 0;
+ if (i == 0) {
+ path = (char *)malloc(sizeof(char) * length_cmd[0] + 1);
+ memcpy(path, tmpline, length_cmd[0]);
+ path[length_cmd[0]] = 0;
+ }
+ argv[i][length_cmd[i]] = 0;
+ tmpline += length_cmd[i] + 1;
+ }
+ *pppargv = argv;
+ *ppath = path;
+
+ return 0;
+}
+
+int
+is_brother_parameter_found(int argc, char **argv, const char *param)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(param, argv[i]) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
+
+int
+add_brother_parameter(int *pargc, char **argv, const char *param)
+{
+ int argc = *pargc;
+ int len = strlen(param);
+
+ argv[argc] = (char *)malloc(sizeof(char) * len + 1);
+ memcpy(argv[argc], param, len);
+ argv[argc][len] = 0;
+ *pargc = argc + 1;
+ return 1;
+}
+
+void
+free_command_line(int argc, char **argv, char *path)
+{
+ int i;
+
+ for (i = 0; i <= argc; i++)
+ free(argv[i]);
+
+ free(argv);
+ free(path);
+
+}
+
+int
+is_run_device_parameter_found(int argc, char **argv, const char *param)
+{
+ int i;
+ int res = 0;
+ char *p = NULL;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(param, argv[i]) == 0) {
+ /* Get the sum for a specific device as a unique identifier */
+ p = argv[i+1];
+ while (*p) {
+ res += *p;
+ p++;
+ }
+ break;
+ }
+ }
+
+ return res;
+}
+
+int
+launch_brother_process(int argc, char **argv, char *path, pid_t *ppid, int shm_fd)
+{
+ int status;
+ posix_spawn_file_actions_t action;
+ posix_spawnattr_t attr;
+
+ for (int i = 0; i < argc; i++) {
+ if (strstr(argv[i], "list-subtests") != NULL)
+ return 0;
+ }
+ posix_spawn_file_actions_init(&action);
+ posix_spawn_file_actions_adddup2(&action, shm_fd, SHARED_BROTHER_DESCRIPTOR);
+ posix_spawnattr_init(&attr);
+ posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSID);
+ status = posix_spawnp(ppid, path, &action, &attr, argv, NULL);
+
+ posix_spawn_file_actions_destroy(&action);
+ posix_spawnattr_destroy(&attr);
+
+ if (status != 0)
+ igt_fail(IGT_EXIT_FAILURE);
+
+ return status;
+}
+
+
diff --git a/lib/amdgpu/amd_shared_process.h b/lib/amdgpu/amd_shared_process.h
new file mode 100644
index 000000000..62b3e104b
--- /dev/null
+++ b/lib/amdgpu/amd_shared_process.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: MIT
+ * Copyright 2024 Advanced Micro Devices, Inc.
+ *
+ */
+
+#ifndef __AMD_SHARED_PROCESS_H__
+#define __AMD_SHARED_PROCESS_H__
+
+#include <semaphore.h>
+
+#define SHARED_BROTHER_DESCRIPTOR 3
+#define NUM_BROTHER_PROCESSES 2
+
+#define BROTHER "brother"
+#define ONDEVICE "--device"
+
+enum process_type {
+ PROCESS_UNKNOWN,
+ PROCESS_TEST,
+ PROCESS_BROTHER,
+};
+
+struct shmbuf {
+ sem_t sem_mutex;
+ sem_t sync_sem_enter;
+ sem_t sync_sem_exit;
+ int count;
+};
+
+int
+shared_mem_create(struct shmbuf **ppbuf, char shm_name[256]);
+
+int
+shared_mem_open(struct shmbuf **ppbuf);
+
+int
+shared_mem_destroy(struct shmbuf *shmp, int shm_fd, int unmap, const char *shm_name);
+
+void
+sync_point_enter(struct shmbuf *sh_mem);
+
+void
+sync_point_exit(struct shmbuf *sh_mem);
+
+int
+get_command_line(char cmdline[2048], int *pargc, char ***pppargv, char **ppath);
+
+int
+is_brother_parameter_found(int argc, char **argv, const char *param);
+
+int
+add_brother_parameter(int *pargc, char **argv, const char *param);
+
+void
+free_command_line(int argc, char **argv, char *path);
+
+int
+is_run_device_parameter_found(int argc, char **argv, const char *param);
+
+int
+launch_brother_process(int argc, char **argv, char *path, pid_t *ppid, int shm_fd);
+
+#endif
diff --git a/lib/meson.build b/lib/meson.build
index 207b6e185..640513e6c 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -160,6 +160,7 @@ if libdrm_amdgpu.found()
'amdgpu/amd_dispatch_helpers.c',
'amdgpu/amd_deadlock_helpers.c',
'amdgpu/amd_pci_unplug.c',
+ 'amdgpu/amd_shared_process.c',
'amdgpu/xalloc.h',
'amdgpu/amd_cp_dma.c',
'amdgpu/amd_mmd_shared.c'
--
2.25.1
More information about the igt-dev
mailing list