[PATCH] drm: RCU syncobj

Chris Wilson chris at chris-wilson.co.uk
Thu Aug 10 19:28:30 UTC 2017


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 at chris-wilson.co.uk>
---
 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



More information about the dri-devel mailing list