/drivers/staging/android/lowmemorykiller.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 213 lines · 155 code · 21 blank · 37 comment · 22 complexity · 52cdec966beb500fa20ec7cb470c20ff MD5 · raw file

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