Am 17.06.2017 um 00:00 schrieb axie:


On 2017-06-16 01:48 PM, Christian König wrote:
Am 16.06.2017 um 07:03 schrieb Alex Xie:
Use rw_semaphore instead of mutex for bo_lists.

In original function amdgpu_bo_list_get, the waiting
for result->lock can be quite long while mutex
bo_list_lock was holding. It can make other tasks
waiting for bo_list_lock for long period too.
Change bo_list_lock to rw_semaphore can avoid most of
such long waiting.

Secondly, this patch allows several tasks(readers of idr)
to proceed at the same time.

v2: use rcu and kref (Dave Airlie and Christian König)

Signed-off-by: Alex Xie <[email protected]>
---
  drivers/gpu/drm/amd/amdgpu/amdgpu.h         |  2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 40 ++++++++++++++++++++---------
  2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 063fc73..e9b3981 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -871,6 +871,8 @@ struct amdgpu_fpriv {
    struct amdgpu_bo_list {
      struct mutex lock;
+    struct rcu_head rhead;
+    struct kref refcount;
      struct amdgpu_bo *gds_obj;
      struct amdgpu_bo *gws_obj;
      struct amdgpu_bo *oa_obj;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index 5af956f..efa6903 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -41,6 +41,20 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
                       struct drm_amdgpu_bo_list_entry *info,
                       unsigned num_entries);
  +static void amdgpu_bo_list_release_rcu(struct kref *ref)
+{
+    unsigned i;
+ struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list,
+                           refcount);
+
+    for (i = 0; i < list->num_entries; ++i)
+        amdgpu_bo_unref(&list->array[i].robj);
+
+    mutex_destroy(&list->lock);
+    drm_free_large(list->array);
+    kfree_rcu(list, rhead);
+}
+

I'm probably missing something here: Why a new function and not change the existing amdgpu_bo_list_free() to use kfree_rcu instead?

Apart from that the patch looks good to me,
Christian.

amdgpu_bo_list_free() is called by amdgpu_driver_postclose_kms in file amdgpu_kms.c too. For amdgpu_driver_postclose_kms, there is no need to call kfree_rcu. It is more suitable to call kfree.

So we need two different release/free functions. Then I created a new function for kref_put.

Ah, I see. Well call from amdgpu_driver_postclose_kms() is only used when the application crashes and doesn't clean up properly after itself.

Not sure if it's a good idea to duplicate the code because of this. Waiting for an RCU grace period is a no-op in most cases (it's very likely that all other CPUs are doing something in userspace), so kfree_rcu is rather cheap.

Either way the patch is Reviewed-by: Christian König <[email protected]>.



  static int amdgpu_bo_list_create(struct amdgpu_device *adev,
                   struct drm_file *filp,
                   struct drm_amdgpu_bo_list_entry *info,
@@ -57,7 +71,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev,
        /* initialize bo list*/
      mutex_init(&list->lock);
-
+    kref_init(&list->refcount);
      r = amdgpu_bo_list_set(adev, filp, list, info, num_entries);
      if (r) {
          kfree(list);
@@ -83,14 +97,9 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
        mutex_lock(&fpriv->bo_list_lock);
      list = idr_remove(&fpriv->bo_list_handles, id);
-    if (list) {
-        /* Another user may have a reference to this list still */
-        mutex_lock(&list->lock);
-        mutex_unlock(&list->lock);
-        amdgpu_bo_list_free(list);
-    }
-
      mutex_unlock(&fpriv->bo_list_lock);
+    if (list)
+        kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
  }
    static int amdgpu_bo_list_set(struct amdgpu_device *adev,
@@ -185,11 +194,17 @@ amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id)
  {
      struct amdgpu_bo_list *result;
  -    mutex_lock(&fpriv->bo_list_lock);
+    rcu_read_lock();
      result = idr_find(&fpriv->bo_list_handles, id);
-    if (result)
-        mutex_lock(&result->lock);
-    mutex_unlock(&fpriv->bo_list_lock);
+
+    if (result) {
+        if (kref_get_unless_zero(&result->refcount))
+            mutex_lock(&result->lock);
+        else
+            result = NULL;
+    }
+    rcu_read_unlock();
+
      return result;
  }
@@ -227,6 +242,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list,
  void amdgpu_bo_list_put(struct amdgpu_bo_list *list)
  {
      mutex_unlock(&list->lock);
+    kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
  }
    void amdgpu_bo_list_free(struct amdgpu_bo_list *list)



_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to