diff options
| author | Dominik Grzegorzek <dominik.grzegorzek@intel.com> | 2020-03-19 08:38:19 +0100 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2020-04-02 18:30:30 +0100 |
| commit | 213062c7dcf0cbc8069cbb5f91acbc494def33fd (patch) | |
| tree | da95c3a448f2a89932a2603384559fbc4eddaa1d | |
| parent | f4e75f5613d327c1be8c6979ccf4462b30832502 (diff) | |
i915/gem_exec_alignment: Exercise potential priority inversion
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 <dominik.grzegorzek@intel.com>
Cc: Zbigniew KempczyĆski <zbigniew.kempczynski@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
| -rw-r--r-- | tests/i915/gem_exec_alignment.c | 116 | ||||
| -rw-r--r-- | tests/intel-ci/blacklist-pre-merge.txt | 9 | ||||
| -rw-r--r-- | tests/intel-ci/blacklist.txt | 1 |
3 files changed, 125 insertions, 1 deletions
diff --git a/tests/i915/gem_exec_alignment.c b/tests/i915/gem_exec_alignment.c index 2895aee1..730d3b77 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-pre-merge.txt b/tests/intel-ci/blacklist-pre-merge.txt index 070f3b32..cddb77c1 100644 --- a/tests/intel-ci/blacklist-pre-merge.txt +++ b/tests/intel-ci/blacklist-pre-merge.txt @@ -63,6 +63,15 @@ igt@gem_pwrite@big-.* ############################################################################### +# This test checks some edge cases of the execbuf API, which is quite time +# consuming and rarely changes. Very unlikely to be affected by any code +# outside of drm_mm and i915_gem_execbuffer, for which the authors assure us +# that they are making deliberate and well tested changes. +############################################################################### +igt@gem_exec_alignment@.* + + +############################################################################### # These 4 tests are covering an edge case which should never be hit by users # unless we already are in a bad situation, yet they are responsible for a # significant portion of our execution time: diff --git a/tests/intel-ci/blacklist.txt b/tests/intel-ci/blacklist.txt index 1b49e8bb..c819fee5 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).* |
