All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH i-g-t 3/3] i915: Exercise timeslice sysfs property
Date: Sat, 19 Oct 2019 11:04:39 +0100	[thread overview]
Message-ID: <20191019100439.24640-3-chris@chris-wilson.co.uk> (raw)
In-Reply-To: <20191019100439.24640-1-chris@chris-wilson.co.uk>

We [will] expose various per-engine scheduling controls. One of which,
'timeslice_duration_ms', defines the scheduling quantum. If a context
exhausts its timeslice, it will be preempted in favour of running one of
its compatriots.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 tests/Makefile.sources                |   1 +
 tests/i915/sysfs_timeslice_duration.c | 310 ++++++++++++++++++++++++++
 tests/meson.build                     |   1 +
 3 files changed, 312 insertions(+)
 create mode 100644 tests/i915/sysfs_timeslice_duration.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 4494d2c05..9bfe214d7 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -100,6 +100,7 @@ TESTS_progs = \
 	vgem_slow \
 	i915/sysfs_heartbeat_interval \
 	i915/sysfs_preemption_timeout \
+	i915/sysfs_timeslice_duration \
 	$(NULL)
 
 TESTS_progs += gem_bad_reloc
diff --git a/tests/i915/sysfs_timeslice_duration.c b/tests/i915/sysfs_timeslice_duration.c
new file mode 100644
index 000000000..4c725923b
--- /dev/null
+++ b/tests/i915/sysfs_timeslice_duration.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "drmtest.h" /* gem_quiescent_gpu()! */
+#include "i915/gem_engine_topology.h"
+#include "igt_dummyload.h"
+#include "igt_sysfs.h"
+#include "ioctl_wrappers.h" /* igt_require_gem()! */
+#include "sw_sync.h"
+
+#include "igt_debugfs.h"
+
+static bool __enable_hangcheck(int dir, bool state)
+{
+	return igt_sysfs_set(dir, "enable_hangcheck", state ? "1" : "0");
+}
+
+static bool enable_hangcheck(int i915, bool state)
+{
+	bool success;
+	int dir;
+
+	dir = igt_sysfs_open_parameters(i915);
+	if (dir < 0) /* no parameters, must be default! */
+		return false;
+
+	success = __enable_hangcheck(dir, state);
+	close(dir);
+
+	return success;
+}
+
+static void set_timeslice(int engine, unsigned int value)
+{
+	unsigned int delay;
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", "%u", value);
+	igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &delay);
+	igt_assert_eq(delay, value);
+}
+
+static void test_idempotent(int i915, int engine)
+{
+	const unsigned int delays[] = { 0, 1, 1234, 654321 };
+	unsigned int saved;
+
+	igt_assert(igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &saved) == 1);
+	igt_debug("Initial timeslice_duration_ms:%u\n", saved);
+
+	for (int i = 0; i < ARRAY_SIZE(delays); i++)
+		set_timeslice(engine, delays[i]);
+
+	set_timeslice(engine, saved);
+}
+
+static void test_invalid(int i915, int engine)
+{
+	unsigned int saved, delay;
+
+	igt_assert(igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &saved) == 1);
+	igt_debug("Initial timeslice_duration_ms:%u\n", saved);
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", PRIu64, -1);
+	igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &delay);
+	igt_assert_eq(delay, saved);
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", "%d", -1);
+	igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &delay);
+	igt_assert_eq(delay, saved);
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", PRIu64, 123ull << 32);
+	igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &delay);
+	igt_assert_eq(delay, saved);
+}
+
+static void set_unbannable(int i915, uint32_t ctx)
+{
+	struct drm_i915_gem_context_param p = {
+		.ctx_id = ctx,
+		.param = I915_CONTEXT_PARAM_BANNABLE,
+	};
+
+	igt_assert_eq(__gem_context_set_param(i915, &p), 0);
+}
+
+static uint32_t create_context(int i915, unsigned int class, unsigned int inst, int prio)
+{
+	uint32_t ctx;
+
+	ctx = gem_context_create_for_engine(i915, class, inst);
+	set_unbannable(i915, ctx);
+	gem_context_set_priority(i915, ctx, prio);
+
+	return ctx;
+}
+
+static uint64_t __test_timeout(int i915, int engine, unsigned int timeout)
+{
+	unsigned int class, inst;
+	struct timespec ts = {};
+	igt_spin_t *spin[2];
+	uint64_t elapsed;
+	uint32_t ctx[2];
+
+	igt_assert(igt_sysfs_scanf(engine, "class", "%u", &class) == 1);
+	igt_assert(igt_sysfs_scanf(engine, "instance", "%u", &inst) == 1);
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", "%u", timeout);
+
+	ctx[0] = create_context(i915, class, inst, 0);
+	spin[0] = igt_spin_new(i915, ctx[0],
+			       .flags = (IGT_SPIN_NO_PREEMPTION |
+					 IGT_SPIN_POLL_RUN |
+					 IGT_SPIN_FENCE_OUT));
+	igt_spin_busywait_until_started(spin[0]);
+
+	ctx[1] = create_context(i915, class, inst, 0);
+	igt_nsec_elapsed(&ts);
+	spin[1] = igt_spin_new(i915, ctx[1], .flags = IGT_SPIN_POLL_RUN);
+	igt_spin_busywait_until_started(spin[1]);
+	elapsed = igt_nsec_elapsed(&ts);
+
+	igt_spin_free(i915, spin[1]);
+
+	igt_assert_eq(sync_fence_wait(spin[0]->out_fence, 1), 0);
+	igt_assert_eq(sync_fence_status(spin[0]->out_fence), -EIO);
+
+	igt_spin_free(i915, spin[0]);
+
+	gem_context_destroy(i915, ctx[1]);
+	gem_context_destroy(i915, ctx[0]);
+	gem_quiescent_gpu(i915);
+
+	return elapsed;
+}
+
+static void test_timeout(int i915, int engine)
+{
+	int delays[] = { 1, 50, 100, 500 };
+	unsigned int saved;
+
+	igt_require(igt_sysfs_printf(engine, "preempt_timeout_ms", "%u", 1) == 1);
+	igt_assert(igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &saved) == 1);
+	igt_debug("Initial timeslice_duration_ms:%u\n", saved);
+
+	gem_quiescent_gpu(i915);
+	igt_require(enable_hangcheck(i915, false));
+
+	for (int i = 0; i < ARRAY_SIZE(delays); i++) {
+		uint64_t elapsed;
+
+		elapsed = __test_timeout(i915, engine, delays[i]);
+		igt_info("timeslice_duration_ms:%d, elapsed=%.3fms\n",
+			 delays[i], elapsed * 1e-6);
+
+		/*
+		 * We need to give a couple of jiffies slack for the scheduler timeouts
+		 * and then a little more slack fr the overhead in submitting and
+		 * measuring. 50ms should cover all of our sins and be useful
+		 * tolerance.
+		 */
+		igt_assert_f(elapsed / 1000 / 1000 < delays[i] + 50,
+			     "Forced preemption timeout exceeded request!\n");
+
+	}
+
+	igt_assert(enable_hangcheck(i915, true));
+	gem_quiescent_gpu(i915);
+
+	set_timeslice(engine, saved);
+}
+
+static void test_off(int i915, int engine)
+{
+	unsigned int class, inst;
+	unsigned int saved;
+	igt_spin_t *spin[2];
+	uint32_t ctx[2];
+
+	igt_require(igt_sysfs_printf(engine, "preempt_timeout_ms", "%u", 1) == 1);
+	igt_assert(igt_sysfs_scanf(engine, "timeslice_duration_ms", "%u", &saved) == 1);
+	igt_debug("Initial timeslice_duration_ms:%u\n", saved);
+
+	gem_quiescent_gpu(i915);
+	igt_require(enable_hangcheck(i915, false));
+
+	igt_assert(igt_sysfs_scanf(engine, "class", "%u", &class) == 1);
+	igt_assert(igt_sysfs_scanf(engine, "instance", "%u", &inst) == 1);
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", "%u", 0);
+
+	ctx[0] = create_context(i915, class, inst, 0);
+	spin[0] = igt_spin_new(i915, ctx[0],
+			       .flags = (IGT_SPIN_NO_PREEMPTION |
+					 IGT_SPIN_POLL_RUN |
+					 IGT_SPIN_FENCE_OUT));
+	igt_spin_busywait_until_started(spin[0]);
+
+	ctx[1] = create_context(i915, class, inst, 0);
+	spin[1] = igt_spin_new(i915, ctx[1], .flags = IGT_SPIN_POLL_RUN);
+
+	for (int i = 0; i < 150; i++) {
+		igt_assert_eq(sync_fence_status(spin[0]->out_fence), 0);
+		sleep(1);
+	}
+
+	igt_sysfs_printf(engine, "timeslice_duration_ms", "%u", 1);
+
+	igt_spin_busywait_until_started(spin[1]);
+	igt_spin_free(i915, spin[1]);
+
+	igt_assert_eq(sync_fence_wait(spin[0]->out_fence, 1), 0);
+	igt_assert_eq(sync_fence_status(spin[0]->out_fence), -EIO);
+
+	igt_spin_free(i915, spin[0]);
+
+	gem_context_destroy(i915, ctx[1]);
+	gem_context_destroy(i915, ctx[0]);
+
+	igt_assert(enable_hangcheck(i915, true));
+	gem_quiescent_gpu(i915);
+
+	set_timeslice(engine, saved);
+}
+
+igt_main
+{
+	const struct intel_execution_engine2 *it;
+	int i915 = -1, engines = -1;
+
+	igt_fixture {
+		int sys;
+
+		i915 = drm_open_driver(DRIVER_INTEL);
+		igt_require_gem(i915);
+
+		sys = igt_sysfs_open(i915);
+		igt_require(sys != -1);
+
+		engines = openat(sys, "engine", O_RDONLY);
+		igt_require(engines != -1);
+
+		close(sys);
+	}
+
+	__for_each_static_engine(it) {
+		igt_subtest_group {
+			int engine = -1;
+			char *name = NULL;
+
+			igt_fixture {
+				struct stat st;
+
+				engine = openat(engines, it->name, O_RDONLY);
+				igt_require(fstatat(engine,
+							"timeslice_duration_ms",
+							&st, 0) == 0);
+
+				name = igt_sysfs_get(engine, "name");
+			}
+			if (!name)
+				continue;
+
+			igt_subtest_f("%s-idempotent", name)
+				test_idempotent(i915, engine);
+			igt_subtest_f("%s-invalid", name)
+				test_invalid(i915, engine);
+			igt_subtest_f("%s-timeout", name)
+				test_timeout(i915, engine);
+			igt_subtest_f("%s-off", name)
+				test_off(i915, engine);
+
+			free(name);
+			close(engine);
+		}
+	}
+
+	igt_fixture {
+		close(engines);
+		close(i915);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 23f730c20..f603ab3e0 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -240,6 +240,7 @@ i915_progs = [
 	'i915_suspend',
 	'sysfs_heartbeat_interval',
 	'sysfs_preemption_timeout',
+	'sysfs_timeslice_duration',
 ]
 
 test_deps = [ igt_deps ]
-- 
2.24.0.rc0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2019-10-19 10:05 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-19 10:04 [PATCH i-g-t 1/3] i915: Exercise preemption timeout controls in sysfs Chris Wilson
2019-10-19 10:04 ` [PATCH i-g-t 2/3] i915: Exercise sysfs heartbeat controls Chris Wilson
2019-10-19 10:04 ` Chris Wilson [this message]
2019-10-19 10:14 ` ✗ GitLab.Pipeline: warning for series starting with [1/3] i915: Exercise preemption timeout controls in sysfs Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-10-18 13:38 sysfs property tests Chris Wilson
2019-10-18 13:38 ` [PATCH i-g-t 3/3] i915: Exercise timeslice sysfs property Chris Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191019100439.24640-3-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.