cc'ing dri-devel.
From e314a1a1583e585d062dfc30c8aad8bf5380510b Mon Sep 17 00:00:00 2001
From: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp Date: Mon, 19 May 2014 18:43:21 +0900 Subject: [PATCH] gpu/drm/ttm: Use mutex_lock_killable() for shrinker functions.
I can observe that RHEL7 environment stalls with 100% CPU usage when a certain type of memory pressure is given. While the shrinker functions are called by shrink_slab() before the OOM killer is triggered, the stall lasts for many minutes.
I added debug printk() and observed that many threads are blocked for more than 10 seconds at ttm_dma_pool_shrink_count()/ttm_dma_pool_shrink_scan() functions. Since the kswapd can call these functions later, the current thread can return from these functions as soon as chosen by the OOM killer.
This patch changes "mutex_lock();" to "if (mutex_lock_killable()) return ...;" so that any threads can promptly give up. (By the way, as far as I tested, changing to "if (!mutex_trylock()) return ...;" likely shortens the duration of stall. Maybe we don't need to wait for mutex if someone is already calling these functions.)
Signed-off-by: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 1b79bf0..f75dab8 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -1012,7 +1012,8 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) if (list_empty(&_manager->pools)) return SHRINK_STOP;
- mutex_lock(&_manager->lock);
- if (mutex_lock_killable(&_manager->lock))
pool_offset = pool_offset % _manager->npools; list_for_each_entry(p, &_manager->pools, pools) { unsigned nr_free;return SHRINK_STOP;
@@ -1043,7 +1044,8 @@ ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc) struct device_pools *p; unsigned long count = 0;
- mutex_lock(&_manager->lock);
- if (mutex_lock_killable(&_manager->lock))
list_for_each_entry(p, &_manager->pools, pools) count += p->pool->npages_free; mutex_unlock(&_manager->lock);return 0;