[Intel-gfx] [PATCH v2] drm/i915: Only report a wakeup if the waiter was truly asleep

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Thu Apr 6 08:04:23 UTC 2017


On 05/04/2017 13:47, Chris Wilson wrote:
> If we attempt to wake up a waiter, who is currently checking the seqno
> it will be in the TASK_INTERRUPTIBLE state and ttwu will report success.
> However, it is actually awake and functioning -- so delay reporting the
> actual wake up until it sleeps.
>
> v2: Defend against !CONFIG_SMP
>
> References: https://bugs.freedesktop.org/show_bug.cgi?id=100007
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_breadcrumbs.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> index 9ccbf26124c6..4fdf7868e2f1 100644
> --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
> +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> @@ -27,6 +27,23 @@
>
>  #include "i915_drv.h"
>
> +#ifdef CONFIG_SMP
> +#define task_asleep(tsk) (!(tsk)->on_cpu)
> +#else
> +#define task_asleep(tsk) ((tsk) != current)
> +#endif

I've looked and on_cpu seems to be a boolean indicating whether a task 
is currently running. Which means on UP tsk != current is a correct 
replacement. However ...

> +
> +static inline bool __wake_up_sleeper(struct task_struct *tsk)
> +{
> +	/* Be careful not to report a successful wakeup if the waiter is
> +	 * currently processing the seqno, where it will have already
> +	 * called set_task_state(TASK_INTERRUPTIBLE). We first check whether
> +	 * the task is currently asleep before calling ttwu, and then we
> +	 * only report success if we were the ones to then trigger the wakeup.
> +	 */
> +	return task_asleep(tsk) && wake_up_process(tsk);

... I don't see why on SMP task couldn't get "on_cpu" between the 
task_asleep() and wake_up_process? That would then foil the test and 
just shrink the race window a bit.

Regards,

Tvrtko

> +}
> +
>  static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
>  {
>  	struct intel_wait *wait;
> @@ -37,7 +54,7 @@ static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
>  	wait = b->irq_wait;
>  	if (wait) {
>  		result = ENGINE_WAKEUP_WAITER;
> -		if (wake_up_process(wait->tsk))
> +		if (__wake_up_sleeper(wait->tsk))
>  			result |= ENGINE_WAKEUP_ASLEEP;
>  	}
>
> @@ -198,7 +215,7 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
>
>  	rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) {
>  		RB_CLEAR_NODE(&wait->node);
> -		if (wake_up_process(wait->tsk) && wait == first)
> +		if (__wake_up_sleeper(wait->tsk) && wait == first)
>  			missed_breadcrumb(engine);
>  	}
>  	b->waiters = RB_ROOT;
>


More information about the Intel-gfx mailing list