All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
@ 2017-08-15 21:44 Antonio Argenziano
  2017-08-15 21:47 ` ✗ Fi.CI.BAT: failure for " Patchwork
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Antonio Argenziano @ 2017-08-15 21:44 UTC (permalink / raw)
  To: intel-gfx

Sending as RFC to get feedback on what would be the correct behaviour of
the driver and, therefore, if the test is valid.

We do a wait while holding the mutex if we are adding a request and figure
out that there is no more space in the ring buffer.
Is that considered a bug? In the current driver all goes well
because even if you are waiting on a hanging request eventually
hangcheck will come in a kill the request and since the new request
would have waited there anyway it is not a big deal. But, when
preemption is going to be added it will cause a high priority
(preemptive) request to wait for a long time before actually preempting.

The testcase added here, stimulates this scenario where a high priority
request is sent while another process keeps submitting requests and
filling its ringbuffer.

Cc: Chris Wilson <chris@chris-wilson.co.uk>

Signed-off-by: Antonio Argenziano <antonio.argenziano@intel.com>
---
 tests/gem_ringfill.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 129 insertions(+), 11 deletions(-)

diff --git a/tests/gem_ringfill.c b/tests/gem_ringfill.c
index b52996a4..6ca8352e 100644
--- a/tests/gem_ringfill.c
+++ b/tests/gem_ringfill.c
@@ -47,8 +47,31 @@
 #define HIBERNATE 0x40
 #define NEWFD 0x80
 
+#define MAX_PRIO 1023
+#define LOCAL_CONTEXT_PARAM_PRIORITY 0x7
+
+IGT_TEST_DESCRIPTION("Check that we can manage the ringbuffer when full");
+
 static unsigned int ring_size;
 
+static int __ctx_set_priority(int fd, uint32_t ctx, int prio)
+{
+	struct local_i915_gem_context_param param;
+
+	memset(&param, 0, sizeof(param));
+	param.context = ctx;
+	param.size = 0;
+	param.param = LOCAL_CONTEXT_PARAM_PRIORITY;
+	param.value = prio;
+
+	return __gem_context_set_param(fd, &param);
+}
+
+static void ctx_set_priority(int fd, uint32_t ctx, int prio)
+{
+	igt_assert_eq(__ctx_set_priority(fd, ctx, prio), 0);
+}
+
 static void check_bo(int fd, uint32_t handle)
 {
 	uint32_t *map;
@@ -324,6 +347,88 @@ static unsigned int measure_ring_size(int fd)
 	return count;
 }
 
+static void exec_noop(int fd, uint32_t ctx, uint32_t engine, uint32_t *handle)
+{
+	uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_exec_object2 exec;
+
+	gem_require_ring(fd, engine);
+
+	memset(&exec, 0, sizeof(exec));
+
+	*handle = exec.handle = gem_create(fd, 4096);
+
+	gem_write(fd, exec.handle, 0, &bbe, sizeof(bbe));
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&exec);
+	execbuf.buffer_count = 1;
+	execbuf.flags = engine;
+	execbuf.rsvd1 = ctx;
+
+	gem_execbuf(fd, &execbuf);
+}
+
+static void wait_batch(int fd, uint32_t handle)
+{
+	int64_t timeout = 1ull * NSEC_PER_SEC; //1 sec
+
+	if(gem_wait(fd, handle, &timeout) != 0) {
+		//Force reset and fail the test
+		igt_force_gpu_reset(fd);
+		igt_assert_f(0, "[0x%x] batch did not complete!", handle);
+	}
+}
+
+/*
+ * This test checks that is possible for a high priority request to trigger a
+ * preemption if another context has filled its ringbuffer.
+ * The aim of the test is to make sure that high priority requests cannot be
+ * stalled by low priority tasks.
+ * */
+static void preempt_while_ringbuffer_full(int fd, uint32_t engine)
+{
+	uint32_t hp_ctx, lp_ctx;
+	uint32_t hp_batch;
+	igt_spin_t *lp_batch;
+
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_relocation_entry reloc[1024];
+	struct drm_i915_gem_execbuffer2 execbuf;
+	const unsigned timeout = 10;
+
+	lp_ctx = gem_context_create(fd);
+	ctx_set_priority(fd, lp_ctx, -MAX_PRIO);
+
+	hp_ctx = gem_context_create(fd);
+	ctx_set_priority(fd, hp_ctx, MAX_PRIO);
+
+	igt_require(setup_execbuf(fd, &execbuf, obj, reloc, engine) == 0);
+	execbuf.rsvd1 = lp_ctx;
+
+	/*Stall execution and fill ring*/
+	lp_batch = igt_spin_batch_new(fd, lp_ctx, engine, 0);
+	igt_fork(child_no, 1) {
+		fill_ring(fd, &execbuf, 0, timeout);
+	}
+
+	/*We don't know when the ring will be full so keep sending in a loop*/
+	igt_until_timeout(1) {
+		exec_noop(fd, hp_ctx, engine, &hp_batch);
+
+		/*Preemption expected, if HP batch doesn't complete test fails*/
+		wait_batch(fd, hp_batch);
+		igt_assert(gem_bo_busy(fd, lp_batch->handle));
+		gem_close(fd, hp_batch);
+
+		usleep(100);
+	}
+
+	igt_terminate_spin_batches();
+	igt_waitchildren();
+}
+
 igt_main
 {
 	const struct {
@@ -363,21 +468,34 @@ igt_main
 		igt_require(ring_size);
 	}
 
-	for (m = modes; m->suffix; m++) {
-		const struct intel_execution_engine *e;
-
-		for (e = intel_execution_engines; e->name; e++) {
-			igt_subtest_f("%s%s%s",
-				      m->basic && !e->exec_id ? "basic-" : "",
-				      e->name,
-				      m->suffix) {
-				igt_skip_on(m->flags & NEWFD && master);
-				run_test(fd, e->exec_id | e->flags,
-					 m->flags, m->timeout);
+	igt_subtest_group {
+		for (m = modes; m->suffix; m++) {
+			const struct intel_execution_engine *e;
+
+			for (e = intel_execution_engines; e->name; e++) {
+				igt_subtest_f("%s%s%s",
+						m->basic && !e->exec_id ? "basic-" : "",
+						e->name,
+						m->suffix) {
+					igt_skip_on(m->flags & NEWFD && master);
+					run_test(fd, e->exec_id | e->flags,
+							m->flags, m->timeout);
+				}
 			}
 		}
 	}
 
+	igt_subtest_group {
+			for (const struct intel_execution_engine *e
+					= intel_execution_engines; e->name; e++) {
+				igt_subtest_f("preempt-while-full-%s", e->name) {
+					igt_fork_hang_detector(fd);
+					preempt_while_ringbuffer_full(fd, e->exec_id | e->flags);
+					igt_stop_hang_detector();
+				}
+			}
+	}
+
 	igt_fixture
 		close(fd);
 }
-- 
2.14.1

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

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* ✗ Fi.CI.BAT: failure for igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-15 21:44 [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test Antonio Argenziano
@ 2017-08-15 21:47 ` Patchwork
  2017-08-15 22:35 ` [RFC i-g-t] " Chris Wilson
  2017-08-15 23:32 ` Chris Wilson
  2 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2017-08-15 21:47 UTC (permalink / raw)
  To: Antonio Argenziano; +Cc: intel-gfx

