@@ -1756,20 +1756,7 @@ void igt_child_done(pid_t pid)
test_children[i] = test_children[i + 1];
}
-/**
- * igt_waitchildren:
- *
- * Wait for all children forked with igt_fork.
- *
- * The magic here is that exit codes from children will be correctly propagated
- * to the main thread, including the relevant exit code if a child thread failed.
- * Of course if multiple children failed with different exit codes the resulting
- * exit code will be non-deterministic.
- *
- * Note that igt_skip() will not be forwarded, feature tests need to be done
- * before spawning threads with igt_fork().
- */
-void igt_waitchildren(void)
+int __igt_waitchildren(void)
{
int err = 0;
int count;
@@ -1815,6 +1802,25 @@ void igt_waitchildren(void)
}
num_test_children = 0;
+ return err;
+}
+
+/**
+ * igt_waitchildren:
+ *
+ * Wait for all children forked with igt_fork.
+ *
+ * The magic here is that exit codes from children will be correctly propagated
+ * to the main thread, including the relevant exit code if a child thread failed.
+ * Of course if multiple children failed with different exit codes the resulting
+ * exit code will be non-deterministic.
+ *
+ * Note that igt_skip() will not be forwarded, feature tests need to be done
+ * before spawning threads with igt_fork().
+ */
+void igt_waitchildren(void)
+{
+ int err = __igt_waitchildren();
if (err)
igt_fail(err);
}
@@ -742,6 +742,7 @@ bool __igt_fork(void);
for (int child = 0; child < (num_children); child++) \
for (; __igt_fork(); exit(0))
void igt_child_done(pid_t pid);
+int __igt_waitchildren(void);
void igt_waitchildren(void);
void igt_waitchildren_timeout(int seconds, const char *reason);
@@ -160,6 +160,57 @@ test_sysfs_reader(bool hibernate)
igt_stop_helper(&reader);
}
+static void
+test_shrink(int fd, unsigned int mode)
+{
+ uint64_t *can_mlock, pin;
+
+ gem_quiescent_gpu(fd);
+ intel_purge_vm_caches(fd);
+
+ pin = (intel_get_total_ram_mb() + 1) << 20;
+
+ igt_debug("Total memory %'"PRIu64" B (%'"PRIu64" MiB)\n",
+ pin, pin >> 20);
+ can_mlock = mmap(NULL, pin, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+ igt_require(can_mlock != MAP_FAILED);
+
+ /* Lock all the system memory, forcing the driver into swap and OOM */
+ for (uint64_t inc = 64 << 20; inc >= 4 << 10; inc >>= 1) {
+ igt_debug("Testing+ %'"PRIu64" B (%'"PRIu64" MiB)\n",
+ *can_mlock, *can_mlock >> 20);
+
+ igt_fork(child, 1) {
+ for (uint64_t bytes = *can_mlock;
+ bytes <= pin;
+ bytes += inc) {
+ if (mlock(can_mlock, bytes))
+ break;
+
+ *can_mlock = bytes;
+ __sync_synchronize();
+ }
+ }
+ __igt_waitchildren();
+ }
+
+ intel_purge_vm_caches(fd);
+
+ igt_require(*can_mlock > 64 << 20);
+ *can_mlock -= 64 << 20;
+
+ igt_debug("Locking %'"PRIu64" B (%'"PRIu64" MiB)\n",
+ *can_mlock, *can_mlock >> 20);
+ igt_assert(!mlock(can_mlock, *can_mlock));
+ igt_info("Locked %'"PRIu64" B (%'"PRIu64" MiB)\n",
+ *can_mlock, *can_mlock >> 20);
+
+ intel_purge_vm_caches(fd);
+ igt_system_suspend_autoresume(mode, SUSPEND_TEST_NONE);
+
+ munmap(can_mlock, pin);
+}
+
static void
test_forcewake(int fd, bool hibernate)
{
@@ -199,6 +250,9 @@ igt_main
igt_subtest("sysfs-reader")
test_sysfs_reader(false);
+ igt_subtest("shrink")
+ test_shrink(fd, SUSPEND_STATE_MEM);
+
igt_subtest("forcewake")
test_forcewake(fd, false);