summaryrefslogtreecommitdiff
path: root/tests/i915
diff options
context:
space:
mode:
Diffstat (limited to 'tests/i915')
-rw-r--r--tests/i915/sysfs_clients.c129
1 files changed, 108 insertions, 21 deletions
diff --git a/tests/i915/sysfs_clients.c b/tests/i915/sysfs_clients.c
index a3a1f81e..e936bd48 100644
--- a/tests/i915/sysfs_clients.c
+++ b/tests/i915/sysfs_clients.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <limits.h>
#include <math.h>
#include <sched.h>
#include <sys/socket.h>
@@ -47,6 +48,8 @@
#define assert_within_epsilon(x, ref, tolerance) \
__assert_within_epsilon(x, ref, tolerance / 100., tolerance / 100.)
+#define BUFSZ 280
+
#define MI_BATCH_BUFFER_START (0x31 << 23)
#define MI_BATCH_BUFFER_END (0xa << 23)
#define MI_ARB_CHECK (0x5 << 23)
@@ -75,7 +78,7 @@ static void pidname(int i915, int clients)
{
struct dirent *de;
int sv[2], rv[2];
- char buf[280];
+ char buf[BUFSZ];
int me = -1;
long count;
pid_t pid;
@@ -180,7 +183,7 @@ static long count_clients(int clients)
{
struct dirent *de;
long count = 0;
- char buf[280];
+ char buf[BUFSZ];
DIR *dir;
dir = fdopendir(dup(clients));
@@ -229,32 +232,113 @@ static void create(int i915, int clients)
igt_assert_eq(count_clients(clients), 1);
}
+static const char *find_client(int clients, pid_t pid, char *buf)
+{
+ DIR *dir = fdopendir(dup(clients));
+
+ /* Reading a dir as it changes does not appear to be stable, SEP */
+ for (int pass = 0; pass < 3; pass++) {
+ struct dirent *de;
+
+ rewinddir(dir);
+ fsync(dirfd(dir));
+ while ((de = readdir(dir))) {
+ if (!isdigit(de->d_name[0]))
+ continue;
+
+ snprintf(buf, BUFSZ, "%s/pid", de->d_name);
+ igt_sysfs_read(clients, buf, buf, sizeof(buf));
+ if (atoi(buf) != pid)
+ continue;
+
+ strncpy(buf, de->d_name, BUFSZ);
+ goto out;
+ }
+ }
+ *buf = '\0';
+out:
+ closedir(dir);
+ return buf;
+}
+
static int find_me(int clients, pid_t pid)
{
- struct dirent *de;
- char buf[280];
- int me = -1;
- DIR *dir;
+ char buf[BUFSZ];
- dir = fdopendir(dup(clients));
- igt_assert(dir);
- rewinddir(dir);
+ return openat(clients,
+ find_client(clients, pid, buf),
+ O_DIRECTORY | O_RDONLY);
+}
- while ((de = readdir(dir))) {
- if (!isdigit(de->d_name[0]))
- continue;
+static int reopen_directory(int fd)
+{
+ char buf[BUFSZ];
+ int dir;
- snprintf(buf, sizeof(buf), "%s/pid", de->d_name);
- igt_sysfs_read(clients, buf, buf, sizeof(buf));
- if (atoi(buf) != pid)
- continue;
+ snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
+ dir = open(buf, O_DIRECTORY | O_RDONLY);
+ igt_assert_fd(dir);
- me = openat(clients, de->d_name, O_DIRECTORY | O_RDONLY);
- break;
+ return dir;
+}
+
+static unsigned long my_id(int clients, pid_t pid)
+{
+ char buf[BUFSZ];
+
+ return strtoul(find_client(clients, pid, buf), NULL, 0);
+}
+
+static unsigned long recycle_client(int i915, int clients)
+{
+ unsigned long client;
+ int device;
+
+ device = gem_reopen_driver(i915);
+ client = my_id(clients, getpid());
+ close(device);
+
+ igt_assert(client != 0);
+ return client;
+}
+
+static void recycle(int i915, int clients)
+{
+ const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+ /*
+ * As we open and close clients, we do not expect to reuse old ids,
+ * i.e. we use a cyclic ida. This reduces the likelihood of userspace
+ * watchers becoming confused and mistaking the new client as a
+ * continuation of the old.
+ */
+ igt_assert(my_id(clients, getpid()));
+
+ igt_fork(child, 2 * ncpus) {
+ unsigned long client, last;
+
+ /* Reopen the directory fd for each client */
+ clients = reopen_directory(clients);
+
+ last = recycle_client(i915, clients);
+ igt_info("Child[%d] first client:%lu\n", getpid(), last);
+ igt_until_timeout(5) {
+ client = recycle_client(i915, clients);
+ igt_assert((long)(client - last) > 0);
+ last = client;
+ }
+ igt_info("Child[%d] last client:%lu\n", getpid(), last);
}
+ igt_waitchildren();
- closedir(dir);
- return me;
+ /* Cleanup delayed behind rcu */
+ igt_until_timeout(30) {
+ sched_yield();
+ if (count_clients(clients) == 1)
+ break;
+ usleep(10000);
+ }
+ igt_assert_eq(count_clients(clients), 1);
}
static int64_t read_runtime(int client, int class)
@@ -719,7 +803,7 @@ sema(int i915, int clients, const struct intel_execution_engine2 *e, int f)
static int read_all(int clients, pid_t pid, int class, uint64_t *runtime)
{
struct dirent *de;
- char buf[280];
+ char buf[BUFSZ];
int count = 0;
DIR *dir;
@@ -958,6 +1042,9 @@ igt_main
igt_subtest("create")
create(i915, clients);
+ igt_subtest("recycle")
+ recycle(i915, clients);
+
igt_subtest_group
test_busy(i915, clients);