diff mbox series

[2/2] drm/syncobj: Lookup the syncobj with RCU protection

Message ID 20190802163659.23255-2-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series [1/2] drm/syncobj: Convert syncobj_idr to XArray | expand

Commit Message

Chris Wilson Aug. 2, 2019, 4:36 p.m. UTC
Relax the spinlock used for looking up the handle in the XArray and
acquiring a reference to it to an RCU protected critical section. This
incurs the requirement that we protect the syncobj struct itself using
RCU, which we achieve by simply calling kfree_rcu() and being more
careful in acquiring our reference.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_syncobj.c | 12 +++++-------
 include/drm/drm_syncobj.h     |  2 ++
 2 files changed, 7 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 4fc71dc9fc43..aafc03986a48 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -86,13 +86,11 @@  struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
 {
 	struct drm_syncobj *syncobj;
 
-	xa_lock(&file_private->syncobjs);
-
+	rcu_read_lock();
 	syncobj = xa_load(&file_private->syncobjs, handle);
-	if (syncobj)
-		drm_syncobj_get(syncobj);
-
-	xa_unlock(&file_private->syncobjs);
+	if (syncobj && !kref_get_unless_zero(&syncobj->refcount))
+		syncobj = NULL;
+	rcu_read_unlock();
 
 	return syncobj;
 }
@@ -309,7 +307,7 @@  void drm_syncobj_free(struct kref *kref)
 						   struct drm_syncobj,
 						   refcount);
 	drm_syncobj_replace_fence(syncobj, NULL);
-	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 6cf7243a1dc5..7c1503d47abf 100644
--- a/include/drm/drm_syncobj.h
+++ b/include/drm/drm_syncobj.h
@@ -61,6 +61,8 @@  struct drm_syncobj {
 	 * @file: A file backing for this syncobj.
 	 */
 	struct file *file;
+
+	struct rcu_head rcu;
 };
 
 void drm_syncobj_free(struct kref *kref);