[PATCH i-g-t 1/3] lib/igt_drm_clients: Add helper to list and count the DRM client processes

Soham Purkait
2026-04-02T13:07:55Z

Add a helper that scans all DRM clients for a card fd, optionally
populating a list of client processes as an array of
struct igt_drm_client_proc, and always returns the count of client
processes excluding the caller process.

This allows callers (like tests) to find other DRM clients which are
using the card.

Signed-off-by: Soham Purkait <soham.purkait@intel.com>
---
lib/igt_drm_clients.c | 93 +++++++++++++++++++++++++++++++++++++++++++
lib/igt_drm_clients.h | 10 +++++
2 files changed, 103 insertions(+)

diff --git a/lib/igt_drm_clients.c b/lib/igt_drm_clients.c
index 858cd3645..2baea1b17 100644
--- a/lib/igt_drm_clients.c
+++ b/lib/igt_drm_clients.c
@@ -608,3 +608,96 @@ next:

return clients;
}
+
+/**
+ * igt_drm_get_client_procs:
+ * @card_fd: DRM device fd to query
+ * @self_pid: Self PID to be excluded from the results
+ * @procs: Array of struct igt_drm_client_proc holding the list of client
+ * processes, to be populated by the function
+ *
+ * Scan all processes for DRM clients using @card_fd and return the count
+ * of client processes, excluding @self_pid.
+ * If @procs is NULL, the function only returns the number of client
+ * processes.
+ * If @procs is not NULL, it points to a newly allocated array of %struct
+ * igt_drm_client_proc.
+ * On allocation failure, the function triggers an assert.
+ */
+int igt_drm_get_client_procs(int card_fd,
+ pid_t self_pid,
+ struct igt_drm_client_proc **procs)
+{
+ struct igt_drm_clients *clients;
+ struct igt_drm_client *c;
+ struct stat st;
+ pid_t *seen_pids = NULL;
+ unsigned int drm_minor;
+ unsigned int seen = 0;
+ int i, count = 0;
+
+ assert(fstat(card_fd, &st) == 0 &&
+ S_ISCHR(st.st_mode) &&
+ major(st.st_rdev) == 226);
+
+ drm_minor = minor(st.st_rdev);
+
+ clients = igt_drm_clients_init(NULL);
+ assert(clients);
+
+ igt_drm_clients_scan(clients, NULL, NULL, 0, NULL, 0);
+
+ if (clients->num_clients) {
+ seen_pids = calloc(clients->num_clients, sizeof(*seen_pids));
+ assert(seen_pids);
+ }
+
+ if (procs)
+ *procs = NULL;
+
+ igt_for_each_drm_client(clients, c, i) {
+ unsigned int j;
+ bool duplicate = false;
+
+ if (c->status != IGT_DRM_CLIENT_ALIVE)
+ continue;
+
+ if (c->drm_minor != drm_minor)
+ continue;
+
+ for (j = 0; j < seen; j++) {
+ if (seen_pids[j] == (pid_t)c->pid) {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (duplicate)
+ continue;
+
+ if (seen_pids)
+ seen_pids[seen++] = c->pid;
+
+ if ((pid_t)c->pid == self_pid)
+ continue;
+
+ if (procs) {
+ struct igt_drm_client_proc *tmp;
+
+ tmp = realloc(*procs, (count + 1) * sizeof(struct igt_drm_client_proc));
+ assert(tmp);
+
+ tmp[count].pid = c->pid;
+ tmp[count].id = c->id;
+ strncpy(tmp[count].print_name, c->print_name,
+ sizeof(tmp[count].print_name) - 1);
+ tmp[count].print_name[sizeof(tmp[count].print_name) - 1] = '\0';
+ *procs = tmp;
+ }
+ count++;
+ }
+
+ free(seen_pids);
+ igt_drm_clients_free(clients);
+ return count;
+}
diff --git a/lib/igt_drm_clients.h b/lib/igt_drm_clients.h
index 946d709de..4d47c06f9 100644
--- a/lib/igt_drm_clients.h
+++ b/lib/igt_drm_clients.h
@@ -54,6 +54,12 @@ struct igt_drm_client_regions {
char **names; /* Array of region names, either auto-detected or from the passed in region map. */
};

+struct igt_drm_client_proc {
+ unsigned int pid;
+ unsigned long id;
+ char print_name[64];
+};
+
struct igt_drm_clients;

struct igt_drm_client {
@@ -119,4 +125,8 @@ struct igt_drm_clients *
igt_drm_clients_sort(struct igt_drm_clients *clients,
int (*cmp)(const void *, const void *, void *));

+int igt_drm_get_client_procs(int card_fd,
+ pid_t self_pid,
+ struct igt_drm_client_proc **procs);
+
#endif /* IGT_DRM_CLIENTS_H */
--
2.34.1