[Intel-gfx] [PATCH] drm/i915: Lock signaler timeline while navigating
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Tue Sep 17 15:22:51 UTC 2019
On 17/09/2019 16:04, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-09-17 15:51:45)
>>
>> On 17/09/2019 08:43, Chris Wilson wrote:
>>> As we need to take a walk back along the signaler timeline to find the
>>> fence before upon which we want to wait, we need to lock that timeline
>>> to prevent it being modified as we walk. Similarly, we also need to
>>> acquire a reference to the earlier fence while it still exists!
>>>
>>> Though we lack the correct locking today, we are saved by the
>>> overarching struct_mutex -- but that protection is being removed.
>>>
>>> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
>>> ---
>>> drivers/gpu/drm/i915/i915_request.c | 30 +++++++++++++++++++++++------
>>> 1 file changed, 24 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
>>> index f12358150097..452ad7a8ff0c 100644
>>> --- a/drivers/gpu/drm/i915/i915_request.c
>>> +++ b/drivers/gpu/drm/i915/i915_request.c
>>> @@ -767,16 +767,34 @@ i915_request_create(struct intel_context *ce)
>>> static int
>>> i915_request_await_start(struct i915_request *rq, struct i915_request *signal)
>>> {
>>> - if (list_is_first(&signal->link, &signal->timeline->requests))
>>> + struct intel_timeline *tl = signal->timeline;
>>> + struct dma_fence *fence;
>>> + int err;
>>> +
>>> + if (list_is_first(&signal->link, &tl->requests))
>>> return 0;
>>>
>>> - signal = list_prev_entry(signal, link);
>>> - if (intel_timeline_sync_is_later(rq->timeline, &signal->fence))
>>> + if (mutex_lock_interruptible_nested(&tl->mutex, SINGLE_DEPTH_NESTING))
>>
>> We are getting more and more these nested ones and it will become
>> unmanageable to remember which ones, why and on what paths. Perhaps we
>> need a comment next to the member in the structure definition?
>
> The timeline mutex is held for request construction and retire; entry
> and exit of the timeline->requests. Since we have a request, it should
> be holding its rq->timeline->mutex; is that what you wish documented?
>
> Similarly that signal->timeline != rq->timeline.
>
> GEM_BUG_ON(signal->timeline == rq->timeline);
> lockdep_assert_held(&rq->timeline->mutex);
Yeah that helps.
>>> + return -EINTR;
>>> +
>>> + if (list_is_first(&signal->link, &tl->requests)) {
>>> + fence = NULL;
>>> + } else {
>>> + signal = list_prev_entry(signal, link);
>>> + fence = dma_fence_get_rcu(&signal->fence);
>>> + }
>>> + mutex_unlock(&tl->mutex);
>>> + if (!fence)
>>
>> Can it be no fence when it was obtained under the mutex?
>
> Yes. The previous fence may have been retired and so removed from the
> tl->requests before we acquire the mutex. It should not be freed while
> it is still in the list, i.e. dma_fence_get_rcu() should never return
> NULL.
I did not worry about the list_is_first check, just about
dma_fence_get_rcu. At least I'm happy that one is safe and v2 is even
better in this respect.
Regards,
Tvrtko
More information about the Intel-gfx
mailing list