linux/drivers/staging/android/lowmemorykiller.c
<<
>>
Prefs
   1/* drivers/misc/lowmemorykiller.c
   2 *
   3 * The lowmemorykiller driver lets user-space specify a set of memory thresholds
   4 * where processes with a range of oom_score_adj values will get killed. Specify
   5 * the minimum oom_score_adj values in
   6 * /sys/module/lowmemorykiller/parameters/adj and the number of free pages in
   7 * /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma
   8 * separated list of numbers in ascending order.
   9 *
  10 * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
  11 * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill
  12 * processes with a oom_score_adj value of 8 or higher when the free memory
  13 * drops below 4096 pages and kill processes with a oom_score_adj value of 0 or
  14 * higher when the free memory drops below 1024 pages.
  15 *
  16 * The driver considers memory used for caches to be free, but if a large
  17 * percentage of the cached memory is locked this can be very inaccurate
  18 * and processes may not get killed until the normal oom killer is triggered.
  19 *
  20 * Copyright (C) 2007-2008 Google, Inc.
  21 *
  22 * This software is licensed under the terms of the GNU General Public
  23 * License version 2, as published by the Free Software Foundation, and
  24 * may be copied, distributed, and modified under those terms.
  25 *
  26 * This program is distributed in the hope that it will be useful,
  27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29 * GNU General Public License for more details.
  30 *
  31 */
  32
  33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  34
  35#include <linux/module.h>
  36#include <linux/kernel.h>
  37#include <linux/mm.h>
  38#include <linux/oom.h>
  39#include <linux/sched.h>
  40#include <linux/swap.h>
  41#include <linux/rcupdate.h>
  42#include <linux/profile.h>
  43#include <linux/notifier.h>
  44
  45static uint32_t lowmem_debug_level = 1;
  46static short lowmem_adj[6] = {
  47        0,
  48        1,
  49        6,
  50        12,
  51};
  52static int lowmem_adj_size = 4;
  53static int lowmem_minfree[6] = {
  54        3 * 512,        /* 6MB */
  55        2 * 1024,       /* 8MB */
  56        4 * 1024,       /* 16MB */
  57        16 * 1024,      /* 64MB */
  58};
  59static int lowmem_minfree_size = 4;
  60
  61static unsigned long lowmem_deathpending_timeout;
  62
  63#define lowmem_print(level, x...)                       \
  64        do {                                            \
  65                if (lowmem_debug_level >= (level))      \
  66                        pr_info(x);                     \
  67        } while (0)
  68
  69static unsigned long lowmem_count(struct shrinker *s,
  70                                  struct shrink_control *sc)
  71{
  72        return global_page_state(NR_ACTIVE_ANON) +
  73                global_page_state(NR_ACTIVE_FILE) +
  74                global_page_state(NR_INACTIVE_ANON) +
  75                global_page_state(NR_INACTIVE_FILE);
  76}
  77
  78static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
  79{
  80        struct task_struct *tsk;
  81        struct task_struct *selected = NULL;
  82        unsigned long rem = 0;
  83        int tasksize;
  84        int i;
  85        short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
  86        int selected_tasksize = 0;
  87        short selected_oom_score_adj;
  88        int array_size = ARRAY_SIZE(lowmem_adj);
  89        int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
  90        int other_file = global_page_state(NR_FILE_PAGES) -
  91                                                global_page_state(NR_SHMEM);
  92
  93        if (lowmem_adj_size < array_size)
  94                array_size = lowmem_adj_size;
  95        if (lowmem_minfree_size < array_size)
  96                array_size = lowmem_minfree_size;
  97        for (i = 0; i < array_size; i++) {
  98                if (other_free < lowmem_minfree[i] &&
  99                    other_file < lowmem_minfree[i]) {
 100                        min_score_adj = lowmem_adj[i];
 101                        break;
 102                }
 103        }
 104
 105        lowmem_print(3, "lowmem_scan %lu, %x, ofree %d %d, ma %hd\n",
 106                        sc->nr_to_scan, sc->gfp_mask, other_free,
 107                        other_file, min_score_adj);
 108
 109        if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
 110                lowmem_print(5, "lowmem_scan %lu, %x, return 0\n",
 111                             sc->nr_to_scan, sc->gfp_mask);
 112                return 0;
 113        }
 114
 115        selected_oom_score_adj = min_score_adj;
 116
 117        rcu_read_lock();
 118        for_each_process(tsk) {
 119                struct task_struct *p;
 120                short oom_score_adj;
 121
 122                if (tsk->flags & PF_KTHREAD)
 123                        continue;
 124
 125                p = find_lock_task_mm(tsk);
 126                if (!p)
 127                        continue;
 128
 129                if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
 130                    time_before_eq(jiffies, lowmem_deathpending_timeout)) {
 131                        task_unlock(p);
 132                        rcu_read_unlock();
 133                        return 0;
 134                }
 135                oom_score_adj = p->signal->oom_score_adj;
 136                if (oom_score_adj < min_score_adj) {
 137                        task_unlock(p);
 138                        continue;
 139                }
 140                tasksize = get_mm_rss(p->mm);
 141                task_unlock(p);
 142                if (tasksize <= 0)
 143                        continue;
 144                if (selected) {
 145                        if (oom_score_adj < selected_oom_score_adj)
 146                                continue;
 147                        if (oom_score_adj == selected_oom_score_adj &&
 148                            tasksize <= selected_tasksize)
 149                                continue;
 150                }
 151                selected = p;
 152                selected_tasksize = tasksize;
 153                selected_oom_score_adj = oom_score_adj;
 154                lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n",
 155                             p->pid, p->comm, oom_score_adj, tasksize);
 156        }
 157        if (selected) {
 158                lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n",
 159                             selected->pid, selected->comm,
 160                             selected_oom_score_adj, selected_tasksize);
 161                lowmem_deathpending_timeout = jiffies + HZ;
 162                send_sig(SIGKILL, selected, 0);
 163                set_tsk_thread_flag(selected, TIF_MEMDIE);
 164                rem += selected_tasksize;
 165        }
 166
 167        lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
 168                     sc->nr_to_scan, sc->gfp_mask, rem);
 169        rcu_read_unlock();
 170        return rem;
 171}
 172
 173static struct shrinker lowmem_shrinker = {
 174        .scan_objects = lowmem_scan,
 175        .count_objects = lowmem_count,
 176        .seeks = DEFAULT_SEEKS * 16
 177};
 178
 179static int __init lowmem_init(void)
 180{
 181        register_shrinker(&lowmem_shrinker);
 182        return 0;
 183}
 184
 185static void __exit lowmem_exit(void)
 186{
 187        unregister_shrinker(&lowmem_shrinker);
 188}
 189
 190module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
 191module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size,
 192                         S_IRUGO | S_IWUSR);
 193module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
 194                         S_IRUGO | S_IWUSR);
 195module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
 196
 197module_init(lowmem_init);
 198module_exit(lowmem_exit);
 199
 200MODULE_LICENSE("GPL");
 201
 202