drm/amdgpu: Optimize mutex usage (v4)
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. 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) v3: update v1 commit message (Michel Dänzer) v4: rebase on upstream (Alex Deucher) Signed-off-by: Alex Xie <AlexBin.Xie@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
parent
99eea4df90
commit
5ac55629d6
|
@ -869,6 +869,8 @@ struct amdgpu_fpriv {
|
||||||
|
|
||||||
struct amdgpu_bo_list {
|
struct amdgpu_bo_list {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
struct rcu_head rhead;
|
||||||
|
struct kref refcount;
|
||||||
struct amdgpu_bo *gds_obj;
|
struct amdgpu_bo *gds_obj;
|
||||||
struct amdgpu_bo *gws_obj;
|
struct amdgpu_bo *gws_obj;
|
||||||
struct amdgpu_bo *oa_obj;
|
struct amdgpu_bo *oa_obj;
|
||||||
|
|
|
@ -41,6 +41,20 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
|
||||||
struct drm_amdgpu_bo_list_entry *info,
|
struct drm_amdgpu_bo_list_entry *info,
|
||||||
unsigned num_entries);
|
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);
|
||||||
|
kvfree(list->array);
|
||||||
|
kfree_rcu(list, rhead);
|
||||||
|
}
|
||||||
|
|
||||||
static int amdgpu_bo_list_create(struct amdgpu_device *adev,
|
static int amdgpu_bo_list_create(struct amdgpu_device *adev,
|
||||||
struct drm_file *filp,
|
struct drm_file *filp,
|
||||||
struct drm_amdgpu_bo_list_entry *info,
|
struct drm_amdgpu_bo_list_entry *info,
|
||||||
|
@ -57,7 +71,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev,
|
||||||
|
|
||||||
/* initialize bo list*/
|
/* initialize bo list*/
|
||||||
mutex_init(&list->lock);
|
mutex_init(&list->lock);
|
||||||
|
kref_init(&list->refcount);
|
||||||
r = amdgpu_bo_list_set(adev, filp, list, info, num_entries);
|
r = amdgpu_bo_list_set(adev, filp, list, info, num_entries);
|
||||||
if (r) {
|
if (r) {
|
||||||
kfree(list);
|
kfree(list);
|
||||||
|
@ -83,14 +97,9 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
|
||||||
|
|
||||||
mutex_lock(&fpriv->bo_list_lock);
|
mutex_lock(&fpriv->bo_list_lock);
|
||||||
list = idr_remove(&fpriv->bo_list_handles, id);
|
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);
|
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,
|
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;
|
struct amdgpu_bo_list *result;
|
||||||
|
|
||||||
mutex_lock(&fpriv->bo_list_lock);
|
rcu_read_lock();
|
||||||
result = idr_find(&fpriv->bo_list_handles, id);
|
result = idr_find(&fpriv->bo_list_handles, id);
|
||||||
if (result)
|
|
||||||
mutex_lock(&result->lock);
|
if (result) {
|
||||||
mutex_unlock(&fpriv->bo_list_lock);
|
if (kref_get_unless_zero(&result->refcount))
|
||||||
|
mutex_lock(&result->lock);
|
||||||
|
else
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
return result;
|
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)
|
void amdgpu_bo_list_put(struct amdgpu_bo_list *list)
|
||||||
{
|
{
|
||||||
mutex_unlock(&list->lock);
|
mutex_unlock(&list->lock);
|
||||||
|
kref_put(&list->refcount, amdgpu_bo_list_release_rcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_bo_list_free(struct amdgpu_bo_list *list)
|
void amdgpu_bo_list_free(struct amdgpu_bo_list *list)
|
||||||
|
|
Loading…
Reference in New Issue