== Series Details ==

Series: igt/gem_ringfill: Adds full ringbuffer preemption test
URL   : https://patchwork.freedesktop.org/series/28829/
State : failure

== Summary ==

IGT patchset build failed on latest successful build
8d2ad9d4d4ba35e1ca8a4989347825fa8e8c0072 tests/kms_flip: fix spin_batch conversion

make  all-recursive
Making all in lib
make  all-recursive
Making all in .
Making all in tests
make[4]: Nothing to be done for 'all'.
Making all in man
make[2]: Nothing to be done for 'all'.
Making all in tools
Making all in null_state_gen
make[3]: Nothing to be done for 'all'.
Making all in registers
make[3]: Nothing to be done for 'all'.
make[3]: Nothing to be done for 'all-am'.
Making all in scripts
make[2]: Nothing to be done for 'all'.
Making all in benchmarks
make[2]: Nothing to be done for 'all'.
Making all in tests
Making all in intel-ci
make[3]: Nothing to be done for 'all'.
  CCLD     gem_bad_batch
  CCLD     gem_hang
  CCLD     gem_bad_blit
  CCLD     gem_bad_address
  CCLD     gem_non_secure_batch
  CCLD     gem_stress
  CCLD     core_auth
  CCLD     core_get_client_auth
  CCLD     core_getclient
  CCLD     core_getstats
  CCLD     core_getversion
  CCLD     core_prop_blob
  CCLD     core_setmaster_vs_auth
  CCLD     debugfs_test
  CCLD     drm_import_export
  CCLD     drm_mm
  CCLD     drm_read
  CCLD     drm_vma_limiter
  CCLD     drm_vma_limiter_cached
  CCLD     drm_vma_limiter_cpu
  CCLD     drm_vma_limiter_gtt
  CCLD     drv_getparams_basic
  CCLD     drv_hangman
  CCLD     drv_missed_irq
  CCLD     drv_module_reload
  CCLD     drv_selftest
  CCLD     drv_suspend
  CCLD     gem_bad_length
  CCLD     gem_bad_reloc
  CCLD     gem_basic
  CCLD     gem_busy
  CCLD     gem_caching
  CCLD     gem_close_race
  CCLD     gem_concurrent_blit
  CCLD     gem_cpu_reloc
  CCLD     gem_create
  CCLD     gem_cs_prefetch
  CCLD     gem_cs_tlb
  CCLD     gem_ctx_bad_destroy
  CCLD     gem_ctx_bad_exec
  CCLD     gem_ctx_basic
  CCLD     gem_ctx_create
  CCLD     gem_ctx_exec
  CCLD     gem_ctx_param
  CCLD     gem_ctx_switch
  CCLD     gem_ctx_thrash
  CCLD     gem_double_irq_loop
  CCLD     gem_eio
  CCLD     gem_evict_alignment
  CCLD     gem_evict_everything
  CCLD     gem_exec_alignment
  CCLD     gem_exec_async
  CCLD     gem_exec_await
  CCLD     gem_exec_bad_domains
  CCLD     gem_exec_basic
  CCLD     gem_exec_big
  CCLD     gem_exec_blt
  CCLD     gem_exec_capture
  CCLD     gem_exec_create
  CCLD     gem_exec_faulting_reloc
  CCLD     gem_exec_fence
  CCLD     gem_exec_flush
  CCLD     gem_exec_gttfill
  CCLD     gem_exec_latency
  CCLD     gem_exec_lut_handle
  CCLD     gem_exec_nop
  CCLD     gem_exec_parallel
  CCLD     gem_exec_params
  CCLD     gem_exec_parse
  CCLD     gem_exec_reloc
  CCLD     gem_exec_reuse
  CCLD     gem_exec_schedule
  CCLD     gem_exec_store
  CCLD     gem_exec_suspend
  CCLD     gem_exec_whisper
  CCLD     gem_fd_exhaustion
  CCLD     gem_fence_thrash
  CCLD     gem_fence_upload
  CCLD     gem_fenced_exec_thrash
  CCLD     gem_flink_basic
  CCLD     gem_flink_race
  CCLD     gem_gpgpu_fill
  CCLD     gem_gtt_cpu_tlb
  CCLD     gem_gtt_hog
  CCLD     gem_gtt_speed
  CCLD     gem_hangcheck_forcewake
  CCLD     gem_largeobject
  CCLD     gem_linear_blits
  CCLD     gem_lut_handle
  CCLD     gem_madvise
  CCLD     gem_media_fill
  CCLD     gem_mmap
  CCLD     gem_mmap_gtt
  CCLD     gem_mmap_offset_exhaustion
  CCLD     gem_mmap_wc
  CCLD     gem_mocs_settings
  CCLD     gem_partial_pwrite_pread
  CCLD     gem_persistent_relocs
  CCLD     gem_pin
  CCLD     gem_pipe_control_store_loop
  CCLD     gem_ppgtt
  CCLD     gem_pread
  CCLD     gem_pread_after_blit
  CCLD     gem_pwrite
  CCLD     gem_pwrite_pread
  CCLD     gem_pwrite_snooped
  CCLD     gem_read_read_speed
  CCLD     gem_readwrite
  CCLD     gem_reg_read
  CCLD     gem_reloc_overflow
  CCLD     gem_reloc_vs_gpu
  CCLD     gem_render_copy
  CCLD     gem_render_copy_redux
  CCLD     gem_render_linear_blits
  CCLD     gem_render_tiled_blits
  CCLD     gem_request_retire
  CCLD     gem_reset_stats
  CCLD     gem_ring_sync_copy
  CCLD     gem_ring_sync_loop
  CC       gem_ringfill.o
