@@ -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);
@@ -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);
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@chris-wilson.co.uk> --- drivers/gpu/drm/drm_syncobj.c | 10 +++++----- include/drm/drm_syncobj.h | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-)