diff options
| author | San Mehat <san@android.com> | 2008-12-20 03:48:38 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 16:52:45 -0500 |
| commit | 08b88cc7844bf984e2e474134c207bb2c46c007d (patch) | |
| tree | 7733a71c85aabea72410253ca8f37a9c5d076f95 | |
| parent | 1fa7026ff026012f3a819b49d44dd6267997f379 (diff) | |
Staging: android: add lowmemorykiller driver
From: San Mehat <san@android.com>
Cc: Brian Swetland <swetland@google.com>
Cc: Robert Love <rlove@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/staging/android/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/staging/android/Makefile | 1 | ||||
| -rw-r--r-- | drivers/staging/android/lowmemorykiller.c | 119 |
3 files changed, 126 insertions, 0 deletions
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 502c283eedcc..934f6f2019b3 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig | |||
| @@ -77,4 +77,10 @@ config ANDROID_TIMED_GPIO | |||
| 77 | depends on GENERIC_GPIO | 77 | depends on GENERIC_GPIO |
| 78 | default n | 78 | default n |
| 79 | 79 | ||
| 80 | config ANDROID_LOW_MEMORY_KILLER | ||
| 81 | bool "Android Low Memory Killer" | ||
| 82 | default N | ||
| 83 | ---help--- | ||
| 84 | Register processes to be killed when memory is low | ||
| 85 | |||
| 80 | endmenu | 86 | endmenu |
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 7ea6fbe92f4b..95209d6273a1 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile | |||
| @@ -2,3 +2,4 @@ obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o | |||
| 2 | obj-$(CONFIG_ANDROID_LOGGER) += logger.o | 2 | obj-$(CONFIG_ANDROID_LOGGER) += logger.o |
| 3 | obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o | 3 | obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o |
| 4 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o | 4 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o |
| 5 | obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o | ||
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c new file mode 100644 index 000000000000..3715d56ca96b --- /dev/null +++ b/drivers/staging/android/lowmemorykiller.c | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | /* drivers/misc/lowmemorykiller.c | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007-2008 Google, Inc. | ||
| 4 | * | ||
| 5 | * This software is licensed under the terms of the GNU General Public | ||
| 6 | * License version 2, as published by the Free Software Foundation, and | ||
| 7 | * may be copied, distributed, and modified under those terms. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/mm.h> | ||
| 19 | #include <linux/oom.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | |||
| 22 | static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask); | ||
| 23 | |||
| 24 | static struct shrinker lowmem_shrinker = { | ||
| 25 | .shrink = lowmem_shrink, | ||
| 26 | .seeks = DEFAULT_SEEKS * 16 | ||
| 27 | }; | ||
| 28 | static uint32_t lowmem_debug_level = 2; | ||
| 29 | static int lowmem_adj[6] = { | ||
| 30 | 0, | ||
| 31 | 1, | ||
| 32 | 6, | ||
| 33 | 12, | ||
| 34 | }; | ||
| 35 | static int lowmem_adj_size = 4; | ||
| 36 | static size_t lowmem_minfree[6] = { | ||
| 37 | 3*512, // 6MB | ||
| 38 | 2*1024, // 8MB | ||
| 39 | 4*1024, // 16MB | ||
| 40 | 16*1024, // 64MB | ||
| 41 | }; | ||
| 42 | static int lowmem_minfree_size = 4; | ||
| 43 | |||
| 44 | #define lowmem_print(level, x...) do { if(lowmem_debug_level >= (level)) printk(x); } while(0) | ||
| 45 | |||
| 46 | module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); | ||
| 47 | module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size, S_IRUGO | S_IWUSR); | ||
| 48 | module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, S_IRUGO | S_IWUSR); | ||
| 49 | module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); | ||
| 50 | |||
| 51 | static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) | ||
| 52 | { | ||
| 53 | struct task_struct *p; | ||
| 54 | struct task_struct *selected = NULL; | ||
| 55 | int rem = 0; | ||
| 56 | int tasksize; | ||
| 57 | int i; | ||
| 58 | int min_adj = OOM_ADJUST_MAX + 1; | ||
| 59 | int selected_tasksize = 0; | ||
| 60 | int array_size = ARRAY_SIZE(lowmem_adj); | ||
| 61 | int other_free = global_page_state(NR_FREE_PAGES) + global_page_state(NR_FILE_PAGES); | ||
| 62 | if(lowmem_adj_size < array_size) | ||
| 63 | array_size = lowmem_adj_size; | ||
| 64 | if(lowmem_minfree_size < array_size) | ||
| 65 | array_size = lowmem_minfree_size; | ||
| 66 | for(i = 0; i < array_size; i++) { | ||
| 67 | if(other_free < lowmem_minfree[i]) { | ||
| 68 | min_adj = lowmem_adj[i]; | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | if(nr_to_scan > 0) | ||
| 73 | lowmem_print(3, "lowmem_shrink %d, %x, ofree %d, ma %d\n", nr_to_scan, gfp_mask, other_free, min_adj); | ||
| 74 | read_lock(&tasklist_lock); | ||
| 75 | for_each_process(p) { | ||
| 76 | if(p->oomkilladj >= 0 && p->mm) { | ||
| 77 | tasksize = get_mm_rss(p->mm); | ||
| 78 | if(nr_to_scan > 0 && tasksize > 0 && p->oomkilladj >= min_adj) { | ||
| 79 | if(selected == NULL || | ||
| 80 | p->oomkilladj > selected->oomkilladj || | ||
| 81 | (p->oomkilladj == selected->oomkilladj && | ||
| 82 | tasksize > selected_tasksize)) { | ||
| 83 | selected = p; | ||
| 84 | selected_tasksize = tasksize; | ||
| 85 | lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n", | ||
| 86 | p->pid, p->comm, p->oomkilladj, tasksize); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | rem += tasksize; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | if(selected != NULL) { | ||
| 93 | lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n", | ||
| 94 | selected->pid, selected->comm, | ||
| 95 | selected->oomkilladj, selected_tasksize); | ||
| 96 | force_sig(SIGKILL, selected); | ||
| 97 | rem -= selected_tasksize; | ||
| 98 | } | ||
| 99 | lowmem_print(4, "lowmem_shrink %d, %x, return %d\n", nr_to_scan, gfp_mask, rem); | ||
| 100 | read_unlock(&tasklist_lock); | ||
| 101 | return rem; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int __init lowmem_init(void) | ||
| 105 | { | ||
| 106 | register_shrinker(&lowmem_shrinker); | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void __exit lowmem_exit(void) | ||
| 111 | { | ||
| 112 | unregister_shrinker(&lowmem_shrinker); | ||
| 113 | } | ||
| 114 | |||
| 115 | module_init(lowmem_init); | ||
| 116 | module_exit(lowmem_exit); | ||
| 117 | |||
| 118 | MODULE_LICENSE("GPL"); | ||
| 119 | |||
