diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-12-03 09:05:54 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-03-29 15:57:50 +0100 |
commit | 068f9ceb628b3d721bf3d74c7932afc01a70905c (patch) | |
tree | 9be0d7c2f3811b5c3ed7e8df503d9cc94ef7e58c /tests/eviction_common.c | |
parent | b9b82fdc5fdcbc43d0720b6aaf79e1f00f407d3a (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.c | 84 |
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, |