[Intel-gfx] [PATCH] drm/i915: Spin until breadcrumb threads are complete
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Wed Nov 9 14:53:34 UTC 2016
On 08/11/2016 14:37, Chris Wilson wrote:
> When we need to reset the global seqno on wraparound, we have to wait
> until the current rbtrees are drained (or otherwise the next waiter will
> be out of sequence). The current mechanism to kick and spin until
> complete, may exit too early as it would break if the target thread was
> currently running. Instead, we must wake up the threads, but keep
> spinning until the trees have been deleted.
>
> In order to appease Tvrtko, busy spin rather than yield().
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> ---
> drivers/gpu/drm/i915/i915_gem_request.c | 5 ++---
> drivers/gpu/drm/i915/intel_breadcrumbs.c | 31 ++++++++++++-------------------
> drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +--
> 3 files changed, 15 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
> index d866069c1767..6c71637d4be1 100644
> --- a/drivers/gpu/drm/i915/i915_gem_request.c
> +++ b/drivers/gpu/drm/i915/i915_gem_request.c
> @@ -319,9 +319,8 @@ static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno)
>
> /* If the seqno wraps around, we need to clear the breadcrumb rbtree */
> if (!i915_seqno_passed(seqno, atomic_read(&timeline->next_seqno))) {
> - while (intel_kick_waiters(i915) || intel_kick_signalers(i915))
> - yield();
> - yield();
> + while (intel_breadcrumbs_busy(i915))
> + cond_resched(); /* spin until threads are complete */
> }
> atomic_set(&timeline->next_seqno, seqno);
>
> diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> index c410d3d6465f..c9c46a538edb 100644
> --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
> +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> @@ -629,35 +629,28 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
> cancel_fake_irq(engine);
> }
>
> -unsigned int intel_kick_waiters(struct drm_i915_private *i915)
> +unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915)
> {
> struct intel_engine_cs *engine;
> enum intel_engine_id id;
> unsigned int mask = 0;
>
> - /* To avoid the task_struct disappearing beneath us as we wake up
> - * the process, we must first inspect the task_struct->state under the
> - * RCU lock, i.e. as we call wake_up_process() we must be holding the
> - * rcu_read_lock().
> - */
> - for_each_engine(engine, i915, id)
> - if (unlikely(intel_engine_wakeup(engine)))
> - mask |= intel_engine_flag(engine);
> + for_each_engine(engine, i915, id) {
> + struct intel_breadcrumbs *b = &engine->breadcrumbs;
>
> - return mask;
> -}
> + spin_lock_irq(&b->lock);
>
> -unsigned int intel_kick_signalers(struct drm_i915_private *i915)
> -{
> - struct intel_engine_cs *engine;
> - enum intel_engine_id id;
> - unsigned int mask = 0;
> + if (b->first_wait) {
> + wake_up_process(b->first_wait->tsk);
> + mask |= intel_engine_flag(engine);
> + }
>
> - for_each_engine(engine, i915, id) {
> - if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) {
> - wake_up_process(engine->breadcrumbs.signaler);
> + if (b->first_signal) {
> + wake_up_process(b->signaler);
> mask |= intel_engine_flag(engine);
> }
> +
> + spin_unlock_irq(&b->lock);
> }
>
> return mask;
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index cbc148863a03..3466b4e77e7c 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -587,7 +587,6 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine)
>
> void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
> void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
> -unsigned int intel_kick_waiters(struct drm_i915_private *i915);
> -unsigned int intel_kick_signalers(struct drm_i915_private *i915);
> +unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915);
>
> #endif /* _INTEL_RINGBUFFER_H_ */
>
Looks OK. Side note to myself - catch up on the rcu waiter business.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list