Makefile:3899: recipe for target 'gem_ringfill.o' failed
Makefile:4370: recipe for target 'all-recursive' failed
Makefile:528: recipe for target 'all-recursive' failed
Makefile:460: recipe for target 'all' failed

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-15 21:44 [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test Antonio Argenziano
  2017-08-15 21:47 ` ✗ Fi.CI.BAT: failure for " Patchwork
@ 2017-08-15 22:35 ` Chris Wilson
  2017-08-16  7:39   ` Chris Wilson
  2017-08-17 15:14   ` Antonio Argenziano
  2017-08-15 23:32 ` Chris Wilson
  2 siblings, 2 replies; 7+ messages in thread
From: Chris Wilson @ 2017-08-15 22:35 UTC (permalink / raw)
  To: Antonio Argenziano, intel-gfx

Quoting Antonio Argenziano (2017-08-15 22:44:21)
> Sending as RFC to get feedback on what would be the correct behaviour of
> the driver and, therefore, if the test is valid.

It's not a preemption specific bug. It is fair to say that any client
blocking any other client over a non-contended resource is an issue.
Skip to end for a really easy way to demonstrate this.

> We do a wait while holding the mutex if we are adding a request and figure
> out that there is no more space in the ring buffer.
> Is that considered a bug?

Yes, but it is one of many priority inversion problems we have because
we have a BKL. Timeframe for fixing it is a few more years.

> +static void wait_batch(int fd, uint32_t handle)
> +{
> +       int64_t timeout = 1ull * NSEC_PER_SEC; //1 sec
> +
> +       if(gem_wait(fd, handle, &timeout) != 0) {
> +               //Force reset and fail the test
> +               igt_force_gpu_reset(fd);

Just terminate the spin batches.

> +               igt_assert_f(0, "[0x%x] batch did not complete!", handle);
> +       }
> +}
> +
> +/*
> + * This test checks that is possible for a high priority request to trigger a
> + * preemption if another context has filled its ringbuffer.
> + * The aim of the test is to make sure that high priority requests cannot be
> + * stalled by low priority tasks.
> + * */
> +static void preempt_while_ringbuffer_full(int fd, uint32_t engine)
> +{
> +       uint32_t hp_ctx, lp_ctx;
> +       uint32_t hp_batch;
> +       igt_spin_t *lp_batch;
> +
> +       struct drm_i915_gem_exec_object2 obj[2];
> +       struct drm_i915_gem_relocation_entry reloc[1024];

That's a bit excessive for this pi test, no ?

> +       struct drm_i915_gem_execbuffer2 execbuf;
> +       const unsigned timeout = 10;
> +
> +       lp_ctx = gem_context_create(fd);
> +       ctx_set_priority(fd, lp_ctx, -MAX_PRIO);
> +
> +       hp_ctx = gem_context_create(fd);
> +       ctx_set_priority(fd, hp_ctx, MAX_PRIO);
> +
> +       igt_require(setup_execbuf(fd, &execbuf, obj, reloc, engine) == 0);
> +       execbuf.rsvd1 = lp_ctx;
> +
> +       /*Stall execution and fill ring*/
> +       lp_batch = igt_spin_batch_new(fd, lp_ctx, engine, 0);
> +       igt_fork(child_no, 1) {
> +               fill_ring(fd, &execbuf, 0, timeout);
> +       }
> +
> +       /*We don't know when the ring will be full so keep sending in a loop*/

Yes we do. See measure_ring_size.

static void bind_to_cpu(int cpu)
{
	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	struct sched_param rt = {.sched_priority = 99 };
	cpu_set_t allowed;

	igt_assert(sched_setscheduler(getpid(), SCHED_RR | SCHED_RESET_ON_FORK, &rt) == 0);

	CPU_ZERO(&allowed);
	CPU_SET(cpu % ncpus, &allowed);
	igt_assert(sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed) == 0);
}

setup timer
execbuf.rsvd1 = ctx_lo;
while (__raw_gem_execbuf(fd, &execbuf) == 0)
	;

/* steal cpu */
bind_to_cpu(0);
igt_fork(child, 1) {
	/* this child is forced to wait for parent to sleep */
	execbuf.rsvd1 = ctx_hi;
	setup timer;
	*success = __raw_gem_execbuf(fd, &execbuf) == 0;
}
setup 2*timer
__raw_gem_execbuf(fd, &execbuf); /* sleeps under mutex, releasing child
*/

igt_terminate_spin_batches();
igt_waitchildren();

igt_assert(*success);

Timer can be safely 10ms.

Similarly:

race set-domain (pretty much any GEM ioctl ends up in set-domain) vs
spin-batch, when successful then try any set-domain ioctl from a second
client and observe that it too is blocked on the first client hogging.

end:
For the purpose of testing, just create a debugfs that acquires
struct_mutex on opening. Then test every ioctl and trap from a second
client.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-15 21:44 [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test Antonio Argenziano
  2017-08-15 21:47 ` ✗ Fi.CI.BAT: failure for " Patchwork
  2017-08-15 22:35 ` [RFC i-g-t] " Chris Wilson
@ 2017-08-15 23:32 ` Chris Wilson
  2 siblings, 0 replies; 7+ messages in thread
From: Chris Wilson @ 2017-08-15 23:32 UTC (permalink / raw)
  To: Antonio Argenziano, intel-gfx

Quoting Antonio Argenziano (2017-08-15 22:44:21)
> Sending as RFC to get feedback on what would be the correct behaviour of
> the driver and, therefore, if the test is valid.
> 
> We do a wait while holding the mutex if we are adding a request and figure
> out that there is no more space in the ring buffer.
> Is that considered a bug?

Hmm, note that we may have contention on a struct drm_i915_file_private
lock for execbuf (as handles are in a per-fd namespace). To be 100% sure
that the clients are independent, use separate fd, and also note that we
can only have client separation for execbuf on full-ppgtt.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-15 22:35 ` [RFC i-g-t] " Chris Wilson
@ 2017-08-16  7:39   ` Chris Wilson
  2017-08-17 15:14   ` Antonio Argenziano
  1 sibling, 0 replies; 7+ messages in thread
From: Chris Wilson @ 2017-08-16  7:39 UTC (permalink / raw)
  To: Antonio Argenziano, intel-gfx

Quoting Chris Wilson (2017-08-15 23:35:46)
> end:
> For the purpose of testing, just create a debugfs that acquires
> struct_mutex on opening. Then test every ioctl and trap from a second
> client.

Whilst fun, this is focusing on the current implementation issue and
doesn't define the behaviour you want, namely that any two ioctls from
different clients for disparate resources do not block. The better test
will be setting up the typical conflicts, but playing with a
struct_mutex-blocker will show you just how widespread the immediate
problem is.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-15 22:35 ` [RFC i-g-t] " Chris Wilson
  2017-08-16  7:39   ` Chris Wilson
@ 2017-08-17 15:14   ` Antonio Argenziano
  2017-08-17 15:38     ` Chris Wilson
  1 sibling, 1 reply; 7+ messages in thread
From: Antonio Argenziano @ 2017-08-17 15:14 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx



On 15/08/17 15:35, Chris Wilson wrote:
> Quoting Antonio Argenziano (2017-08-15 22:44:21)
>> Sending as RFC to get feedback on what would be the correct behaviour of
>> the driver and, therefore, if the test is valid.
> 
> It's not a preemption specific bug. It is fair to say that any client
> blocking any other client over a non-contended resource is an issue.
> Skip to end for a really easy way to demonstrate this.

Ok, I'll push a patch then.

> 
>> We do a wait while holding the mutex if we are adding a request and figure
>> out that there is no more space in the ring buffer.
>> Is that considered a bug?
> 
> Yes, but it is one of many priority inversion problems we have because
> we have a BKL. Timeframe for fixing it is a few more years.
> 
>> +static void wait_batch(int fd, uint32_t handle)
>> +{
>> +       int64_t timeout = 1ull * NSEC_PER_SEC; //1 sec
>> +
>> +       if(gem_wait(fd, handle, &timeout) != 0) {
>> +               //Force reset and fail the test
>> +               igt_force_gpu_reset(fd);
> 
> Just terminate the spin batches.
> 
>> +               igt_assert_f(0, "[0x%x] batch did not complete!", handle);
>> +       }
>> +}
>> +
>> +/*
>> + * This test checks that is possible for a high priority request to trigger a
>> + * preemption if another context has filled its ringbuffer.
>> + * The aim of the test is to make sure that high priority requests cannot be
>> + * stalled by low priority tasks.
>> + * */
>> +static void preempt_while_ringbuffer_full(int fd, uint32_t engine)
>> +{
>> +       uint32_t hp_ctx, lp_ctx;
>> +       uint32_t hp_batch;
>> +       igt_spin_t *lp_batch;
>> +
>> +       struct drm_i915_gem_exec_object2 obj[2];
>> +       struct drm_i915_gem_relocation_entry reloc[1024];
> 
> That's a bit excessive for this pi test, no ?

Just wanted to reuse the utility functions in the test with minimal changes.

> 
>> +       struct drm_i915_gem_execbuffer2 execbuf;
>> +       const unsigned timeout = 10;
>> +
>> +       lp_ctx = gem_context_create(fd);
>> +       ctx_set_priority(fd, lp_ctx, -MAX_PRIO);
>> +
>> +       hp_ctx = gem_context_create(fd);
>> +       ctx_set_priority(fd, hp_ctx, MAX_PRIO);
>> +
>> +       igt_require(setup_execbuf(fd, &execbuf, obj, reloc, engine) == 0);
>> +       execbuf.rsvd1 = lp_ctx;
>> +
>> +       /*Stall execution and fill ring*/
>> +       lp_batch = igt_spin_batch_new(fd, lp_ctx, engine, 0);
>> +       igt_fork(child_no, 1) {
>> +               fill_ring(fd, &execbuf, 0, timeout);
>> +       }
>> +
>> +       /*We don't know when the ring will be full so keep sending in a loop*/
> 
> Yes we do. See measure_ring_size.
> 
> static void bind_to_cpu(int cpu)
> {
> 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> 	struct sched_param rt = {.sched_priority = 99 };
> 	cpu_set_t allowed;
> 
> 	igt_assert(sched_setscheduler(getpid(), SCHED_RR | SCHED_RESET_ON_FORK, &rt) == 0);
> 
> 	CPU_ZERO(&allowed);
> 	CPU_SET(cpu % ncpus, &allowed);
> 	igt_assert(sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed) == 0);
> }
> 
> setup timer
> execbuf.rsvd1 = ctx_lo;
> while (__raw_gem_execbuf(fd, &execbuf) == 0)
> 	;
> 
> /* steal cpu */
> bind_to_cpu(0);
> igt_fork(child, 1) {
> 	/* this child is forced to wait for parent to sleep */
> 	execbuf.rsvd1 = ctx_hi;
> 	setup timer;
> 	*success = __raw_gem_execbuf(fd, &execbuf) == 0;
> }
> setup 2*timer
> __raw_gem_execbuf(fd, &execbuf); /* sleeps under mutex, releasing child
> */
> 
> igt_terminate_spin_batches();
> igt_waitchildren();
> 
> igt_assert(*success);
> 
> Timer can be safely 10ms.

Isn't this a bit too complicated? Wouldn't a "keep poking at it for a 
while" approach just do the same while being more readable?

-Antonio

> 
> Similarly:
> 
> race set-domain (pretty much any GEM ioctl ends up in set-domain) vs
> spin-batch, when successful then try any set-domain ioctl from a second
> client and observe that it too is blocked on the first client hogging.
> 
> end:
> For the purpose of testing, just create a debugfs that acquires
> struct_mutex on opening. Then test every ioctl and trap from a second
> client.
> -Chris
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test
  2017-08-17 15:14   ` Antonio Argenziano
@ 2017-08-17 15:38     ` Chris Wilson
  0 siblings, 0 replies; 7+ messages in thread
From: Chris Wilson @ 2017-08-17 15:38 UTC (permalink / raw)
  To: Antonio Argenziano, intel-gfx

Quoting Antonio Argenziano (2017-08-17 16:14:04)
> 
> 
> On 15/08/17 15:35, Chris Wilson wrote:
> > Quoting Antonio Argenziano (2017-08-15 22:44:21)
> >> Sending as RFC to get feedback on what would be the correct behaviour of
> >> the driver and, therefore, if the test is valid.
> > 
> > It's not a preemption specific bug. It is fair to say that any client
> > blocking any other client over a non-contended resource is an issue.
> > Skip to end for a really easy way to demonstrate this.
> 
> Ok, I'll push a patch then.
> 
> > 
> >> We do a wait while holding the mutex if we are adding a request and figure
> >> out that there is no more space in the ring buffer.
> >> Is that considered a bug?
> > 
> > Yes, but it is one of many priority inversion problems we have because
> > we have a BKL. Timeframe for fixing it is a few more years.
> > 
> >> +static void wait_batch(int fd, uint32_t handle)
> >> +{
> >> +       int64_t timeout = 1ull * NSEC_PER_SEC; //1 sec
> >> +
> >> +       if(gem_wait(fd, handle, &timeout) != 0) {
> >> +               //Force reset and fail the test
> >> +               igt_force_gpu_reset(fd);
> > 
> > Just terminate the spin batches.
> > 
> >> +               igt_assert_f(0, "[0x%x] batch did not complete!", handle);
> >> +       }
> >> +}
> >> +
> >> +/*
> >> + * This test checks that is possible for a high priority request to trigger a
> >> + * preemption if another context has filled its ringbuffer.
> >> + * The aim of the test is to make sure that high priority requests cannot be
> >> + * stalled by low priority tasks.
> >> + * */
> >> +static void preempt_while_ringbuffer_full(int fd, uint32_t engine)
> >> +{
> >> +       uint32_t hp_ctx, lp_ctx;
> >> +       uint32_t hp_batch;
> >> +       igt_spin_t *lp_batch;
> >> +
> >> +       struct drm_i915_gem_exec_object2 obj[2];
> >> +       struct drm_i915_gem_relocation_entry reloc[1024];
> > 
> > That's a bit excessive for this pi test, no ?
> 
> Just wanted to reuse the utility functions in the test with minimal changes.
> 
> > 
> >> +       struct drm_i915_gem_execbuffer2 execbuf;
> >> +       const unsigned timeout = 10;
> >> +
> >> +       lp_ctx = gem_context_create(fd);
> >> +       ctx_set_priority(fd, lp_ctx, -MAX_PRIO);
> >> +
> >> +       hp_ctx = gem_context_create(fd);
> >> +       ctx_set_priority(fd, hp_ctx, MAX_PRIO);
> >> +
> >> +       igt_require(setup_execbuf(fd, &execbuf, obj, reloc, engine) == 0);
> >> +       execbuf.rsvd1 = lp_ctx;
> >> +
> >> +       /*Stall execution and fill ring*/
> >> +       lp_batch = igt_spin_batch_new(fd, lp_ctx, engine, 0);
> >> +       igt_fork(child_no, 1) {
> >> +               fill_ring(fd, &execbuf, 0, timeout);
> >> +       }
> >> +
> >> +       /*We don't know when the ring will be full so keep sending in a loop*/
> > 
> > Yes we do. See measure_ring_size.
> > 
> > static void bind_to_cpu(int cpu)
> > {
> >       const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
> >       struct sched_param rt = {.sched_priority = 99 };
> >       cpu_set_t allowed;
> > 
> >       igt_assert(sched_setscheduler(getpid(), SCHED_RR | SCHED_RESET_ON_FORK, &rt) == 0);
> > 
> >       CPU_ZERO(&allowed);
> >       CPU_SET(cpu % ncpus, &allowed);
> >       igt_assert(sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed) == 0);
> > }
> > 
> > setup timer
> > execbuf.rsvd1 = ctx_lo;
> > while (__raw_gem_execbuf(fd, &execbuf) == 0)
> >       ;
> > 
> > /* steal cpu */
> > bind_to_cpu(0);
> > igt_fork(child, 1) {
> >       /* this child is forced to wait for parent to sleep */
> >       execbuf.rsvd1 = ctx_hi;
> >       setup timer;
> >       *success = __raw_gem_execbuf(fd, &execbuf) == 0;
> > }
> > setup 2*timer
> > __raw_gem_execbuf(fd, &execbuf); /* sleeps under mutex, releasing child
> > */
> > 
> > igt_terminate_spin_batches();
> > igt_waitchildren();
> > 
> > igt_assert(*success);
> > 
> > Timer can be safely 10ms.
> 
> Isn't this a bit too complicated? Wouldn't a "keep poking at it for a 
> while" approach just do the same while being more readable?

Be explicit and use fine control to exactly describe the behaviour you
want. This case is one client exhausts their ring, it will block not
only itself but all users.

Please don't add this to gem_ringfill, if you consider it a scheduling /
priority inversion issue, add it to gem_exec_scheduler. If you want to
tackle more generally as being just one of many, many ways a client can
block another client, start a new test. Considering just how general
this problem is, I'd rather we tackle the problem of modelling the
driver and a system to find all such contention points.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-08-17 15:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-15 21:44 [RFC i-g-t] igt/gem_ringfill: Adds full ringbuffer preemption test Antonio Argenziano
2017-08-15 21:47 ` ✗ Fi.CI.BAT: failure for " Patchwork
2017-08-15 22:35 ` [RFC i-g-t] " Chris Wilson
2017-08-16  7:39   ` Chris Wilson
2017-08-17 15:14   ` Antonio Argenziano
2017-08-17 15:38     ` Chris Wilson
2017-08-15 23:32 ` Chris Wilson

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.