The first contention point we hit using syncobjs from concurrent threads is the spinlock guarding drm_syncobj_find(). We use an RCU-safe idr to store the syncobj, so if we employ RCU to free drm_syncobj and be careful in acquiring the reference (as we may now observe zombie synocbjs in the idr) we can do a lockless drm_syncobj_find(). Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/drm_syncobj.c | 10 +++++----- include/drm/drm_syncobj.h | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 38eca783a78c..cb5de50174ed 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -69,14 +69,14 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, { struct drm_syncobj *syncobj; - spin_lock(&file_private->syncobj_table_lock); + rcu_read_lock(); /* Check if we currently have a reference on the object */ syncobj = idr_find(&file_private->syncobj_idr, handle); - if (syncobj) - drm_syncobj_get(syncobj); + if (syncobj && !kref_get_unless_zero(&syncobj->refcount)) + syncobj = NULL; - spin_unlock(&file_private->syncobj_table_lock); + rcu_read_unlock(); return syncobj; } @@ -151,7 +151,7 @@ void drm_syncobj_free(struct kref *kref) syncobj_notify(syncobj, NULL); dma_fence_put(syncobj->fence); - kfree(syncobj); + kfree_rcu(syncobj, rcu); } EXPORT_SYMBOL(drm_syncobj_free); diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index b8f60d6793fb..88c949d2cb34 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -56,6 +56,8 @@ struct drm_syncobj { * a file backing for this syncobj. */ struct file *file; + + struct rcu_head rcu; }; void drm_syncobj_free(struct kref *kref); -- 2.13.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel