drm/i915/shrinker: Wrap need_resched() inside preempt-disable
In order for us to successfully detect the end of a timeslice, preemption must be disabled. Otherwise, inside the loop we may be preempted many times without our noticing, and each time our timeslice will be reset, invalidating need_resched() Reported-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reported-by: Tomi Sarvela <tomi.p.sarvela@intel.com> Fixes:zero-colors290271de34
("drm/i915: Spin for struct_mutex inside shrinker") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: <drm-intel-fixes@lists.freedesktop.org> # v4.13-rc1+ Link: https://patchwork.freedesktop.org/patch/msgid/20170804104135.26805-1-chris@chris-wilson.co.uk Tested-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> (cherry picked from commit6cb0c6ad9e
) Signed-off-by: Jani Nikula <jani.nikula@intel.com>
parent
b5fa57ddc4
commit
cd82f37a9d
|
@ -43,16 +43,21 @@ static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MUTEX_TRYLOCK_FAILED:
|
case MUTEX_TRYLOCK_FAILED:
|
||||||
|
*unlock = false;
|
||||||
|
preempt_disable();
|
||||||
do {
|
do {
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
if (mutex_trylock(&dev_priv->drm.struct_mutex)) {
|
if (mutex_trylock(&dev_priv->drm.struct_mutex)) {
|
||||||
case MUTEX_TRYLOCK_SUCCESS:
|
|
||||||
*unlock = true;
|
*unlock = true;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
} while (!need_resched());
|
} while (!need_resched());
|
||||||
|
preempt_enable();
|
||||||
|
return *unlock;
|
||||||
|
|
||||||
return false;
|
case MUTEX_TRYLOCK_SUCCESS:
|
||||||
|
*unlock = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG();
|
BUG();
|
||||||
|
|
Loading…
Reference in New Issue