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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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 | |||