diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-05-24 17:31:43 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-05-24 17:34:31 +0100 |
commit | 00ce341b95c718611689ded8ccec45086186c5b7 (patch) | |
tree | 5fa194b96d780dfcd1a6f5c56f88f5628573a890 /tests/gem_shrink.c | |
parent | 056765c412951b991836126412fbd6ffb8054013 (diff) |
igt/gem_shrink: Exercise concurrent calls to i915_gem_shrink()
Just recently I once again made the mistake of thinking we could do a
plain mutex_lock() inside i915_gem_shrink(). However, such a lock is
liable to cyclic deadlocks between multiple relcaimers. This can be
reported by lockdep, but we need contention in the shrinker for it to
spot this particular mistake. The easiest way to explicit cause
contention is via concurrent calls to debugfs/i915_drop_caches whilst
the GPU is busy.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tests/gem_shrink.c')
-rw-r--r-- | tests/gem_shrink.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/tests/gem_shrink.c b/tests/gem_shrink.c index bd0f17da..8b09fc80 100644 --- a/tests/gem_shrink.c +++ b/tests/gem_shrink.c @@ -29,6 +29,8 @@ #include "igt.h" #include "igt_gt.h" +#include "igt_debugfs.h" +#include "igt_sysfs.h" #ifndef MADV_FREE #define MADV_FREE 8 @@ -291,6 +293,44 @@ static void run_test(int nchildren, uint64_t alloc, igt_waitchildren(); } +static void reclaim(unsigned engine, int timeout) +{ + const uint64_t timeout_100ms = 100000000LL; + int fd = drm_open_driver(DRIVER_INTEL); + int debugfs = igt_debugfs_dir(fd); + igt_spin_t *spin; + volatile uint32_t *shared; + + shared = mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + igt_assert(shared != MAP_FAILED); + + igt_fork(child, sysconf(_SC_NPROCESSORS_ONLN)) { + do { + igt_sysfs_printf(debugfs, "i915_drop_caches", + "%d", DROP_BOUND | DROP_UNBOUND); + } while (!*shared); + } + + spin = igt_spin_batch_new(fd, engine, 0); + igt_until_timeout(timeout) { + igt_spin_t *next = __igt_spin_batch_new(fd, engine, 0); + + igt_spin_batch_set_timeout(spin, timeout_100ms); + gem_sync(fd, spin->handle); + + igt_spin_batch_free(fd, spin); + spin = next; + } + igt_spin_batch_free(fd, spin); + + *shared = 1; + igt_waitchildren(); + + munmap((void *)shared, 4096); + close(debugfs); + close(fd); +} + igt_main { const struct test { @@ -341,6 +381,9 @@ igt_main CHECK_SWAP | CHECK_RAM); } + igt_subtest("reclaim") + reclaim(I915_EXEC_DEFAULT, 2); + for(const struct test *t = tests; t->name; t++) { for(const struct mode *m = modes; m->suffix; m++) { igt_subtest_f("%s%s", t->name, m->suffix) |