[Intel-gfx] [PATCH v2] drm/i915/gem: Move obj->lut_list under its own lock
Ruhl, Michael J
michael.j.ruhl at intel.com
Tue Jun 30 19:11:16 UTC 2020
>-----Original Message-----
>From: Intel-gfx <intel-gfx-bounces at lists.freedesktop.org> On Behalf Of Chris
>Wilson
>Sent: Monday, June 29, 2020 7:36 AM
>To: intel-gfx at lists.freedesktop.org
>Cc: Chris Wilson <chris at chris-wilson.co.uk>
>Subject: [Intel-gfx] [PATCH v2] drm/i915/gem: Move obj->lut_list under its
>own lock
>
>The obj->lut_list is traversed when the object is closed as the file
>table is destroyed during process termination. As this occurs before we
>kill any outstanding context if, due to some bug or another, the closure
>is blocked, then we fail to shootdown any inflight operations
>potentially leaving the GPU spinning forever. As we only need to guard
>the list against concurrent closures and insertions, the hold is short
>and merits being treated as a simple spinlock.
The comment:
/* Break long locks, and carefully continue on from this spot */
seems to be contrary to your "the hold is short" comment. Is calling out
this apparent worst case scenario (i.e. how it could happen), worth
documenting?
>Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
>---
> drivers/gpu/drm/i915/gem/i915_gem_context.c | 6 ++----
> .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 4 ++--
> drivers/gpu/drm/i915/gem/i915_gem_object.c | 21 +++++++++++++------
> .../gpu/drm/i915/gem/i915_gem_object_types.h | 1 +
> 4 files changed, 20 insertions(+), 12 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c
>b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>index 5c13809dc3c8..6675447a47b9 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
>@@ -112,8 +112,7 @@ static void lut_close(struct i915_gem_context *ctx)
> if (!kref_get_unless_zero(&obj->base.refcount))
> continue;
>
>- rcu_read_unlock();
>- i915_gem_object_lock(obj);
>+ spin_lock(&obj->lut_lock);
> list_for_each_entry(lut, &obj->lut_list, obj_link) {
> if (lut->ctx != ctx)
> continue;
>@@ -124,8 +123,7 @@ static void lut_close(struct i915_gem_context *ctx)
> list_del(&lut->obj_link);
> break;
> }
>- i915_gem_object_unlock(obj);
>- rcu_read_lock();
>+ spin_unlock(&obj->lut_lock);
>
> if (&lut->obj_link != &obj->lut_list) {
> i915_lut_handle_free(lut);
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
>b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
>index c38ab51e82f0..b4862afaaf28 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
>@@ -789,14 +789,14 @@ static int __eb_add_lut(struct i915_execbuffer *eb,
> if (err == 0) { /* And nor has this handle */
> struct drm_i915_gem_object *obj = vma->obj;
>
>- i915_gem_object_lock(obj);
>+ spin_lock(&obj->lut_lock);
> if (idr_find(&eb->file->object_idr, handle) == obj) {
> list_add(&lut->obj_link, &obj->lut_list);
> } else {
> radix_tree_delete(&ctx->handles_vma,
>handle);
> err = -ENOENT;
> }
>- i915_gem_object_unlock(obj);
>+ spin_unlock(&obj->lut_lock);
> }
> mutex_unlock(&ctx->mutex);
> }
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>index b6ec5b50d93b..6b69191c5543 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>@@ -61,6 +61,7 @@ void i915_gem_object_init(struct drm_i915_gem_object
>*obj,
> INIT_LIST_HEAD(&obj->mm.link);
>
> INIT_LIST_HEAD(&obj->lut_list);
>+ spin_lock_init(&obj->lut_lock);
>
> spin_lock_init(&obj->mmo.lock);
> obj->mmo.offsets = RB_ROOT;
>@@ -104,21 +105,29 @@ void i915_gem_close_object(struct
>drm_gem_object *gem, struct drm_file *file)
> {
> struct drm_i915_gem_object *obj = to_intel_bo(gem);
> struct drm_i915_file_private *fpriv = file->driver_priv;
>+ struct i915_lut_handle bookmark = {};
> struct i915_mmap_offset *mmo, *mn;
> struct i915_lut_handle *lut, *ln;
> LIST_HEAD(close);
>
>- i915_gem_object_lock(obj);
>+ spin_lock(&obj->lut_lock);
> list_for_each_entry_safe(lut, ln, &obj->lut_list, obj_link) {
> struct i915_gem_context *ctx = lut->ctx;
>
>- if (ctx->file_priv != fpriv)
>- continue;
>+ if (ctx && ctx->file_priv == fpriv) {
Null checking ctx was not done before. I think this changed with the possible cond_resched?
Or is this just being extra cautious?
Thanks,
Mike
>+ i915_gem_context_get(ctx);
>+ list_move(&lut->obj_link, &close);
>+ }
>
>- i915_gem_context_get(ctx);
>- list_move(&lut->obj_link, &close);
>+ /* Break long locks, and carefully continue on from this spot */
>+ if (&ln->obj_link != &obj->lut_list) {
>+ list_add_tail(&bookmark.obj_link, &ln->obj_link);
>+ if (cond_resched_lock(&obj->lut_lock))
>+ list_safe_reset_next(&bookmark, ln,
>obj_link);
>+ __list_del_entry(&bookmark.obj_link);
>+ }
> }
>- i915_gem_object_unlock(obj);
>+ spin_unlock(&obj->lut_lock);
>
> spin_lock(&obj->mmo.lock);
> rbtree_postorder_for_each_entry_safe(mmo, mn, &obj-
>>mmo.offsets, offset)
>diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>index b1f82a11aef2..5335f799b548 100644
>--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>@@ -121,6 +121,7 @@ struct drm_i915_gem_object {
> * this translation from object to context->handles_vma.
> */
> struct list_head lut_list;
>+ spinlock_t lut_lock; /* guards lut_list */
>
> /** Stolen memory for this object, instead of being backed by
>shmem. */
> struct drm_mm_node *stolen;
>--
>2.20.1
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx at lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list