[Intel-gfx] [PATCH 3/6] drm/i915: Tighten atomicity of i915_active_acquire vs i915_active_release

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Mon Jan 27 14:20:27 UTC 2020


On 26/01/2020 10:23, Chris Wilson wrote:
> As we use a mutex to serialise the first acquire (as it may be a lengthy
> operation), but only an atomic decrement for the release, we have to
> be careful in case a second thread races and completes both
> acquire/release as the first finishes its acquire.
> 
> Thread A			Thread B
> i915_active_acquire		i915_active_acquire
>    atomic_read() == 0		  atomic_read() == 0
>    mutex_lock()			  mutex_lock()
> 				  atomic_read() == 0
> 				    ref->active();
> 				  atomic_inc()
> 				  mutex_unlock()
>    atomic_read() == 1
> 				i915_active_release
> 				  atomic_dec_and_test() -> 0
> 				    ref->retire()
>    atomic_inc() -> 1
>    mutex_unlock()
> 
> So thread A has acquired the ref->active_count but since the ref was
> still active at the time, it did not initialise it. By switching the
> check inside the mutex to an atomic increment only if already active, we
> close the race.
> 
> Fixes: c9ad602feabe ("drm/i915: Split i915_active.mutex into an irq-safe spinlock for the rbtree")
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>   drivers/gpu/drm/i915/i915_active.c | 16 +++++++++-------
>   1 file changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
> index ace55d5d4ca7..9d6830885d2e 100644
> --- a/drivers/gpu/drm/i915/i915_active.c
> +++ b/drivers/gpu/drm/i915/i915_active.c
> @@ -416,13 +416,15 @@ int i915_active_acquire(struct i915_active *ref)
>   	if (err)
>   		return err;
>   
> -	if (!atomic_read(&ref->count) && ref->active)
> -		err = ref->active(ref);
> -	if (!err) {
> -		spin_lock_irq(&ref->tree_lock); /* vs __active_retire() */
> -		debug_active_activate(ref);
> -		atomic_inc(&ref->count);
> -		spin_unlock_irq(&ref->tree_lock);
> +	if (likely(!i915_active_acquire_if_busy(ref))) {
> +		if (ref->active)
> +			err = ref->active(ref);
> +		if (!err) {
> +			spin_lock_irq(&ref->tree_lock); /* __active_retire() */
> +			debug_active_activate(ref);
> +			atomic_inc(&ref->count);
> +			spin_unlock_irq(&ref->tree_lock);
> +		}
>   	}
>   
>   	mutex_unlock(&ref->mutex);
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Regards,

Tvrtko


More information about the Intel-gfx mailing list