From: Dominik Grzegorzek <[email protected]>

A low priority client should not block a high priority client. In this
case we check that if a low priority client poisons its own GTT and so
its execbuf may take ages to process, a high priority client can still
execute in parallel.

Signed-off-by: Dominik Grzegorzek <[email protected]>
Cc: Zbigniew KempczyƄski <[email protected]>
Reviewed-by: Chris Wilson <[email protected]>
Signed-off-by: Chris Wilson <[email protected]>
---
 tests/i915/gem_exec_alignment.c | 116 ++++++++++++++++++++++++++++++++
 tests/intel-ci/blacklist.txt    |   1 -
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/tests/i915/gem_exec_alignment.c b/tests/i915/gem_exec_alignment.c
index 2895aee1e..730d3b778 100644
--- a/tests/i915/gem_exec_alignment.c
+++ b/tests/i915/gem_exec_alignment.c
@@ -38,6 +38,8 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
+#include <signal.h>
+#include <sched.h>
 
 #include "drm.h"
 
@@ -121,6 +123,118 @@ static uint32_t batch_create(int i915, unsigned long sz)
        return handle;
 }
 
+static void naughty_child(int i915, int link)
+{
+       struct drm_i915_gem_execbuffer2 execbuf;
+       struct drm_i915_gem_exec_object2 *obj;
+       uint64_t gtt_size, ram_size, count;
+       struct timespec tv = {};
+
+       gtt_size = gem_aperture_size(i915); /* We have to *share* our GTT! */
+       ram_size = intel_get_total_ram_mb();
+       ram_size *= 1024 * 1024;
+
+       count = min(gtt_size, ram_size) / 16384;
+       if (count > file_max()) /* vfs cap */
+               count = file_max();
+       intel_require_memory(count, 4096, CHECK_RAM);
+
+       /* Fill the low-priority address space */
+       obj = calloc(sizeof(*obj), count);
+       igt_assert(obj);
+       for (unsigned long i = 0; i < count; i++) {
+               obj[i].handle = batch_create(i915, 4096);
+               if ((gtt_size - 1) >> 32)
+                       obj[i].flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+               obj[i].alignment = 4096;
+       }
+
+       memset(&execbuf, 0, sizeof(execbuf));
+       execbuf.buffers_ptr = to_user_pointer(obj);
+       execbuf.buffer_count = count;
+       execbuf.rsvd1 = gem_context_create(i915);
+       gem_execbuf(i915, &execbuf);
+
+       /* Calibrate a long execbuf() */
+       for (unsigned long i = 0; i < count; i++)
+               obj[i].alignment = 8192;
+
+       execbuf.buffer_count = 2;
+       while (igt_seconds_elapsed(&tv) < 2) {
+               execbuf.buffer_count <<= 1;
+               gem_execbuf(i915, &execbuf);
+       }
+       execbuf.buffer_count <<= 1;
+       if (execbuf.buffer_count > count)
+               execbuf.buffer_count = count;
+       igt_debug("Using %u buffers to delay execbuf\n", execbuf.buffer_count);
+
+       for (unsigned long i = 0; i < count; i++)
+               obj[i].alignment = 16384;
+
+       write(link, &tv, sizeof(tv));
+
+       igt_debug("Executing naughty execbuf\n");
+       igt_nsec_elapsed(memset(&tv, 0, sizeof(tv)));
+       gem_execbuf(i915, &execbuf); /* this should take over 2s */
+       igt_info("Naughty client took %'"PRIu64"ns\n",
+                igt_nsec_elapsed(&tv));
+
+       gem_context_destroy(i915, execbuf.rsvd1);
+       for (unsigned long i = 0; i < count; i++)
+               gem_close(i915, obj[i].handle);
+       free(obj);
+}
+
+static void prio_inversion(int i915)
+{
+       struct drm_i915_gem_exec_object2 obj = {
+               .handle = batch_create(i915, 4095)
+       };
+       struct drm_i915_gem_execbuffer2 execbuf = {
+               .buffers_ptr = to_user_pointer(&obj),
+               .buffer_count = 1,
+       };
+       struct timespec tv;
+       uint64_t elapsed;
+       int link[2];
+
+       /*
+        * First low priority client create mass of holes in their
+        * own address space, then launch a batch with oodles of object with
+        * alignment that doesn't match previous one. While lp execbufer
+        * is performing we want to start high priority task
+        * and we expect it will not be blocked.
+        */
+
+       igt_require(gem_uses_full_ppgtt(i915));
+       igt_assert(pipe(link) == 0);
+
+       /* Prime our prestine context */
+       gem_execbuf(i915, &execbuf);
+
+       igt_fork(child, 1)
+               naughty_child(i915, link[1]);
+
+       igt_debug("Waiting for naughty client\n");
+       read(link[0], &tv, sizeof(tv));
+       igt_debug("Ready...\n");
+       sleep(1); /* let the naughty execbuf begin */
+       igt_debug("Go!\n");
+
+       igt_nsec_elapsed(memset(&tv, 0, sizeof(tv)));
+       gem_execbuf(i915, &execbuf);
+       elapsed = igt_nsec_elapsed(&tv);
+       igt_info("Normal client took %'"PRIu64"ns\n", elapsed);
+
+       igt_waitchildren();
+       gem_close(i915, obj.handle);
+
+       igt_assert(elapsed < 10 * 1000 * 1000); /* 10ms */
+       close(link[0]);
+       close(link[1]);
+}
+
 static void many(int fd, int timeout)
 {
        struct drm_i915_gem_exec_object2 *execobj;
@@ -281,4 +395,6 @@ igt_main
                single(fd);
        igt_subtest("many")
                many(fd, 20);
+       igt_subtest("pi")
+               prio_inversion(fd);
 }
diff --git a/tests/intel-ci/blacklist.txt b/tests/intel-ci/blacklist.txt
index 1b49e8bb7..c819fee51 100644
--- a/tests/intel-ci/blacklist.txt
+++ b/tests/intel-ci/blacklist.txt
@@ -24,7 +24,6 @@ igt@gem_ctx_switch(@.*)?
 igt@gem_ctx_thrash(@.*)?
 igt@gem_evict_alignment(@.*)?
 igt@gem_evict_everything(@.*)?
-igt@gem_exec_alignment@(?!.*single).*
 igt@gem_exec_big@(?!.*single).*
 igt@gem_exec_capture@many-(?!4K-).*
 igt@gem_exec_fence@(?!.*basic).*
-- 
2.26.0

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to