summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_gem_shrinker.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2021-03-31 18:27:19 -0700
committerRob Clark <robdclark@chromium.org>2021-04-07 11:05:42 -0700
commitcc8a4d5a1bd84a37ff1827e2902c459e9b2d4e25 (patch)
tree7de47a94da6e7aee4f9d19cf7be12351b926035a /drivers/gpu/drm/msm/msm_gem_shrinker.c
parentbc90dc33c46c8b98843f33f40446b7fdb0ba8f1c (diff)
drm/msm: Avoid mutex in shrinker_count()
When the system is under heavy memory pressure, we can end up with lots of concurrent calls into the shrinker. Keeping a running tab on what we can shrink avoids grabbing a lock in shrinker->count(), and avoids shrinker->scan() getting called when not profitable. Also, we can keep purged objects in their own list to avoid re-traversing them to help cut down time in the critical section further. Signed-off-by: Rob Clark <robdclark@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Link: https://lore.kernel.org/r/20210401012722.527712-3-robdclark@gmail.com Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem_shrinker.c')
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c28
1 files changed, 11 insertions, 17 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 9d5248be746f..f3e948af01c5 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -14,22 +14,7 @@ msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
struct msm_drm_private *priv =
container_of(shrinker, struct msm_drm_private, shrinker);
- struct msm_gem_object *msm_obj;
- unsigned long count = 0;
-
- mutex_lock(&priv->mm_lock);
-
- list_for_each_entry(msm_obj, &priv->inactive_dontneed, mm_list) {
- if (!msm_gem_trylock(&msm_obj->base))
- continue;
- if (is_purgeable(msm_obj))
- count += msm_obj->base.size >> PAGE_SHIFT;
- msm_gem_unlock(&msm_obj->base);
- }
-
- mutex_unlock(&priv->mm_lock);
-
- return count;
+ return priv->shrinkable_count;
}
static unsigned long
@@ -45,6 +30,9 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
list_for_each_entry(msm_obj, &priv->inactive_dontneed, mm_list) {
if (freed >= sc->nr_to_scan)
break;
+ /* Use trylock, because we cannot block on a obj that
+ * might be trying to acquire mm_lock
+ */
if (!msm_gem_trylock(&msm_obj->base))
continue;
if (is_purgeable(msm_obj)) {
@@ -56,8 +44,11 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
mutex_unlock(&priv->mm_lock);
- if (freed > 0)
+ if (freed > 0) {
trace_msm_gem_purge(freed << PAGE_SHIFT);
+ } else {
+ return SHRINK_STOP;
+ }
return freed;
}
@@ -75,6 +66,9 @@ vmap_shrink(struct list_head *mm_list)
unsigned unmapped = 0;
list_for_each_entry(msm_obj, mm_list, mm_list) {
+ /* Use trylock, because we cannot block on a obj that
+ * might be trying to acquire mm_lock
+ */
if (!msm_gem_trylock(&msm_obj->base))
continue;
if (is_vunmapable(msm_obj)) {