[Intel-gfx] [PATCH 17/50] drm/i915: Switch back to an array of logical per-engine HW contexts

Chris Wilson chris at chris-wilson.co.uk
Fri Apr 12 13:43:14 UTC 2019


Quoting Tvrtko Ursulin (2019-04-12 14:31:31)
> 
> On 12/04/2019 09:53, Chris Wilson wrote:
> > @@ -875,22 +927,27 @@ static int context_barrier_task(struct i915_gem_context *ctx,
> >       i915_active_init(i915, &cb->base, cb_retire);
> >       i915_active_acquire(&cb->base);
> >   
> > -     rbtree_postorder_for_each_entry_safe(ce, next, &ctx->hw_contexts, node) {
> > -             struct intel_engine_cs *engine = ce->engine;
> > +     for_each_gem_engine(it, ctx) {
> > +             struct intel_context *ce = it.context;
> >               struct i915_request *rq;
> >   
> > -             if (!(engine->mask & engines))
> > +             if (!(ce->engine->mask & engines))
> > +                     continue;
> > +
> > +             if (!intel_context_is_pinned(ce))
> >                       continue;
> >   
> >               if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
> > -                                    engine->mask)) {
> > +                                    ce->engine->mask)) {
> >                       err = -ENXIO;
> > +                     i915_gem_engines_iter_fini(&it);
> 
> This would be our only iterator which needs manual cleanup. But only on 
> abort, not normal termination.
> 
> Would it be cleaner if for_each_gem_engine took engines which the caller 
> would previously have to obtain via i915_gem_context_engine_list_lock? 
> And the caller would also be obviously responsible for unlocking.

But then it's just a for (i = 0; i < engines->num_engines; i++) again.
I'm not really convinced that if the caller has to do everything anyway,
replacing the for() is much of a gain :)

> >                       break;
> >               }
> >   
> > -             rq = i915_request_alloc(engine, ctx);
> > +             rq = intel_context_create_request(ce);
> >               if (IS_ERR(rq)) {
> >                       err = PTR_ERR(rq);
> > +                     i915_gem_engines_iter_fini(&it);
> >                       break;
> >               }
> >   
> > @@ -901,8 +958,10 @@ static int context_barrier_task(struct i915_gem_context *ctx,
> >                       err = i915_active_ref(&cb->base, rq->fence.context, rq);
> >   
> >               i915_request_add(rq);
> > -             if (err)
> > +             if (err) {
> > +                     i915_gem_engines_iter_fini(&it);
> >                       break;
> > +             }
> >       }
> >   
> >       cb->task = err ? NULL : task; /* caller needs to unwind instead */
> > @@ -1739,6 +1798,43 @@ int __i915_gem_context_pin_hw_id(struct i915_gem_context *ctx)
> >       return err;
> >   }
> >   
> > +/* GEM context-engines iterator: for_each_gem_engine() */
> > +bool i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
> > +{
> > +     if (!it->engines)
> > +             goto end;
> 
> When can engines be null? Should it be GEM_BUG_ON if onyl when used 
> outside the for_each_gem_engine?

Hmm, it can't. I seem to have been unusually defensive!

> > +     do {
> > +             if (it->idx >= it->engines->num_engines)
> > +                     goto end;
> > +
> > +             it->context = it->engines->engines[it->idx++];
> > +     } while (!it->context);
> > +
> > +     return true;
> > +
> > +end:
> > +     i915_gem_engines_iter_fini(it);
> > +     return false;
> > +}
> > +
> > +void i915_gem_engines_iter_init(struct i915_gem_engines_iter *it,
> > +                             struct i915_gem_context *ctx)
> > +{
> > +     it->gem_context = ctx;
> > +     it->engines = i915_gem_context_engine_list_lock(ctx);
> > +     it->idx = 0;
> 
> Clear it->context just in case?
> 
> > +}
> > +
> > +void i915_gem_engines_iter_fini(struct i915_gem_engines_iter *it)
> > +{
> > +     struct i915_gem_context *ctx;
> > +
> > +     ctx = fetch_and_zero(&it->gem_context);
> 
> This is iter_fini can be called multiple times? When does that come to 
> play? Oh... when i915_gem_engines_iter_next went past the array and the 
> loop decides to bail out.

Yeah, I was just worrying about the mix of the user calling
	iter_fini();
	continue;

> If iterator took engines as parameter this could also go.

Equally if there was no iterator :)

So is the iterator worth it? If I have to do the locking and list management
in the caller, I would say no. Yay or nay?
-Chris


More information about the Intel-gfx mailing list