staging: android: lowmemorykiller: Add config option to support oom_adj values
authorArve Hjønnevåg <arve@android.com>
Wed, 26 Sep 2012 00:37:14 +0000 (17:37 -0700)
committerJohn Stultz <john.stultz@linaro.org>
Tue, 16 Feb 2016 21:41:34 +0000 (13:41 -0800)
The conversion to use oom_score_adj instead of the deprecated oom_adj
values breaks existing user-space code. Add a config option to convert
oom_adj values written to oom_score_adj values if they appear to be
valid oom_adj values.

Change-Id: I68308125059b802ee2991feefb07e9703bc48549
Signed-off-by: Arve Hjønnevåg <arve@android.com>
drivers/staging/android/Kconfig
drivers/staging/android/lowmemorykiller.c

index 42b15126aa06bc0828405b0b6fe65b733f7eb871..6e8557fc2200f6d480e2e32eb5770c4673ce1ede 100644 (file)
@@ -38,6 +38,15 @@ config ANDROID_LOW_MEMORY_KILLER
          scripts (/init.rc), and it defines priority values with minimum free memory size
          for each priority.
 
+config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+       bool "Android Low Memory Killer: detect oom_adj values"
+       depends on ANDROID_LOW_MEMORY_KILLER
+       default y
+       ---help---
+         Detect oom_adj values written to
+         /sys/module/lowmemorykiller/parameters/adj and convert them
+         to oom_score_adj values.
+
 config SYNC
        bool "Synchronization framework"
        default n
index e679d8432810bf8bad5cdb83ab8cb9abe59df503..9c33d5d95b2c5c0263c97cfb61cdaf6448a3a4ef 100644 (file)
@@ -193,13 +193,98 @@ static int __init lowmem_init(void)
 }
 device_initcall(lowmem_init);
 
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+static short lowmem_oom_adj_to_oom_score_adj(short oom_adj)
+{
+       if (oom_adj == OOM_ADJUST_MAX)
+               return OOM_SCORE_ADJ_MAX;
+       else
+               return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+}
+
+static void lowmem_autodetect_oom_adj_values(void)
+{
+       int i;
+       short oom_adj;
+       short oom_score_adj;
+       int array_size = ARRAY_SIZE(lowmem_adj);
+
+       if (lowmem_adj_size < array_size)
+               array_size = lowmem_adj_size;
+
+       if (array_size <= 0)
+               return;
+
+       oom_adj = lowmem_adj[array_size - 1];
+       if (oom_adj > OOM_ADJUST_MAX)
+               return;
+
+       oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+       if (oom_score_adj <= OOM_ADJUST_MAX)
+               return;
+
+       lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n");
+       for (i = 0; i < array_size; i++) {
+               oom_adj = lowmem_adj[i];
+               oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+               lowmem_adj[i] = oom_score_adj;
+               lowmem_print(1, "oom_adj %d => oom_score_adj %d\n",
+                            oom_adj, oom_score_adj);
+       }
+}
+
+static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp)
+{
+       int ret;
+
+       ret = param_array_ops.set(val, kp);
+
+       /* HACK: Autodetect oom_adj values in lowmem_adj array */
+       lowmem_autodetect_oom_adj_values();
+
+       return ret;
+}
+
+static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp)
+{
+       return param_array_ops.get(buffer, kp);
+}
+
+static void lowmem_adj_array_free(void *arg)
+{
+       param_array_ops.free(arg);
+}
+
+static struct kernel_param_ops lowmem_adj_array_ops = {
+       .set = lowmem_adj_array_set,
+       .get = lowmem_adj_array_get,
+       .free = lowmem_adj_array_free,
+};
+
+static const struct kparam_array __param_arr_adj = {
+       .max = ARRAY_SIZE(lowmem_adj),
+       .num = &lowmem_adj_size,
+       .ops = &param_ops_short,
+       .elemsize = sizeof(lowmem_adj[0]),
+       .elem = lowmem_adj,
+};
+#endif
+
 /*
  * not really modular, but the easiest way to keep compat with existing
  * bootargs behaviour is to continue using module_param here.
  */
 module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+__module_param_call(MODULE_PARAM_PREFIX, adj,
+                   &lowmem_adj_array_ops,
+                   .arr = &__param_arr_adj,
+                   S_IRUGO | S_IWUSR, -1);
+__MODULE_PARM_TYPE(adj, "array of short");
+#else
 module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size,
                         S_IRUGO | S_IWUSR);
+#endif
 module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
                         S_IRUGO | S_IWUSR);
 module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);