[Intel-gfx] [PATCH] drm/i915: Hide unshrinkable context objects from the shrinker
Chris Wilson
chris at chris-wilson.co.uk
Fri Jul 19 15:50:57 UTC 2019
Quoting Tvrtko Ursulin (2019-07-19 16:38:28)
>
> On 19/07/2019 14:04, Chris Wilson wrote:
> > +void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj)
> > +{
> > + if (!list_empty(&obj->mm.link)) {
>
> Which lock protects this list head?
Hmm, I was thinking this would be nicely ordered by the caller. But no,
not strongly protected against the shrinker...
> > + struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&i915->mm.obj_lock, flags);
> > + GEM_BUG_ON(list_empty(&obj->mm.link));
..and so this should be a regular if() not BUG_ON.
> > + list_del_init(&obj->mm.link);
> > + i915->mm.shrink_count--;
> > + i915->mm.shrink_memory -= obj->base.size;
> > +
> > + spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
> > + }
> > +}
> > +
> > +void i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj)
> > +{
> > + GEM_BUG_ON(!i915_gem_object_has_pages(obj));
> > + GEM_BUG_ON(!list_empty(&obj->mm.link));
> > +
> > + if (i915_gem_object_is_shrinkable(obj)) {
> > + struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&i915->mm.obj_lock, flags);
> > + GEM_BUG_ON(!kref_read(&obj->base.refcount));
> > +
> > + list_add_tail(&obj->mm.link, &i915->mm.shrink_list);
> > + i915->mm.shrink_count++;
> > + i915->mm.shrink_memory += obj->base.size;
> > +
> > + spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
> > + }
> > +}
> > +
> > +void i915_gem_object_make_purgeable(struct drm_i915_gem_object *obj)
> > +{
> > + GEM_BUG_ON(!i915_gem_object_has_pages(obj));
> > + GEM_BUG_ON(!list_empty(&obj->mm.link));
> > +
> > + if (i915_gem_object_is_shrinkable(obj)) {
> > + struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&i915->mm.obj_lock, flags);
> > + GEM_BUG_ON(!kref_read(&obj->base.refcount));
> > +
> > + list_add_tail(&obj->mm.link, &i915->mm.purge_list);
> > + i915->mm.shrink_count++;
> > + i915->mm.shrink_memory += obj->base.size;
> > +
> > + spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
> > + }
> > +}
>
> Common helper for the above to passing in the correct list from each?
It's also worth making that has_pages into a has_pinned_pages.
> > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
> > index 9e4f51ce52ff..9830edda1ade 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_context.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_context.c
> > @@ -118,7 +118,7 @@ static int __context_pin_state(struct i915_vma *vma)
> > * And mark it as a globally pinned object to let the shrinker know
> > * it cannot reclaim the object until we release it.
> > */
> > - vma->obj->pin_global++;
> > + i915_vma_make_unshrinkable(vma);
> > vma->obj->mm.dirty = true;
> >
> > return 0;
> > @@ -126,8 +126,8 @@ static int __context_pin_state(struct i915_vma *vma)
> >
> > static void __context_unpin_state(struct i915_vma *vma)
> > {
> > - vma->obj->pin_global--;
> > __i915_vma_unpin(vma);
> > + i915_vma_make_shrinkable(vma);
> > }
> >
> > static void __intel_context_retire(struct i915_active *active)
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
> > index f7e69db4019d..5b16b233a059 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> > @@ -231,6 +231,8 @@ int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size)
> > if (ret)
> > goto err_unref;
> >
> > + i915_gem_object_make_unshrinkable(obj);
> > +
> > gt->scratch = vma;
> > return 0;
> >
> > diff --git a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
> > index 38ec11ae6ed7..d8efb88f33f3 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
> > @@ -1238,7 +1238,7 @@ int intel_ring_pin(struct intel_ring *ring)
> > goto err_ring;
> > }
> >
> > - vma->obj->pin_global++;
> > + i915_vma_make_unshrinkable(vma);
> >
> > GEM_BUG_ON(ring->vaddr);
> > ring->vaddr = addr;
> > @@ -1267,6 +1267,8 @@ void intel_ring_reset(struct intel_ring *ring, u32 tail)
> >
> > void intel_ring_unpin(struct intel_ring *ring)
> > {
> > + struct i915_vma *vma = ring->vma;
> > +
> > if (!atomic_dec_and_test(&ring->pin_count))
> > return;
> >
> > @@ -1275,18 +1277,17 @@ void intel_ring_unpin(struct intel_ring *ring)
> > /* Discard any unused bytes beyond that submitted to hw. */
> > intel_ring_reset(ring, ring->tail);
> >
> > - GEM_BUG_ON(!ring->vma);
> > - i915_vma_unset_ggtt_write(ring->vma);
> > - if (i915_vma_is_map_and_fenceable(ring->vma))
> > - i915_vma_unpin_iomap(ring->vma);
> > + i915_vma_unset_ggtt_write(vma);
> > + if (i915_vma_is_map_and_fenceable(vma))
> > + i915_vma_unpin_iomap(vma);
> > else
> > - i915_gem_object_unpin_map(ring->vma->obj);
> > + i915_gem_object_unpin_map(vma->obj);
> >
> > GEM_BUG_ON(!ring->vaddr);
> > ring->vaddr = NULL;
> >
> > - ring->vma->obj->pin_global--;
> > - i915_vma_unpin(ring->vma);
> > + i915_vma_unpin(vma);
> > + i915_vma_make_purgeable(vma);
>
> Why is ring purgeable and scratch or context state shrinkable?
Because the ring contains nothing, but context state must be preserved.
I was thinking the explicit selection would be clearer.
scratch will be thrown away at the end of the driver. I don't see an
instance where we make scratch shrinkable (except for a brief period it
is an internal object but is pinned).
> > +void i915_vma_make_unshrinkable(struct i915_vma *vma)
> > +{
> > + i915_gem_object_make_unshrinkable(vma->obj);
> > +}
> > +
> > +void i915_vma_make_shrinkable(struct i915_vma *vma)
> > +{
> > + i915_gem_object_make_shrinkable(vma->obj);
> > +}
> > +
> > +void i915_vma_make_purgeable(struct i915_vma *vma)
> > +{
> > + i915_gem_object_make_purgeable(vma->obj);
> > +}
>
> Would i915_vma_make_*object*_... be a better name? I am thinking the
> concept does not apply to vma's.
I'm planning ahead for a common backing store shared between objects and
vma, where vma doesn't operate on the object per-se, and we have a
first-class reference counted vma.
-Chris
More information about the Intel-gfx
mailing list