[Intel-gfx] [PATCH] drm/i915: Lock signaler timeline while navigating

Chris Wilson chris at chris-wilson.co.uk
Tue Sep 17 15:04:03 UTC 2019


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);

> > +             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.
-Chris


More information about the Intel-gfx mailing list