From e8eb9afd4c53e67d834f520a42a641adb874a463 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 8 Mar 2017 13:09:00 +0000 Subject: igt: Exercise the shrinker Introduce a new fork helper that spawns a process that just repeatedly calls i915_gem_shrink_all() and watch what happens as we try to use objects that have been shrunk. Signed-off-by: Chris Wilson --- lib/igt_aux.c | 39 +++++++++++++++++++++++++++++++++++++++ lib/igt_aux.h | 3 +++ lib/igt_debugfs.c | 22 ++++++++++++++++++++++ lib/igt_debugfs.h | 9 +++++++++ 4 files changed, 73 insertions(+) (limited to 'lib') diff --git a/lib/igt_aux.c b/lib/igt_aux.c index 5117dbec..7ee279a3 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -349,6 +349,45 @@ void igt_stop_signal_helper(void) sig_stat = 0; } +static struct igt_helper_process shrink_helper; +static void __attribute__((noreturn)) shrink_helper_process(pid_t pid) +{ + while (1) { + igt_drop_caches_set(DROP_SHRINK_ALL); + usleep(1000 * 1000 / 50); + if (kill(pid, 0)) /* Parent has died, so must we. */ + exit(0); + } +} + +/** + * igt_fork_shrink_helper: + * + * Fork a child process using #igt_fork_helper to force all available objects + * to be paged out (via i915_gem_shrink()). + * + * This is useful to exercise swapping paths, without requiring us to hit swap. + * + * This should only be used from an igt_fixture. + */ +void igt_fork_shrink_helper(void) +{ + assert(!igt_only_list_subtests()); + igt_require(igt_drop_caches_has(DROP_SHRINK_ALL)); + igt_fork_helper(&shrink_helper) + shrink_helper_process(getppid()); +} + +/** + * igt_stop_shrink_helper: + * + * Stops the child process spawned with igt_fork_shrink_helper(). + */ +void igt_stop_shrink_helper(void) +{ + igt_stop_helper(&shrink_helper); +} + #if HAVE_UDEV #include diff --git a/lib/igt_aux.h b/lib/igt_aux.h index cb54ca5e..13f6f156 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -51,6 +51,9 @@ extern int num_trash_bos; void igt_fork_signal_helper(void); void igt_stop_signal_helper(void); +void igt_fork_shrink_helper(void); +void igt_stop_shrink_helper(void); + void igt_fork_hang_detector(int fd); void igt_stop_hang_detector(void); diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index e64d001b..0a991a1f 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -872,6 +872,28 @@ void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc) * Drop caches */ +/** + * igt_drop_caches_has: + * @val: bitmask for DROP_* values + * + * This queries the debugfs to see if it supports the full set of desired + * operations. + */ +bool igt_drop_caches_has(uint64_t val) +{ + FILE *file; + uint64_t mask; + + mask = 0; + file = igt_debugfs_fopen("i915_gem_drop_caches", "r"); + if (file) { + fscanf(file, "0x%" PRIx64, &mask); + fclose(file); + } + + return (val & mask) == val; +} + /** * igt_drop_caches_set: * @val: bitmask for DROP_* values diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 5587ad40..aa59f8a8 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -169,6 +169,13 @@ void igt_require_hpd_storm_ctl(void); * Also drop freed objects. */ #define DROP_FREED 0x10 +/** + * DROP_SHRINK_ALL: + * + * Force all unpinned buffers to be evicted from their GTT and returned to the + * system. + */ +#define DROP_SHRINK_ALL 0x20 /** * DROP_ALL: * @@ -176,10 +183,12 @@ void igt_require_hpd_storm_ctl(void); */ #define DROP_ALL (DROP_UNBOUND | \ DROP_BOUND | \ + DROP_SHRINK_ALL | \ DROP_RETIRE | \ DROP_ACTIVE | \ DROP_FREED) +bool igt_drop_caches_has(uint64_t val); void igt_drop_caches_set(uint64_t val); /* -- cgit v1.2.3