summaryrefslogtreecommitdiff
path: root/linux/shrinker.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-11-12 16:48:07 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2017-11-12 16:48:07 -0500
commit3347339bbd1e39fbb254d3d80f10b2e3b4d19e6e (patch)
treee10659d3772db2d238bcf0f814348e850107ea8b /linux/shrinker.c
parente9afb70d261e420e540b0c79a718e76b03b1182b (diff)
Simple stupid memory reclaim code
Diffstat (limited to 'linux/shrinker.c')
-rw-r--r--linux/shrinker.c87
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);
+}