summaryrefslogtreecommitdiff
path: root/tests/gem_shrink.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-05-24 17:31:43 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2017-05-24 17:34:31 +0100
commit00ce341b95c718611689ded8ccec45086186c5b7 (patch)
tree5fa194b96d780dfcd1a6f5c56f88f5628573a890 /tests/gem_shrink.c
parent056765c412951b991836126412fbd6ffb8054013 (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.c43
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)