aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-11-21 08:04:04 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-21 11:47:14 -0500
commit5774506f157a91400c587b85d1ce4de56f0d32f6 (patch)
tree167ec5514586d474a34f9fa4185fcc56a4034ae1 /drivers
parent8742267af4043606869f5b8dadbef635405543c3 (diff)
drm/i915: Borrow our struct_mutex for the direct reclaim
If we have hit oom whilst holding our struct_mutex, then currently we cannot reap our own GPU buffers which likely pin most of memory, making an outright OOM more likely. So if we are running in direct reclaim and already hold the mutex, attempt to free buffers knowing that the original function can not continue until we return. v2: Add a note explaining that the mutex may be stolen due to pre-emption, and that is bad. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 71b5129947ba..b0016bb65631 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4342,6 +4342,19 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file)
4342 spin_unlock(&file_priv->mm.lock); 4342 spin_unlock(&file_priv->mm.lock);
4343} 4343}
4344 4344
4345static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
4346{
4347 if (!mutex_is_locked(mutex))
4348 return false;
4349
4350#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
4351 return mutex->owner == task;
4352#else
4353 /* Since UP may be pre-empted, we cannot assume that we own the lock */
4354 return false;
4355#endif
4356}
4357
4345static int 4358static int
4346i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) 4359i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
4347{ 4360{
@@ -4352,10 +4365,15 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
4352 struct drm_device *dev = dev_priv->dev; 4365 struct drm_device *dev = dev_priv->dev;
4353 struct drm_i915_gem_object *obj; 4366 struct drm_i915_gem_object *obj;
4354 int nr_to_scan = sc->nr_to_scan; 4367 int nr_to_scan = sc->nr_to_scan;
4368 bool unlock = true;
4355 int cnt; 4369 int cnt;
4356 4370
4357 if (!mutex_trylock(&dev->struct_mutex)) 4371 if (!mutex_trylock(&dev->struct_mutex)) {
4358 return 0; 4372 if (!mutex_is_locked_by(&dev->struct_mutex, current))
4373 return 0;
4374
4375 unlock = false;
4376 }
4359 4377
4360 if (nr_to_scan) { 4378 if (nr_to_scan) {
4361 nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); 4379 nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
@@ -4371,6 +4389,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
4371 if (obj->pin_count == 0 && obj->pages_pin_count == 0) 4389 if (obj->pin_count == 0 && obj->pages_pin_count == 0)
4372 cnt += obj->base.size >> PAGE_SHIFT; 4390 cnt += obj->base.size >> PAGE_SHIFT;
4373 4391
4374 mutex_unlock(&dev->struct_mutex); 4392 if (unlock)
4393 mutex_unlock(&dev->struct_mutex);
4375 return cnt; 4394 return cnt;
4376} 4395}