[PATCH 2/2] drm/amdgpu: Optimize mutex usage (v2)
axie
axie at amd.com
Fri Jun 16 22:00:21 UTC 2017
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 <AlexBin.Xie at amd.com>
>> ---
>> 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.
>
>> 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)
>
>
More information about the amd-gfx
mailing list