summaryrefslogtreecommitdiff
path: root/tests/gem_ctx_thrash.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-02-04 22:18:33 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2016-02-05 09:12:31 +0000
commite7faf33ec791b78b2bf1ebb81be228364c3439c4 (patch)
tree49e9d180587f90522b9f891a92d3705607c3cbc3 /tests/gem_ctx_thrash.c
parent0e96238bf35959f933b545d2ec85ada6b769cf8b (diff)
igt/gem_ctx_thrash: Rewrite to avoid extraneous allocations
The goal of the test is to exercise what happens when we fill the Global GTT with the contexts. To that end, we only need to allocate 2/4GiB of context objects, and can forgo filling each context with buffers. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94005 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tests/gem_ctx_thrash.c')
-rw-r--r--tests/gem_ctx_thrash.c328
1 files changed, 138 insertions, 190 deletions
diff --git a/tests/gem_ctx_thrash.c b/tests/gem_ctx_thrash.c
index ff752b7c..c7d0bbf7 100644
--- a/tests/gem_ctx_thrash.c
+++ b/tests/gem_ctx_thrash.c
@@ -31,29 +31,9 @@
#include <sys/stat.h>
#include <sys/resource.h>
-
IGT_TEST_DESCRIPTION("Fill the Gobal GTT with context objects and VMs\n");
-#define OBJECT_SIZE (1024 * 1024)
-#define NUM_THREADS 8
-
-static int fd;
-static unsigned devid;
-static igt_render_copyfunc_t render_copy;
-
-static dri_bo **all_bo;
-static int num_bo;
-static int bo_per_ctx;
-
-static drm_intel_context **all_ctx;
-static int num_ctx;
-static int ctx_per_thread;
-
-static void xchg_ptr(void *array, unsigned i, unsigned j)
-{
- void **A = array;
- igt_swap(A[i], A[j]);
-}
+#define NUM_THREADS sysconf(_SC_NPROCESSORS_ONLN)
static void xchg_int(void *array, unsigned i, unsigned j)
{
@@ -61,93 +41,80 @@ static void xchg_int(void *array, unsigned i, unsigned j)
igt_swap(A[i], A[j]);
}
-static int reopen(int _fd)
+static unsigned get_num_contexts(int fd)
{
- struct stat st;
- char name[128];
-
- igt_assert(fstat(_fd, &st) == 0);
-
- sprintf(name, "/dev/dri/card%u", (unsigned)(st.st_rdev & 0x7f));
- return open(name, O_RDWR);
-}
+ uint64_t ggtt_size;
+ unsigned size;
+ unsigned count;
-static void *thread(void *bufmgr)
-{
- struct intel_batchbuffer *batch;
- dri_bo **bo;
- drm_intel_context **ctx;
- int c, b;
-
- batch = intel_batchbuffer_alloc(bufmgr, devid);
+ /* Compute the number of contexts we can allocate to fill the GGTT */
+ if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ ggtt_size = 1ull << 32;
+ else
+ ggtt_size = 1ull << 31;
- bo = malloc(num_bo * sizeof(dri_bo *));
- igt_assert(bo);
- memcpy(bo, all_bo, num_bo * sizeof(dri_bo *));
+ size = 64 << 10; /* Most gen require at least 64k for ctx */
- ctx = malloc(num_ctx * sizeof(drm_intel_context *));
- igt_assert(ctx);
- memcpy(ctx, all_ctx, num_ctx * sizeof(drm_intel_context *));
- igt_permute_array(ctx, num_ctx, xchg_ptr);
-
- for (c = 0; c < ctx_per_thread; c++) {
- igt_permute_array(bo, num_bo, xchg_ptr);
- for (b = 0; b < bo_per_ctx; b++) {
- struct igt_buf src, dst;
-
- src.bo = bo[b % num_bo];
- src.stride = 64;
- src.size = OBJECT_SIZE;
- src.tiling = I915_TILING_NONE;
-
- dst.bo = bo[(b+1) % num_bo];
- dst.stride = 64;
- dst.size = OBJECT_SIZE;
- dst.tiling = I915_TILING_NONE;
-
- render_copy(batch, ctx[c % num_ctx],
- &src, 0, 0, 16, 16, &dst, 0, 0);
- }
- }
+ count = 3 * (ggtt_size / size) / 2;
+ igt_info("Creating %lld contexts (assuming of size %lld)\n",
+ (long long)count, (long long)size);
- free(ctx);
- free(bo);
- intel_batchbuffer_free(batch);
+ intel_require_memory(count, size, CHECK_RAM | CHECK_SWAP);
+ return count;
+}
- return NULL;
+static int has_engine(int fd, const struct intel_execution_engine *e)
+{
+ uint32_t bbe = MI_BATCH_BUFFER_END;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec;
+ int ret;
+
+ memset(&exec, 0, sizeof(exec));
+ exec.handle = gem_create(fd, 4096);
+ gem_write(fd, exec.handle, 0, &bbe, sizeof(bbe));
+
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = (uintptr_t)&exec;
+ execbuf.buffer_count = 1;
+ execbuf.flags = e->exec_id | e->flags;
+ ret = __gem_execbuf(fd, &execbuf);
+ gem_close(fd, exec.handle);
+
+ return ret == 0;
}
-static void
-processes(void)
+static void processes(void)
{
- int *all_fds;
- uint64_t aperture;
+ const struct intel_execution_engine *e;
+ unsigned engines[16];
+ int num_engines;
struct rlimit rlim;
- int ppgtt_mode;
- int ctx_size;
- int obj_size;
- int n;
+ unsigned num_ctx;
+ uint32_t name;
+ int fd, *fds;
- igt_skip_on_simulation();
+ fd = drm_open_driver(DRIVER_INTEL);
+ num_ctx = get_num_contexts(fd);
- fd = drm_open_driver_render(DRIVER_INTEL);
- devid = intel_get_drm_devid(fd);
- aperture = gem_aperture_size(fd);
+ num_engines = 0;
+ for (e = intel_execution_engines; e->name; e++) {
+ if (e->exec_id == 0)
+ continue;
- ppgtt_mode = gem_gtt_type(fd);
- igt_require(ppgtt_mode);
+ if (!has_engine(fd, e))
+ continue;
- render_copy = igt_get_render_copyfunc(devid);
- igt_require_f(render_copy, "no render-copy function\n");
+ if (e->exec_id == I915_EXEC_BSD) {
+ int is_bsd2 = e->flags != 0;
+ if (gem_has_bsd2(fd) != is_bsd2)
+ continue;
+ }
- if (ppgtt_mode > 1)
- ctx_size = aperture >> 10; /* Assume full-ppgtt of maximum size */
- else
- ctx_size = 64 << 10; /* Most gen require at least 64k for ctx */
- num_ctx = 3 * (aperture / ctx_size) / 2;
- igt_info("Creating %d contexts (assuming of size %d)\n",
- num_ctx, ctx_size);
- intel_require_memory(num_ctx, ctx_size, CHECK_RAM | CHECK_SWAP);
+ engines[num_engines++] = e->exec_id | e->flags;
+ if (num_engines == ARRAY_SIZE(engines))
+ break;
+ }
/* tweak rlimits to allow us to create this many files */
igt_assert(getrlimit(RLIMIT_NOFILE, &rlim) == 0);
@@ -158,134 +125,115 @@ processes(void)
igt_assert(setrlimit(RLIMIT_NOFILE, &rlim) == 0);
}
- all_fds = malloc(num_ctx * sizeof(int));
- igt_assert(all_fds);
- for (n = 0; n < num_ctx; n++) {
- all_fds[n] = reopen(fd);
- if (all_fds[n] == -1) {
+ fds = malloc(num_ctx * sizeof(int));
+ igt_assert(fds);
+ for (unsigned n = 0; n < num_ctx; n++) {
+ fds[n] = drm_open_driver(DRIVER_INTEL);
+ if (fds[n] == -1) {
int err = errno;
- for (int i = n; i--; )
- close(all_fds[i]);
- free(all_fds);
+ for (unsigned i = n; i--; )
+ close(fds[i]);
+ free(fds);
errno = err;
- igt_assert_f(0, "failed to create context %d/%d\n", n, num_ctx);
+ igt_assert_f(0, "failed to create context %lld/%lld\n", (long long)n, (long long)num_ctx);
}
}
- num_bo = 2 * num_ctx;
- obj_size = (2 * aperture / num_bo + 4095) & -4096;
- igt_info("Creating %d surfaces (of size %d)\n", num_bo, obj_size);
- intel_require_memory(num_bo, obj_size, CHECK_RAM);
+ if (1) {
+ uint32_t bbe = MI_BATCH_BUFFER_END;
+ name = gem_create(fd, 4096);
+ gem_write(fd, name, 0, &bbe, sizeof(bbe));
+ name = gem_flink(fd, name);
+ }
igt_fork(child, NUM_THREADS) {
- drm_intel_bufmgr *bufmgr;
- struct intel_batchbuffer *batch;
- int c;
-
- igt_permute_array(all_fds, num_ctx, xchg_int);
-
- for (c = 0; c < num_ctx; c++) {
- struct igt_buf src, dst;
-
- bufmgr = drm_intel_bufmgr_gem_init(all_fds[c], 4096);
- igt_assert(bufmgr);
- batch = intel_batchbuffer_alloc(bufmgr, devid);
-
- src.bo = drm_intel_bo_alloc(bufmgr, "", obj_size, 0);
- igt_assert(src.bo);
- src.stride = 64;
- src.size = obj_size;
- src.tiling = I915_TILING_NONE;
-
- dst.bo = drm_intel_bo_alloc(bufmgr, "", obj_size, 0);
- igt_assert(dst.bo);
- dst.stride = 64;
- dst.size = obj_size;
- dst.tiling = I915_TILING_NONE;
-
- render_copy(batch, NULL,
- &src, 0, 0, 16, 16, &dst, 0, 0);
-
- intel_batchbuffer_free(batch);
- drm_intel_bo_unreference(src.bo);
- drm_intel_bo_unreference(dst.bo);
- drm_intel_bufmgr_destroy(bufmgr);
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 obj;
+
+ memset(&obj, 0, sizeof(obj));
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = (uintptr_t)&obj;
+ execbuf.buffer_count = 1;
+
+ igt_permute_array(fds, num_ctx, xchg_int);
+ for (unsigned n = 0; n < num_ctx; n++) {
+ obj.handle = gem_open(fds[n], name);
+ execbuf.flags = engines[n % num_engines];
+ gem_execbuf(fds[n], &execbuf);
+ gem_close(fds[n], obj.handle);
}
}
igt_waitchildren();
- for (n = 0; n < num_ctx; n++)
- close(all_fds[n]);
- free(all_fds);
+ for (unsigned n = 0; n < num_ctx; n++)
+ close(fds[n]);
+ free(fds);
close(fd);
}
-static void
-threads(void)
+struct thread {
+ int fd;
+ uint32_t *all_ctx;
+ unsigned num_ctx;
+};
+
+static void *thread(void *data)
{
- pthread_t threads[NUM_THREADS];
- drm_intel_bufmgr *bufmgr;
- uint64_t aperture;
- int ppgtt_mode;
- int ctx_size;
- int n;
+ struct thread *t = data;
+ uint32_t bbe = MI_BATCH_BUFFER_END;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 obj;
+ uint32_t *ctx;
- igt_skip_on_simulation();
+ memset(&obj, 0, sizeof(obj));
+ obj.handle = gem_create(t->fd, 4096);
+ gem_write(t->fd, obj.handle, 0, &bbe, sizeof(bbe));
- fd = drm_open_driver_render(DRIVER_INTEL);
- devid = intel_get_drm_devid(fd);
- aperture = gem_aperture_size(fd);
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = (uintptr_t)&obj;
+ execbuf.buffer_count = 1;
- ppgtt_mode = gem_gtt_type(fd);
- igt_require(ppgtt_mode);
+ ctx = malloc(t->num_ctx * sizeof(uint32_t));
+ igt_assert(ctx);
+ memcpy(ctx, t->all_ctx, t->num_ctx * sizeof(uint32_t));
+ igt_permute_array(ctx, t->num_ctx, xchg_int);
- render_copy = igt_get_render_copyfunc(devid);
- igt_require_f(render_copy, "no render-copy function\n");
+ for (unsigned n = 0; n < t->num_ctx; n++) {
+ execbuf.rsvd1 = ctx[n];
+ gem_execbuf(t->fd, &execbuf);
+ }
- bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
- igt_assert(bufmgr);
- drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ free(ctx);
+ gem_close(t->fd, obj.handle);
- if (ppgtt_mode > 1)
- ctx_size = aperture >> 10; /* Assume full-ppgtt of maximum size */
- else
- ctx_size = 64 << 10; /* Most gen require at least 64k for ctx */
- num_ctx = 3 * (aperture / ctx_size) / 2;
- igt_info("Creating %d contexts (assuming of size %d)\n",
- num_ctx, ctx_size);
- intel_require_memory(num_ctx, ctx_size, CHECK_RAM | CHECK_SWAP);
- all_ctx = malloc(num_ctx * sizeof(drm_intel_context *));
- igt_assert(all_ctx);
- for (n = 0; n < num_ctx; n++) {
- all_ctx[n] = drm_intel_gem_context_create(bufmgr);
- igt_assert(all_ctx[n]);
- }
+ return NULL;
+}
- num_bo = 3 * (aperture / OBJECT_SIZE) / 2;
- igt_info("Creating %d surfaces (of size %d)\n", num_bo, OBJECT_SIZE);
- intel_require_memory(num_bo, OBJECT_SIZE, CHECK_RAM);
- all_bo = malloc(num_bo * sizeof(dri_bo *));
- igt_assert(all_bo);
- for (n = 0; n < num_bo; n++) {
- all_bo[n] = drm_intel_bo_alloc(bufmgr, "", OBJECT_SIZE, 0);
- igt_assert(all_bo[n]);
- }
+static void threads(void)
+{
+ pthread_t threads[NUM_THREADS];
+ struct thread data;
- ctx_per_thread = 3 * num_ctx / NUM_THREADS / 2;
- bo_per_ctx = 3 * num_bo / NUM_THREADS / 2;
+ data.fd = drm_open_driver_render(DRIVER_INTEL);
+ data.num_ctx = get_num_contexts(data.fd);
+ data.all_ctx = malloc(data.num_ctx * sizeof(uint32_t));
+ igt_assert(data.all_ctx);
+ for (unsigned n = 0; n < data.num_ctx; n++)
+ data.all_ctx[n] = gem_context_create(data.fd);
- for (n = 0; n < NUM_THREADS; n++)
- pthread_create(&threads[n], NULL, thread, bufmgr);
+ for (int n = 0; n < NUM_THREADS; n++)
+ pthread_create(&threads[n], NULL, thread, &data);
- for (n = 0; n < NUM_THREADS; n++)
+ for (int n = 0; n < NUM_THREADS; n++)
pthread_join(threads[n], NULL);
- drm_intel_bufmgr_destroy(bufmgr);
- close(fd);
+ close(data.fd);
}
igt_main
{
+ igt_skip_on_simulation();
+
igt_subtest("processes")
processes();