diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2017-11-12 16:48:07 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-11-12 16:48:07 -0500 |
commit | 3347339bbd1e39fbb254d3d80f10b2e3b4d19e6e (patch) | |
tree | e10659d3772db2d238bcf0f814348e850107ea8b /linux/shrinker.c | |
parent | e9afb70d261e420e540b0c79a718e76b03b1182b (diff) |
Simple stupid memory reclaim code
Diffstat (limited to 'linux/shrinker.c')
-rw-r--r-- | linux/shrinker.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/linux/shrinker.c b/linux/shrinker.c new file mode 100644 index 00000000..b8fc2464 --- /dev/null +++ b/linux/shrinker.c @@ -0,0 +1,87 @@ + +#include <stdio.h> + +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/shrinker.h> + +#include "tools-util.h" + +static LIST_HEAD(shrinker_list); +static DEFINE_MUTEX(shrinker_lock); + +int register_shrinker(struct shrinker *shrinker) +{ + mutex_lock(&shrinker_lock); + list_add_tail(&shrinker->list, &shrinker_list); + mutex_unlock(&shrinker_lock); + return 0; +} + +void unregister_shrinker(struct shrinker *shrinker) +{ + mutex_lock(&shrinker_lock); + list_del(&shrinker->list); + mutex_unlock(&shrinker_lock); +} + +struct meminfo { + u64 total; + u64 available; + +}; + +static u64 parse_meminfo_line(const char *line) +{ + u64 v; + + if (sscanf(line, " %llu kB", &v) < 1) + die("sscanf error"); + return v << 10; +} + +static struct meminfo read_meminfo(void) +{ + struct meminfo ret = { 0 }; + size_t len, n = 0; + char *line = NULL; + const char *v; + FILE *f; + + f = fopen("/proc/meminfo", "r"); + if (!f) + die("error opening /proc/meminfo: %m"); + + while ((len = getline(&line, &n, f)) != -1) { + if ((v = strcmp_prefix(line, "MemTotal:"))) + ret.total = parse_meminfo_line(v); + + if ((v = strcmp_prefix(line, "MemAvailable:"))) + ret.available = parse_meminfo_line(v); + } + + fclose(f); + free(line); + + return ret; +} + +void run_shrinkers(void) +{ + struct shrinker *shrinker; + struct meminfo info = read_meminfo(); + s64 want_shrink = (info.total >> 2) - info.available; + + if (want_shrink <= 0) + return; + + mutex_lock(&shrinker_lock); + list_for_each_entry(shrinker, &shrinker_list, list) { + struct shrink_control sc = { + .nr_to_scan = want_shrink >> PAGE_SHIFT + }; + + shrinker->scan_objects(shrinker, &sc); + } + mutex_unlock(&shrinker_lock); +} |