summaryrefslogtreecommitdiff
path: root/tests/eviction_common.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-12-03 09:05:54 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2015-03-29 15:57:50 +0100
commit068f9ceb628b3d721bf3d74c7932afc01a70905c (patch)
tree9be0d7c2f3811b5c3ed7e8df503d9cc94ef7e58c /tests/eviction_common.c
parentb9b82fdc5fdcbc43d0720b6aaf79e1f00f407d3a (diff)
igt/gem_evict_everything: Use mlock to reduce available memory
The idea here is to check what happens when a large process requests memory from us - we create and utilize a bunch of surfaces then have to relinquish some but continue using the whole working set (so as to force reloads). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tests/eviction_common.c')
-rw-r--r--tests/eviction_common.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/tests/eviction_common.c b/tests/eviction_common.c
index 82cdaebc..4fa5c045 100644
--- a/tests/eviction_common.c
+++ b/tests/eviction_common.c
@@ -130,6 +130,90 @@ static int major_evictions(int fd, struct igt_eviction_test_ops *ops,
return 0;
}
+static void mlocked_evictions(int fd, struct igt_eviction_test_ops *ops,
+ int surface_size,
+ int surface_count)
+{
+ size_t sz, pin;
+ int result[2];
+ void *locked;
+ int ret = -1;
+
+ intel_require_memory(surface_count, surface_size, CHECK_RAM);
+ igt_assert(pipe(result) == 0);
+
+ sz = surface_size*surface_count;
+ pin = intel_get_avail_ram_mb();
+ pin *= 1024 * 1024;
+ igt_require(pin > sz);
+ pin -= 3*sz/2;
+
+ igt_debug("Pinning [%ld, %ld] MiB\n",
+ (long)pin/(1024*1024), (long)(pin + sz)/(1024*1024));
+
+ locked = malloc(pin + sz);
+ if (locked != NULL && mlock(locked, pin + sz)) {
+ free(locked);
+ locked = NULL;
+ } else {
+ munlock(locked, pin + sz);
+ free(locked);
+ }
+ igt_require(locked);
+
+ igt_fork(child, 1) {
+ uint32_t *bo;
+ int n;
+
+ bo = malloc(surface_count*sizeof(*bo));
+ igt_assert(bo);
+
+ locked = malloc(pin);
+ if (locked == NULL || mlock(locked, pin)) {
+ ret = ENOSPC;
+ goto out;
+ }
+
+ for (n = 0; n < surface_count; n++)
+ bo[n] = ops->create(fd, surface_size);
+
+ ret = 0;
+ for (n = 0; n < surface_count - 2; n++) {
+ igt_permute_array(bo, surface_count, exchange_uint32_t);
+ ret = ops->copy(fd, bo[0], bo[1], bo, surface_count-n);
+ if (ret)
+ break;
+
+ /* Having used the surfaces (and so pulled out of
+ * our pages into memory), start a memory hog to
+ * force evictions.
+ */
+
+ locked = malloc(surface_size);
+ if (locked == NULL || mlock(locked, surface_size)) {
+ ret = ENOSPC;
+ goto out;
+ }
+ }
+
+ for (n = 0; n < surface_count; n++)
+ ops->close(fd, bo[n]);
+
+out:
+ write(result[1], &ret, sizeof(ret));
+ }
+
+ igt_waitchildren();
+
+ fcntl(result[0], F_SETFL, fcntl(result[0], F_GETFL) | O_NONBLOCK);
+ read(result[0], &ret, sizeof(ret));
+ close(result[0]);
+ close(result[1]);
+
+ errno = ret;
+ igt_assert(ret == 0);
+}
+
static int swapping_evictions(int fd, struct igt_eviction_test_ops *ops,
int surface_size,
int working_surfaces,