diff options
author | Rob Clark <robdclark@chromium.org> | 2021-03-31 18:27:19 -0700 |
---|---|---|
committer | Rob Clark <robdclark@chromium.org> | 2021-04-07 11:05:42 -0700 |
commit | cc8a4d5a1bd84a37ff1827e2902c459e9b2d4e25 (patch) | |
tree | 7de47a94da6e7aee4f9d19cf7be12351b926035a /drivers/gpu/drm/msm/msm_gem.h | |
parent | bc90dc33c46c8b98843f33f40446b7fdb0ba8f1c (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.h')
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.h | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 7a9107cf1818..13aabfe92dac 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -51,17 +51,23 @@ struct msm_gem_object { uint8_t madv; /** + * Is object on inactive_dontneed list (ie. counted in priv->shrinkable_count)? + */ + bool dontneed : 1; + + /** * count of active vmap'ing */ uint8_t vmap_count; - /* And object is either: - * inactive - on priv->inactive_list + /** + * An object is either: + * inactive - on priv->inactive_dontneed/willneed/purged depending + * on status * active - on one one of the gpu's active_list.. well, at * least for now we don't have (I don't think) hw sync between * 2d and 3d one devices which have both, meaning we need to * block on submit if a bo is already on other ring - * */ struct list_head mm_list; @@ -186,10 +192,16 @@ static inline bool is_active(struct msm_gem_object *msm_obj) return msm_obj->active_count; } +/* imported/exported objects are not purgable: */ +static inline bool is_unpurgable(struct msm_gem_object *msm_obj) +{ + return msm_obj->base.dma_buf && msm_obj->base.import_attach; +} + static inline bool is_purgeable(struct msm_gem_object *msm_obj) { return (msm_obj->madv == MSM_MADV_DONTNEED) && msm_obj->sgt && - !msm_obj->base.dma_buf && !msm_obj->base.import_attach; + !is_unpurgable(msm_obj); } static inline bool is_vunmapable(struct msm_gem_object *msm_obj) @@ -198,6 +210,39 @@ static inline bool is_vunmapable(struct msm_gem_object *msm_obj) return (msm_obj->vmap_count == 0) && msm_obj->vaddr; } +static inline void mark_purgable(struct msm_gem_object *msm_obj) +{ + struct msm_drm_private *priv = msm_obj->base.dev->dev_private; + + WARN_ON(!mutex_is_locked(&priv->mm_lock)); + + if (is_unpurgable(msm_obj)) + return; + + if (WARN_ON(msm_obj->dontneed)) + return; + + priv->shrinkable_count += msm_obj->base.size >> PAGE_SHIFT; + msm_obj->dontneed = true; +} + +static inline void mark_unpurgable(struct msm_gem_object *msm_obj) +{ + struct msm_drm_private *priv = msm_obj->base.dev->dev_private; + + WARN_ON(!mutex_is_locked(&priv->mm_lock)); + + if (is_unpurgable(msm_obj)) + return; + + if (WARN_ON(!msm_obj->dontneed)) + return; + + priv->shrinkable_count -= msm_obj->base.size >> PAGE_SHIFT; + WARN_ON(priv->shrinkable_count < 0); + msm_obj->dontneed = false; +} + void msm_gem_purge(struct drm_gem_object *obj); void msm_gem_vunmap(struct drm_gem_object *obj); |