1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/mm.h>
19#include <linux/sched.h>
20#include <linux/swap.h>
21#include <linux/timex.h>
22#include <linux/jiffies.h>
23#include <linux/module.h>
24#include <linux/notifier.h>
25
26int oom_kill_enabled = 1;
27int sysctl_panic_on_oom;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50static unsigned long badness(struct task_struct *p, unsigned long uptime)
51{
52 unsigned long points, cpu_time, run_time, s;
53
54 if (!p->mm)
55 return 0;
56
57 if (p->flags & PF_MEMDIE)
58 return 0;
59
60
61
62 points = p->mm->total_vm;
63
64
65
66
67
68
69 cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
70
71 if (uptime >= p->start_time.tv_sec)
72 run_time = (uptime - p->start_time.tv_sec) >> 10;
73 else
74 run_time = 0;
75
76 s = int_sqrt(cpu_time);
77 if (s)
78 points /= s;
79 s = int_sqrt(int_sqrt(run_time));
80 if (s)
81 points /= s;
82
83
84
85
86
87 if (task_nice(p) > 0)
88 points *= 2;
89
90
91
92
93
94 if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
95 p->uid == 0 || p->euid == 0)
96 points /= 4;
97
98
99
100
101
102
103
104 if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
105 points /= 4;
106#ifdef DEBUG
107 printk(KERN_DEBUG "OOMkill: task %d (%s) got %d points\n",
108 p->pid, p->comm, points);
109#endif
110 return points;
111}
112
113
114
115
116
117
118
119static struct task_struct * select_bad_process(void)
120{
121 unsigned long maxpoints = 0;
122 struct task_struct *g, *p;
123 struct task_struct *chosen = NULL;
124 struct timespec uptime;
125
126 do_posix_clock_monotonic_gettime(&uptime);
127 do_each_thread(g, p)
128 if (p->pid) {
129 unsigned long points = badness(p, uptime.tv_sec);
130 if (points > maxpoints) {
131 chosen = p;
132 maxpoints = points;
133 }
134 if (p->flags & PF_SWAPOFF)
135 return p;
136 }
137 while_each_thread(g, p);
138 return chosen;
139}
140
141
142
143
144
145
146static void __oom_kill_task(task_t *p)
147{
148 task_lock(p);
149 if (!p->mm || p->mm == &init_mm) {
150 WARN_ON(1);
151 printk(KERN_WARNING "tried to kill an mm-less task!\n");
152 task_unlock(p);
153 return;
154 }
155 task_unlock(p);
156 printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
157
158
159
160
161
162
163 p->time_slice = HZ;
164 p->flags |= PF_MEMALLOC | PF_MEMDIE;
165
166
167 if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) {
168 force_sig(SIGTERM, p);
169 } else {
170 force_sig(SIGKILL, p);
171 }
172}
173
174static struct mm_struct *oom_kill_task(task_t *p)
175{
176 struct mm_struct *mm = get_task_mm(p);
177 if (!mm || mm == &init_mm)
178 return NULL;
179 __oom_kill_task(p);
180 return mm;
181}
182
183
184
185
186
187
188
189
190
191
192static void oom_kill(void)
193{
194 struct mm_struct *mm;
195 struct task_struct *g, *p, *q;
196
197
198 show_mem();
199
200 if (!oom_kill_enabled) {
201 printk(KERN_INFO "Would have oom-killed but /proc/sys/vm/oom-kill is disabled\n");
202 return;
203 }
204
205 if (sysctl_panic_on_oom)
206 panic("out of memory. panic_on_oom is selected\n");
207
208 read_lock(&tasklist_lock);
209retry:
210 p = select_bad_process();
211
212
213 if (!p) {
214 show_free_areas();
215 panic("Out of memory and no killable processes...\n");
216 }
217
218 mm = oom_kill_task(p);
219 if (!mm)
220 goto retry;
221
222
223
224
225 do_each_thread(g, q)
226 if (q->mm == mm && q->tgid != p->tgid)
227 __oom_kill_task(q);
228 while_each_thread(g, q);
229 if (!p->mm)
230 printk(KERN_INFO "Fixed up OOM kill of mm-less task\n");
231 read_unlock(&tasklist_lock);
232 mmput(mm);
233
234
235
236
237
238
239 yield();
240 return;
241}
242
243static struct notifier_block *oom_notify_list;
244
245int register_oom_notifier(struct notifier_block *nb)
246{
247 return notifier_chain_register(&oom_notify_list, nb);
248}
249EXPORT_SYMBOL_GPL(register_oom_notifier);
250
251int unregister_oom_notifier(struct notifier_block *nb)
252{
253 return notifier_chain_unregister(&oom_notify_list, nb);
254}
255EXPORT_SYMBOL_GPL(unregister_oom_notifier);
256
257
258
259
260void out_of_memory(int gfp_mask)
261{
262
263
264
265
266 static spinlock_t oom_lock = SPIN_LOCK_UNLOCKED;
267 static unsigned long first, last, count, lastkill;
268 unsigned long now, since;
269 unsigned long freed = 0;
270
271 notifier_call_chain(&oom_notify_list, 0, &freed);
272 if (freed > 0)
273
274 return;
275
276 spin_lock(&oom_lock);
277 now = jiffies;
278 since = now - last;
279 last = now;
280
281
282
283
284
285 if (since > 5*HZ)
286 goto reset;
287
288
289
290
291
292 since = now - first;
293 if (since < HZ)
294 goto out_unlock;
295
296
297
298
299
300 if (++count < 10)
301 goto out_unlock;
302
303
304
305
306
307
308 since = now - lastkill;
309 if (since < HZ*5)
310 goto out_unlock;
311
312
313
314
315 lastkill = now;
316
317 printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
318
319
320 spin_unlock(&oom_lock);
321 oom_kill();
322 spin_lock(&oom_lock);
323
324reset:
325
326
327
328
329 if (time_after(now, first))
330 first = now;
331 count = 0;
332
333out_unlock:
334 spin_unlock(&oom_lock);
335}
336