Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 166014
b: refs/heads/master
c: 3116971
h: refs/heads/master
v: v3
  • Loading branch information
Chris Wilson authored and Jesse Barnes committed Sep 17, 2009
1 parent bb44d43 commit 01daed8
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 725ceaa08a98fcdb1ec1c302700e33b629aece4b
refs/heads/master: 31169714fc928aed4e945b959dca2bedd259b9c9
3 changes: 3 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ static int __init i915_init(void)
{
driver.num_ioctls = i915_max_ioctl;

i915_gem_shrinker_init();

/*
* If CONFIG_DRM_I915_KMS is set, default to KMS unless
* explicitly disabled with the module pararmeter.
Expand All @@ -388,6 +390,7 @@ static int __init i915_init(void)

static void __exit i915_exit(void)
{
i915_gem_shrinker_exit();
drm_exit(&driver);
}

Expand Down
12 changes: 12 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ typedef struct drm_i915_private {
struct io_mapping *gtt_mapping;
int gtt_mtrr;

/**
* Membership on list of all loaded devices, used to evict
* inactive buffers under memory pressure.
*
* Modifications should only be done whilst holding the
* shrink_list_lock spinlock.
*/
struct list_head shrink_list;

/**
* List of objects currently involved in rendering from the
* ringbuffer.
Expand Down Expand Up @@ -741,6 +750,9 @@ int i915_gem_object_get_pages(struct drm_gem_object *obj);
void i915_gem_object_put_pages(struct drm_gem_object *obj);
void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);

void i915_gem_shrinker_init(void);
void i915_gem_shrinker_exit(void);

/* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
Expand Down
144 changes: 144 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *o
struct drm_i915_gem_pwrite *args,
struct drm_file *file_priv);

static LIST_HEAD(shrink_list);
static DEFINE_SPINLOCK(shrink_list_lock);

int i915_gem_do_init(struct drm_device *dev, unsigned long start,
unsigned long end)
{
Expand Down Expand Up @@ -4265,6 +4268,10 @@ i915_gem_load(struct drm_device *dev)
i915_gem_retire_work_handler);
dev_priv->mm.next_gem_seqno = 1;

spin_lock(&shrink_list_lock);
list_add(&dev_priv->mm.shrink_list, &shrink_list);
spin_unlock(&shrink_list_lock);

/* Old X drivers will take 0-2 for front, back, depth buffers */
dev_priv->fence_reg_start = 3;

Expand Down Expand Up @@ -4482,3 +4489,140 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv)
list_del_init(i915_file_priv->mm.request_list.next);
mutex_unlock(&dev->struct_mutex);
}

/* Immediately discard the backing storage */
static void
i915_gem_object_truncate(struct drm_gem_object *obj)
{
struct inode *inode;

inode = obj->filp->f_path.dentry->d_inode;

mutex_lock(&inode->i_mutex);
truncate_inode_pages(inode->i_mapping, 0);
mutex_unlock(&inode->i_mutex);
}

static inline int
i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
{
return !obj_priv->dirty;
}

static int
i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
{
drm_i915_private_t *dev_priv, *next_dev;
struct drm_i915_gem_object *obj_priv, *next_obj;
int cnt = 0;
int would_deadlock = 1;

/* "fast-path" to count number of available objects */
if (nr_to_scan == 0) {
spin_lock(&shrink_list_lock);
list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) {
struct drm_device *dev = dev_priv->dev;

if (mutex_trylock(&dev->struct_mutex)) {
list_for_each_entry(obj_priv,
&dev_priv->mm.inactive_list,
list)
cnt++;
mutex_unlock(&dev->struct_mutex);
}
}
spin_unlock(&shrink_list_lock);

return (cnt / 100) * sysctl_vfs_cache_pressure;
}

spin_lock(&shrink_list_lock);

/* first scan for clean buffers */
list_for_each_entry_safe(dev_priv, next_dev,
&shrink_list, mm.shrink_list) {
struct drm_device *dev = dev_priv->dev;

if (! mutex_trylock(&dev->struct_mutex))
continue;

spin_unlock(&shrink_list_lock);

i915_gem_retire_requests(dev);

list_for_each_entry_safe(obj_priv, next_obj,
&dev_priv->mm.inactive_list,
list) {
if (i915_gem_object_is_purgeable(obj_priv)) {
struct drm_gem_object *obj = obj_priv->obj;
i915_gem_object_unbind(obj);
i915_gem_object_truncate(obj);

if (--nr_to_scan <= 0)
break;
}
}

spin_lock(&shrink_list_lock);
mutex_unlock(&dev->struct_mutex);

if (nr_to_scan <= 0)
break;
}

/* second pass, evict/count anything still on the inactive list */
list_for_each_entry_safe(dev_priv, next_dev,
&shrink_list, mm.shrink_list) {
struct drm_device *dev = dev_priv->dev;

if (! mutex_trylock(&dev->struct_mutex))
continue;

spin_unlock(&shrink_list_lock);

list_for_each_entry_safe(obj_priv, next_obj,
&dev_priv->mm.inactive_list,
list) {
if (nr_to_scan > 0) {
struct drm_gem_object *obj = obj_priv->obj;
i915_gem_object_unbind(obj);
if (i915_gem_object_is_purgeable(obj_priv))
i915_gem_object_truncate(obj);

nr_to_scan--;
} else
cnt++;
}

spin_lock(&shrink_list_lock);
mutex_unlock(&dev->struct_mutex);

would_deadlock = 0;
}

spin_unlock(&shrink_list_lock);

if (would_deadlock)
return -1;
else if (cnt > 0)
return (cnt / 100) * sysctl_vfs_cache_pressure;
else
return 0;
}

static struct shrinker shrinker = {
.shrink = i915_gem_shrink,
.seeks = DEFAULT_SEEKS,
};

__init void
i915_gem_shrinker_init(void)
{
register_shrinker(&shrinker);
}

__exit void
i915_gem_shrinker_exit(void)
{
unregister_shrinker(&shrinker);
}

0 comments on commit 01daed8

Please sign in to comment.