blob: 5a210ababea99916b0b0f6f6f7e188f2e4b39b5e [file] [log] [blame]
Todd Poynor3948f802013-07-09 19:35:14 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "lowmemorykiller"
18
19#include <errno.h>
Robert Beneac47f2992017-08-21 15:18:31 -070020#include <inttypes.h>
Suren Baghdasaryan4311d1e2018-03-20 16:03:29 -070021#include <pwd.h>
Mark Salyzyncfd5b082016-10-17 14:28:00 -070022#include <sched.h>
Todd Poynor3948f802013-07-09 19:35:14 -070023#include <signal.h>
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -070024#include <stdbool.h>
Todd Poynor3948f802013-07-09 19:35:14 -070025#include <stdlib.h>
26#include <string.h>
Mark Salyzyne6ed68b2014-04-30 13:36:35 -070027#include <sys/cdefs.h>
Todd Poynor3948f802013-07-09 19:35:14 -070028#include <sys/epoll.h>
29#include <sys/eventfd.h>
Colin Crossb28ff912014-07-11 17:15:44 -070030#include <sys/mman.h>
Todd Poynor3948f802013-07-09 19:35:14 -070031#include <sys/socket.h>
32#include <sys/types.h>
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -080033#include <sys/sysinfo.h>
Mark Salyzyne6ed68b2014-04-30 13:36:35 -070034#include <unistd.h>
35
Robert Benea58891d52017-07-31 17:15:20 -070036#include <cutils/properties.h>
Todd Poynor3948f802013-07-09 19:35:14 -070037#include <cutils/sockets.h>
Suren Baghdasaryan0f100512018-01-24 16:51:41 -080038#include <lmkd.h>
Mark Salyzyn30f991f2017-01-10 13:19:54 -080039#include <log/log.h>
Mark Salyzyne6ed68b2014-04-30 13:36:35 -070040
Rajeev Kumar70450032018-01-31 17:54:56 -080041#ifdef LMKD_LOG_STATS
Rajeev Kumar70450032018-01-31 17:54:56 -080042#include <statslog.h>
43#endif
44
Suren Baghdasaryanc7135592018-01-04 10:43:58 -080045/*
46 * Define LMKD_TRACE_KILLS to record lmkd kills in kernel traces
47 * to profile and correlate with OOM kills
48 */
49#ifdef LMKD_TRACE_KILLS
50
51#define ATRACE_TAG ATRACE_TAG_ALWAYS
52#include <cutils/trace.h>
53
54#define TRACE_KILL_START(pid) ATRACE_INT(__FUNCTION__, pid);
55#define TRACE_KILL_END() ATRACE_INT(__FUNCTION__, 0);
56
57#else /* LMKD_TRACE_KILLS */
58
Daniel Colascione347f6b42018-02-12 11:24:47 -080059#define TRACE_KILL_START(pid) ((void)(pid))
60#define TRACE_KILL_END() ((void)0)
Suren Baghdasaryanc7135592018-01-04 10:43:58 -080061
62#endif /* LMKD_TRACE_KILLS */
63
Mark Salyzyne6ed68b2014-04-30 13:36:35 -070064#ifndef __unused
65#define __unused __attribute__((__unused__))
66#endif
Todd Poynor3948f802013-07-09 19:35:14 -070067
68#define MEMCG_SYSFS_PATH "/dev/memcg/"
Robert Beneac47f2992017-08-21 15:18:31 -070069#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes"
70#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
Rajeev Kumar70450032018-01-31 17:54:56 -080071
Todd Poynor3948f802013-07-09 19:35:14 -070072#define LINE_MAX 128
73
74#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
75#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
76
77#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
Robert Benea673e2762017-06-01 16:32:31 -070078#define EIGHT_MEGA (1 << 23)
Todd Poynor3948f802013-07-09 19:35:14 -070079
Suren Baghdasaryan4311d1e2018-03-20 16:03:29 -070080/* Defined as ProcessList.SYSTEM_ADJ in ProcessList.java */
81#define SYSTEM_ADJ (-900)
82
Greg Kaiser6bbd5212018-03-23 14:16:12 -070083#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
84#define STRINGIFY_INTERNAL(x) #x
85
Todd Poynor3948f802013-07-09 19:35:14 -070086/* default to old in-kernel interface if no memory pressure events */
87static int use_inkernel_interface = 1;
Robert Benea164baeb2017-09-11 16:53:28 -070088static bool has_inkernel_module;
Todd Poynor3948f802013-07-09 19:35:14 -070089
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -080090/* memory pressure levels */
91enum vmpressure_level {
92 VMPRESS_LEVEL_LOW = 0,
93 VMPRESS_LEVEL_MEDIUM,
94 VMPRESS_LEVEL_CRITICAL,
95 VMPRESS_LEVEL_COUNT
96};
Todd Poynor3948f802013-07-09 19:35:14 -070097
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -080098static const char *level_name[] = {
99 "low",
100 "medium",
101 "critical"
102};
103
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800104struct mem_size {
105 int free_mem;
106 int free_swap;
107};
108
109struct {
110 int min_free; /* recorded but not used yet */
111 int max_free;
112} low_pressure_mem = { -1, -1 };
113
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800114static int level_oomadj[VMPRESS_LEVEL_COUNT];
Suren Baghdasaryane82e15c2018-01-04 09:16:21 -0800115static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
Robert Beneac47f2992017-08-21 15:18:31 -0700116static bool debug_process_killing;
117static bool enable_pressure_upgrade;
118static int64_t upgrade_pressure;
Robert Benea6e8e7102017-09-13 15:20:30 -0700119static int64_t downgrade_pressure;
Robert Benea164baeb2017-09-11 16:53:28 -0700120static bool is_go_device;
Suren Baghdasaryan662492a2017-12-08 13:17:06 -0800121static bool kill_heaviest_task;
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -0800122static unsigned long kill_timeout_ms;
Robert Benea58891d52017-07-31 17:15:20 -0700123
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800124/* data required to handle events */
125struct event_handler_info {
126 int data;
127 void (*handler)(int data, uint32_t events);
128};
Todd Poynor3948f802013-07-09 19:35:14 -0700129
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800130/* data required to handle socket events */
131struct sock_event_handler_info {
132 int sock;
133 struct event_handler_info handler_info;
134};
135
136/* max supported number of data connections */
137#define MAX_DATA_CONN 2
138
139/* socket event handler data */
140static struct sock_event_handler_info ctrl_sock;
141static struct sock_event_handler_info data_sock[MAX_DATA_CONN];
142
143/* vmpressure event handler data */
144static struct event_handler_info vmpressure_hinfo[VMPRESS_LEVEL_COUNT];
145
146/* 3 memory pressure levels, 1 ctrl listen socket, 2 ctrl data socket */
147#define MAX_EPOLL_EVENTS (1 + MAX_DATA_CONN + VMPRESS_LEVEL_COUNT)
Todd Poynor3948f802013-07-09 19:35:14 -0700148static int epollfd;
149static int maxevents;
150
Chong Zhang0a4acdf2015-10-14 16:19:53 -0700151/* OOM score values used by both kernel and framework */
Todd Poynor16b60992013-09-16 19:26:47 -0700152#define OOM_SCORE_ADJ_MIN (-1000)
153#define OOM_SCORE_ADJ_MAX 1000
154
Todd Poynor3948f802013-07-09 19:35:14 -0700155static int lowmem_adj[MAX_TARGETS];
156static int lowmem_minfree[MAX_TARGETS];
157static int lowmem_targets_size;
158
159struct sysmeminfo {
160 int nr_free_pages;
161 int nr_file_pages;
162 int nr_shmem;
163 int totalreserve_pages;
164};
165
166struct adjslot_list {
167 struct adjslot_list *next;
168 struct adjslot_list *prev;
169};
170
171struct proc {
172 struct adjslot_list asl;
173 int pid;
Colin Crossfbb78c62014-06-13 14:52:43 -0700174 uid_t uid;
Todd Poynor3948f802013-07-09 19:35:14 -0700175 int oomadj;
176 struct proc *pidhash_next;
177};
178
Rajeev Kumar70450032018-01-31 17:54:56 -0800179#ifdef LMKD_LOG_STATS
Rajeev Kumar70450032018-01-31 17:54:56 -0800180static bool enable_stats_log;
181static android_log_context log_ctx;
182#endif
183
Todd Poynor3948f802013-07-09 19:35:14 -0700184#define PIDHASH_SZ 1024
185static struct proc *pidhash[PIDHASH_SZ];
186#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
187
Chih-Hung Hsiehdaa13ea2016-05-19 16:02:22 -0700188#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
Chong Zhang0a4acdf2015-10-14 16:19:53 -0700189static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
Todd Poynor3948f802013-07-09 19:35:14 -0700190
Todd Poynor3948f802013-07-09 19:35:14 -0700191/* PAGE_SIZE / 1024 */
192static long page_k;
193
Colin Crossce85d952014-07-11 17:53:27 -0700194static ssize_t read_all(int fd, char *buf, size_t max_len)
195{
196 ssize_t ret = 0;
197
198 while (max_len > 0) {
199 ssize_t r = read(fd, buf, max_len);
200 if (r == 0) {
201 break;
202 }
203 if (r == -1) {
204 return -1;
205 }
206 ret += r;
207 buf += r;
208 max_len -= r;
209 }
210
211 return ret;
212}
213
Todd Poynor3948f802013-07-09 19:35:14 -0700214static struct proc *pid_lookup(int pid) {
215 struct proc *procp;
216
217 for (procp = pidhash[pid_hashfn(pid)]; procp && procp->pid != pid;
218 procp = procp->pidhash_next)
219 ;
220
221 return procp;
222}
223
224static void adjslot_insert(struct adjslot_list *head, struct adjslot_list *new)
225{
226 struct adjslot_list *next = head->next;
227 new->prev = head;
228 new->next = next;
229 next->prev = new;
230 head->next = new;
231}
232
233static void adjslot_remove(struct adjslot_list *old)
234{
235 struct adjslot_list *prev = old->prev;
236 struct adjslot_list *next = old->next;
237 next->prev = prev;
238 prev->next = next;
239}
240
241static struct adjslot_list *adjslot_tail(struct adjslot_list *head) {
242 struct adjslot_list *asl = head->prev;
243
244 return asl == head ? NULL : asl;
245}
246
247static void proc_slot(struct proc *procp) {
248 int adjslot = ADJTOSLOT(procp->oomadj);
249
250 adjslot_insert(&procadjslot_list[adjslot], &procp->asl);
251}
252
253static void proc_unslot(struct proc *procp) {
254 adjslot_remove(&procp->asl);
255}
256
257static void proc_insert(struct proc *procp) {
258 int hval = pid_hashfn(procp->pid);
259
260 procp->pidhash_next = pidhash[hval];
261 pidhash[hval] = procp;
262 proc_slot(procp);
263}
264
265static int pid_remove(int pid) {
266 int hval = pid_hashfn(pid);
267 struct proc *procp;
268 struct proc *prevp;
269
270 for (procp = pidhash[hval], prevp = NULL; procp && procp->pid != pid;
271 procp = procp->pidhash_next)
272 prevp = procp;
273
274 if (!procp)
275 return -1;
276
277 if (!prevp)
278 pidhash[hval] = procp->pidhash_next;
279 else
280 prevp->pidhash_next = procp->pidhash_next;
281
282 proc_unslot(procp);
283 free(procp);
284 return 0;
285}
286
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700287/*
288 * Write a string to a file.
289 * Returns false if the file does not exist.
290 */
291static bool writefilestring(const char *path, const char *s,
292 bool err_if_missing) {
Nick Kralevichc68c8862015-12-18 20:52:37 -0800293 int fd = open(path, O_WRONLY | O_CLOEXEC);
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700294 ssize_t len = strlen(s);
295 ssize_t ret;
Todd Poynor3948f802013-07-09 19:35:14 -0700296
297 if (fd < 0) {
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700298 if (err_if_missing) {
299 ALOGE("Error opening %s; errno=%d", path, errno);
300 }
301 return false;
Todd Poynor3948f802013-07-09 19:35:14 -0700302 }
303
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700304 ret = TEMP_FAILURE_RETRY(write(fd, s, len));
Todd Poynor3948f802013-07-09 19:35:14 -0700305 if (ret < 0) {
306 ALOGE("Error writing %s; errno=%d", path, errno);
307 } else if (ret < len) {
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700308 ALOGE("Short write on %s; length=%zd", path, ret);
Todd Poynor3948f802013-07-09 19:35:14 -0700309 }
310
311 close(fd);
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700312 return true;
Todd Poynor3948f802013-07-09 19:35:14 -0700313}
314
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800315static void cmd_procprio(LMKD_CTRL_PACKET packet) {
Todd Poynor3948f802013-07-09 19:35:14 -0700316 struct proc *procp;
317 char path[80];
318 char val[20];
Robert Benea673e2762017-06-01 16:32:31 -0700319 int soft_limit_mult;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800320 struct lmk_procprio params;
Suren Baghdasaryan4311d1e2018-03-20 16:03:29 -0700321 bool is_system_server;
322 struct passwd *pwdrec;
Todd Poynor3948f802013-07-09 19:35:14 -0700323
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800324 lmkd_pack_get_procprio(packet, &params);
325
326 if (params.oomadj < OOM_SCORE_ADJ_MIN ||
327 params.oomadj > OOM_SCORE_ADJ_MAX) {
328 ALOGE("Invalid PROCPRIO oomadj argument %d", params.oomadj);
Todd Poynor3948f802013-07-09 19:35:14 -0700329 return;
330 }
331
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800332 snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
333 snprintf(val, sizeof(val), "%d", params.oomadj);
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700334 if (!writefilestring(path, val, false)) {
335 ALOGW("Failed to open %s; errno=%d: process %d might have been killed",
336 path, errno, params.pid);
337 /* If this file does not exist the process is dead. */
338 return;
339 }
Todd Poynor3948f802013-07-09 19:35:14 -0700340
341 if (use_inkernel_interface)
342 return;
343
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800344 if (params.oomadj >= 900) {
Robert Benea673e2762017-06-01 16:32:31 -0700345 soft_limit_mult = 0;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800346 } else if (params.oomadj >= 800) {
Robert Benea673e2762017-06-01 16:32:31 -0700347 soft_limit_mult = 0;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800348 } else if (params.oomadj >= 700) {
Robert Benea673e2762017-06-01 16:32:31 -0700349 soft_limit_mult = 0;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800350 } else if (params.oomadj >= 600) {
Robert Beneacaeaa652017-08-11 16:03:20 -0700351 // Launcher should be perceptible, don't kill it.
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800352 params.oomadj = 200;
Robert Beneacaeaa652017-08-11 16:03:20 -0700353 soft_limit_mult = 1;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800354 } else if (params.oomadj >= 500) {
Robert Benea673e2762017-06-01 16:32:31 -0700355 soft_limit_mult = 0;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800356 } else if (params.oomadj >= 400) {
Robert Benea673e2762017-06-01 16:32:31 -0700357 soft_limit_mult = 0;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800358 } else if (params.oomadj >= 300) {
Robert Benea673e2762017-06-01 16:32:31 -0700359 soft_limit_mult = 1;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800360 } else if (params.oomadj >= 200) {
Robert Benea673e2762017-06-01 16:32:31 -0700361 soft_limit_mult = 2;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800362 } else if (params.oomadj >= 100) {
Robert Benea673e2762017-06-01 16:32:31 -0700363 soft_limit_mult = 10;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800364 } else if (params.oomadj >= 0) {
Robert Benea673e2762017-06-01 16:32:31 -0700365 soft_limit_mult = 20;
366 } else {
367 // Persistent processes will have a large
368 // soft limit 512MB.
369 soft_limit_mult = 64;
370 }
371
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800372 snprintf(path, sizeof(path),
373 "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
374 params.uid, params.pid);
Robert Benea673e2762017-06-01 16:32:31 -0700375 snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
Suren Baghdasaryan4311d1e2018-03-20 16:03:29 -0700376
377 /*
378 * system_server process has no memcg under /dev/memcg/apps but should be
379 * registered with lmkd. This is the best way so far to identify it.
380 */
381 is_system_server = (params.oomadj == SYSTEM_ADJ &&
382 (pwdrec = getpwnam("system")) != NULL &&
383 params.uid == pwdrec->pw_uid);
384 writefilestring(path, val, !is_system_server);
Robert Benea673e2762017-06-01 16:32:31 -0700385
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800386 procp = pid_lookup(params.pid);
Todd Poynor3948f802013-07-09 19:35:14 -0700387 if (!procp) {
388 procp = malloc(sizeof(struct proc));
389 if (!procp) {
390 // Oh, the irony. May need to rebuild our state.
391 return;
392 }
393
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800394 procp->pid = params.pid;
395 procp->uid = params.uid;
396 procp->oomadj = params.oomadj;
Todd Poynor3948f802013-07-09 19:35:14 -0700397 proc_insert(procp);
398 } else {
399 proc_unslot(procp);
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800400 procp->oomadj = params.oomadj;
Todd Poynor3948f802013-07-09 19:35:14 -0700401 proc_slot(procp);
402 }
403}
404
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800405static void cmd_procremove(LMKD_CTRL_PACKET packet) {
406 struct lmk_procremove params;
407
Todd Poynor3948f802013-07-09 19:35:14 -0700408 if (use_inkernel_interface)
409 return;
410
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800411 lmkd_pack_get_procremove(packet, &params);
412 pid_remove(params.pid);
Todd Poynor3948f802013-07-09 19:35:14 -0700413}
414
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800415static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
Todd Poynor3948f802013-07-09 19:35:14 -0700416 int i;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800417 struct lmk_target target;
Todd Poynor3948f802013-07-09 19:35:14 -0700418
419 if (ntargets > (int)ARRAY_SIZE(lowmem_adj))
420 return;
421
422 for (i = 0; i < ntargets; i++) {
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800423 lmkd_pack_get_target(packet, i, &target);
424 lowmem_minfree[i] = target.minfree;
425 lowmem_adj[i] = target.oom_adj_score;
Todd Poynor3948f802013-07-09 19:35:14 -0700426 }
427
428 lowmem_targets_size = ntargets;
429
Robert Benea164baeb2017-09-11 16:53:28 -0700430 if (has_inkernel_module) {
Todd Poynor3948f802013-07-09 19:35:14 -0700431 char minfreestr[128];
432 char killpriostr[128];
433
434 minfreestr[0] = '\0';
435 killpriostr[0] = '\0';
436
437 for (i = 0; i < lowmem_targets_size; i++) {
438 char val[40];
439
440 if (i) {
441 strlcat(minfreestr, ",", sizeof(minfreestr));
442 strlcat(killpriostr, ",", sizeof(killpriostr));
443 }
444
Robert Benea164baeb2017-09-11 16:53:28 -0700445 snprintf(val, sizeof(val), "%d", use_inkernel_interface ? lowmem_minfree[i] : 0);
Todd Poynor3948f802013-07-09 19:35:14 -0700446 strlcat(minfreestr, val, sizeof(minfreestr));
Robert Benea164baeb2017-09-11 16:53:28 -0700447 snprintf(val, sizeof(val), "%d", use_inkernel_interface ? lowmem_adj[i] : 0);
Todd Poynor3948f802013-07-09 19:35:14 -0700448 strlcat(killpriostr, val, sizeof(killpriostr));
449 }
450
Suren Baghdasaryan1ffa2462018-03-20 13:53:17 -0700451 writefilestring(INKERNEL_MINFREE_PATH, minfreestr, true);
452 writefilestring(INKERNEL_ADJ_PATH, killpriostr, true);
Todd Poynor3948f802013-07-09 19:35:14 -0700453 }
454}
455
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800456static void ctrl_data_close(int dsock_idx) {
457 struct epoll_event epev;
458
459 ALOGI("closing lmkd data connection");
460 if (epoll_ctl(epollfd, EPOLL_CTL_DEL, data_sock[dsock_idx].sock, &epev) == -1) {
461 // Log a warning and keep going
462 ALOGW("epoll_ctl for data connection socket failed; errno=%d", errno);
463 }
Todd Poynor3948f802013-07-09 19:35:14 -0700464 maxevents--;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800465
466 close(data_sock[dsock_idx].sock);
467 data_sock[dsock_idx].sock = -1;
Todd Poynor3948f802013-07-09 19:35:14 -0700468}
469
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800470static int ctrl_data_read(int dsock_idx, char *buf, size_t bufsz) {
Todd Poynor3948f802013-07-09 19:35:14 -0700471 int ret = 0;
472
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800473 ret = read(data_sock[dsock_idx].sock, buf, bufsz);
Todd Poynor3948f802013-07-09 19:35:14 -0700474
475 if (ret == -1) {
476 ALOGE("control data socket read failed; errno=%d", errno);
477 } else if (ret == 0) {
478 ALOGE("Got EOF on control data socket");
479 ret = -1;
480 }
481
482 return ret;
483}
484
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800485static void ctrl_command_handler(int dsock_idx) {
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800486 LMKD_CTRL_PACKET packet;
Todd Poynor3948f802013-07-09 19:35:14 -0700487 int len;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800488 enum lmk_cmd cmd;
Todd Poynor3948f802013-07-09 19:35:14 -0700489 int nargs;
490 int targets;
491
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800492 len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
Todd Poynor3948f802013-07-09 19:35:14 -0700493 if (len <= 0)
494 return;
495
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800496 if (len < (int)sizeof(int)) {
497 ALOGE("Wrong control socket read length len=%d", len);
498 return;
499 }
500
501 cmd = lmkd_pack_get_cmd(packet);
Todd Poynor3948f802013-07-09 19:35:14 -0700502 nargs = len / sizeof(int) - 1;
503 if (nargs < 0)
504 goto wronglen;
505
Todd Poynor3948f802013-07-09 19:35:14 -0700506 switch(cmd) {
507 case LMK_TARGET:
508 targets = nargs / 2;
509 if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj))
510 goto wronglen;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800511 cmd_target(targets, packet);
Todd Poynor3948f802013-07-09 19:35:14 -0700512 break;
513 case LMK_PROCPRIO:
Colin Crossfbb78c62014-06-13 14:52:43 -0700514 if (nargs != 3)
Todd Poynor3948f802013-07-09 19:35:14 -0700515 goto wronglen;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800516 cmd_procprio(packet);
Todd Poynor3948f802013-07-09 19:35:14 -0700517 break;
518 case LMK_PROCREMOVE:
519 if (nargs != 1)
520 goto wronglen;
Suren Baghdasaryan0f100512018-01-24 16:51:41 -0800521 cmd_procremove(packet);
Todd Poynor3948f802013-07-09 19:35:14 -0700522 break;
523 default:
524 ALOGE("Received unknown command code %d", cmd);
525 return;
526 }
527
528 return;
529
530wronglen:
531 ALOGE("Wrong control socket read length cmd=%d len=%d", cmd, len);
532}
533
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800534static void ctrl_data_handler(int data, uint32_t events) {
535 if (events & EPOLLIN) {
536 ctrl_command_handler(data);
Todd Poynor3948f802013-07-09 19:35:14 -0700537 }
538}
539
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800540static int get_free_dsock() {
541 for (int i = 0; i < MAX_DATA_CONN; i++) {
542 if (data_sock[i].sock < 0) {
543 return i;
544 }
545 }
546 return -1;
547}
Todd Poynor3948f802013-07-09 19:35:14 -0700548
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800549static void ctrl_connect_handler(int data __unused, uint32_t events __unused) {
550 struct epoll_event epev;
551 int free_dscock_idx = get_free_dsock();
552
553 if (free_dscock_idx < 0) {
554 /*
555 * Number of data connections exceeded max supported. This should not
556 * happen but if it does we drop all existing connections and accept
557 * the new one. This prevents inactive connections from monopolizing
558 * data socket and if we drop ActivityManager connection it will
559 * immediately reconnect.
560 */
561 for (int i = 0; i < MAX_DATA_CONN; i++) {
562 ctrl_data_close(i);
563 }
564 free_dscock_idx = 0;
Todd Poynor3948f802013-07-09 19:35:14 -0700565 }
566
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800567 data_sock[free_dscock_idx].sock = accept(ctrl_sock.sock, NULL, NULL);
568 if (data_sock[free_dscock_idx].sock < 0) {
Todd Poynor3948f802013-07-09 19:35:14 -0700569 ALOGE("lmkd control socket accept failed; errno=%d", errno);
570 return;
571 }
572
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800573 ALOGI("lmkd data connection established");
574 /* use data to store data connection idx */
575 data_sock[free_dscock_idx].handler_info.data = free_dscock_idx;
576 data_sock[free_dscock_idx].handler_info.handler = ctrl_data_handler;
Todd Poynor3948f802013-07-09 19:35:14 -0700577 epev.events = EPOLLIN;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800578 epev.data.ptr = (void *)&(data_sock[free_dscock_idx].handler_info);
579 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, data_sock[free_dscock_idx].sock, &epev) == -1) {
Todd Poynor3948f802013-07-09 19:35:14 -0700580 ALOGE("epoll_ctl for data connection socket failed; errno=%d", errno);
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800581 ctrl_data_close(free_dscock_idx);
Todd Poynor3948f802013-07-09 19:35:14 -0700582 return;
583 }
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800584 maxevents++;
Todd Poynor3948f802013-07-09 19:35:14 -0700585}
586
Rajeev Kumar70450032018-01-31 17:54:56 -0800587#ifdef LMKD_LOG_STATS
588static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
Greg Kaiser6bbd5212018-03-23 14:16:12 -0700589 char key[LINE_MAX + 1];
Rajeev Kumar70450032018-01-31 17:54:56 -0800590 int64_t value;
591
Greg Kaiser6bbd5212018-03-23 14:16:12 -0700592 sscanf(line, "%" STRINGIFY(LINE_MAX) "s %" SCNd64 "", key, &value);
Rajeev Kumar70450032018-01-31 17:54:56 -0800593
594 if (strcmp(key, "total_") < 0) {
595 return;
596 }
597
598 if (!strcmp(key, "total_pgfault"))
599 mem_st->pgfault = value;
600 else if (!strcmp(key, "total_pgmajfault"))
601 mem_st->pgmajfault = value;
602 else if (!strcmp(key, "total_rss"))
603 mem_st->rss_in_bytes = value;
604 else if (!strcmp(key, "total_cache"))
605 mem_st->cache_in_bytes = value;
606 else if (!strcmp(key, "total_swap"))
607 mem_st->swap_in_bytes = value;
608}
609
610static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) {
611 FILE *fp;
612 char buf[PATH_MAX];
613
614 snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
615
616 fp = fopen(buf, "r");
617
618 if (fp == NULL) {
Rajeev Kumar92b659b2018-02-21 19:08:15 -0800619 ALOGE("%s open failed: %s", buf, strerror(errno));
Rajeev Kumar70450032018-01-31 17:54:56 -0800620 return -1;
621 }
622
623 while (fgets(buf, PAGE_SIZE, fp) != NULL ) {
624 memory_stat_parse_line(buf, mem_st);
625 }
626 fclose(fp);
627
628 return 0;
629}
630#endif
631
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800632static int get_free_memory(struct mem_size *ms) {
633 struct sysinfo si;
634
635 if (sysinfo(&si) < 0)
636 return -1;
637
638 ms->free_mem = (int)(si.freeram * si.mem_unit / PAGE_SIZE);
639 ms->free_swap = (int)(si.freeswap * si.mem_unit / PAGE_SIZE);
640
641 return 0;
642}
643
Todd Poynor3948f802013-07-09 19:35:14 -0700644static int proc_get_size(int pid) {
645 char path[PATH_MAX];
646 char line[LINE_MAX];
Colin Crossce85d952014-07-11 17:53:27 -0700647 int fd;
Todd Poynor3948f802013-07-09 19:35:14 -0700648 int rss = 0;
649 int total;
Colin Crossce85d952014-07-11 17:53:27 -0700650 ssize_t ret;
Todd Poynor3948f802013-07-09 19:35:14 -0700651
652 snprintf(path, PATH_MAX, "/proc/%d/statm", pid);
Nick Kralevichc68c8862015-12-18 20:52:37 -0800653 fd = open(path, O_RDONLY | O_CLOEXEC);
Colin Crossce85d952014-07-11 17:53:27 -0700654 if (fd == -1)
Todd Poynor3948f802013-07-09 19:35:14 -0700655 return -1;
Colin Crossce85d952014-07-11 17:53:27 -0700656
657 ret = read_all(fd, line, sizeof(line) - 1);
658 if (ret < 0) {
659 close(fd);
Todd Poynor3948f802013-07-09 19:35:14 -0700660 return -1;
661 }
662
663 sscanf(line, "%d %d ", &total, &rss);
Colin Crossce85d952014-07-11 17:53:27 -0700664 close(fd);
Todd Poynor3948f802013-07-09 19:35:14 -0700665 return rss;
666}
667
668static char *proc_get_name(int pid) {
669 char path[PATH_MAX];
670 static char line[LINE_MAX];
Colin Crossce85d952014-07-11 17:53:27 -0700671 int fd;
Todd Poynor3948f802013-07-09 19:35:14 -0700672 char *cp;
Colin Crossce85d952014-07-11 17:53:27 -0700673 ssize_t ret;
Todd Poynor3948f802013-07-09 19:35:14 -0700674
675 snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid);
Nick Kralevichc68c8862015-12-18 20:52:37 -0800676 fd = open(path, O_RDONLY | O_CLOEXEC);
Colin Crossce85d952014-07-11 17:53:27 -0700677 if (fd == -1)
Todd Poynor3948f802013-07-09 19:35:14 -0700678 return NULL;
Colin Crossce85d952014-07-11 17:53:27 -0700679 ret = read_all(fd, line, sizeof(line) - 1);
680 close(fd);
681 if (ret < 0) {
Todd Poynor3948f802013-07-09 19:35:14 -0700682 return NULL;
683 }
684
685 cp = strchr(line, ' ');
686 if (cp)
687 *cp = '\0';
688
689 return line;
690}
691
692static struct proc *proc_adj_lru(int oomadj) {
693 return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]);
694}
695
Suren Baghdasaryan662492a2017-12-08 13:17:06 -0800696static struct proc *proc_get_heaviest(int oomadj) {
697 struct adjslot_list *head = &procadjslot_list[ADJTOSLOT(oomadj)];
698 struct adjslot_list *curr = head->next;
699 struct proc *maxprocp = NULL;
700 int maxsize = 0;
701 while (curr != head) {
702 int pid = ((struct proc *)curr)->pid;
703 int tasksize = proc_get_size(pid);
704 if (tasksize <= 0) {
705 struct adjslot_list *next = curr->next;
706 pid_remove(pid);
707 curr = next;
708 } else {
709 if (tasksize > maxsize) {
710 maxsize = tasksize;
711 maxprocp = (struct proc *)curr;
712 }
713 curr = curr->next;
714 }
715 }
716 return maxprocp;
717}
718
Colin Cross16b09462014-07-14 12:39:56 -0700719/* Kill one process specified by procp. Returns the size of the process killed */
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800720static int kill_one_process(struct proc* procp, int min_score_adj,
721 enum vmpressure_level level) {
Colin Cross16b09462014-07-14 12:39:56 -0700722 int pid = procp->pid;
723 uid_t uid = procp->uid;
724 char *taskname;
725 int tasksize;
726 int r;
727
Rajeev Kumar70450032018-01-31 17:54:56 -0800728#ifdef LMKD_LOG_STATS
Rajeev Kumar92b659b2018-02-21 19:08:15 -0800729 struct memory_stat mem_st = {};
Rajeev Kumar70450032018-01-31 17:54:56 -0800730 int memory_stat_parse_result = -1;
731#endif
732
Colin Cross16b09462014-07-14 12:39:56 -0700733 taskname = proc_get_name(pid);
734 if (!taskname) {
735 pid_remove(pid);
736 return -1;
737 }
738
739 tasksize = proc_get_size(pid);
740 if (tasksize <= 0) {
741 pid_remove(pid);
742 return -1;
743 }
744
Rajeev Kumar70450032018-01-31 17:54:56 -0800745#ifdef LMKD_LOG_STATS
746 if (enable_stats_log) {
747 memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
748 }
749#endif
750
Suren Baghdasaryanc7135592018-01-04 10:43:58 -0800751 TRACE_KILL_START(pid);
752
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800753 r = kill(pid, SIGKILL);
Robert Beneacaeaa652017-08-11 16:03:20 -0700754 ALOGI(
755 "Killing '%s' (%d), uid %d, adj %d\n"
Suren Baghdasaryand07a94f2018-03-20 16:25:54 -0700756 " to free %ldkB because system is under %s memory pressure (min_oom_adj=%d)\n",
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800757 taskname, pid, uid, procp->oomadj, tasksize * page_k,
758 level_name[level], min_score_adj);
Colin Cross16b09462014-07-14 12:39:56 -0700759 pid_remove(pid);
760
Suren Baghdasaryanc7135592018-01-04 10:43:58 -0800761 TRACE_KILL_END();
762
Colin Cross16b09462014-07-14 12:39:56 -0700763 if (r) {
Mark Salyzyn919f5382018-02-04 15:27:23 -0800764 ALOGE("kill(%d): errno=%d", pid, errno);
Colin Cross16b09462014-07-14 12:39:56 -0700765 return -1;
Rajeev Kumar70450032018-01-31 17:54:56 -0800766 } else {
767#ifdef LMKD_LOG_STATS
768 if (memory_stat_parse_result == 0) {
769 stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
770 procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
771 mem_st.cache_in_bytes, mem_st.swap_in_bytes);
772 }
773#endif
774 return tasksize;
Colin Cross16b09462014-07-14 12:39:56 -0700775 }
Mark Salyzyn919f5382018-02-04 15:27:23 -0800776
777 return tasksize;
Colin Cross16b09462014-07-14 12:39:56 -0700778}
779
780/*
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800781 * Find processes to kill to free required number of pages.
782 * If pages_to_free is set to 0 only one process will be killed.
783 * Returns the size of the killed processes.
Colin Cross16b09462014-07-14 12:39:56 -0700784 */
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800785static int find_and_kill_processes(enum vmpressure_level level,
786 int pages_to_free) {
Colin Cross16b09462014-07-14 12:39:56 -0700787 int i;
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800788 int killed_size;
789 int pages_freed = 0;
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800790 int min_score_adj = level_oomadj[level];
Colin Cross16b09462014-07-14 12:39:56 -0700791
Rajeev Kumar70450032018-01-31 17:54:56 -0800792#ifdef LMKD_LOG_STATS
793 if (enable_stats_log) {
794 stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED, LMK_STATE_CHANGE_START);
795 }
796#endif
797
Chong Zhang0a4acdf2015-10-14 16:19:53 -0700798 for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
Colin Cross16b09462014-07-14 12:39:56 -0700799 struct proc *procp;
800
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800801 while (true) {
802 if (is_go_device)
803 procp = proc_adj_lru(i);
804 else
805 procp = proc_get_heaviest(i);
Colin Cross16b09462014-07-14 12:39:56 -0700806
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800807 if (!procp)
808 break;
809
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800810 killed_size = kill_one_process(procp, min_score_adj, level);
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800811 if (killed_size >= 0) {
812 pages_freed += killed_size;
813 if (pages_freed >= pages_to_free) {
Rajeev Kumar70450032018-01-31 17:54:56 -0800814
815#ifdef LMKD_LOG_STATS
816 if (enable_stats_log) {
817 stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED,
818 LMK_STATE_CHANGE_STOP);
819 }
820#endif
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800821 return pages_freed;
822 }
Colin Cross16b09462014-07-14 12:39:56 -0700823 }
824 }
825 }
826
Rajeev Kumar70450032018-01-31 17:54:56 -0800827#ifdef LMKD_LOG_STATS
828 if (enable_stats_log) {
829 stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED, LMK_STATE_CHANGE_STOP);
830 }
831#endif
832
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800833 return pages_freed;
Colin Cross16b09462014-07-14 12:39:56 -0700834}
835
Robert Beneac47f2992017-08-21 15:18:31 -0700836static int64_t get_memory_usage(const char* path) {
837 int ret;
838 int64_t mem_usage;
839 char buf[32];
840 int fd = open(path, O_RDONLY | O_CLOEXEC);
841 if (fd == -1) {
842 ALOGE("%s open: errno=%d", path, errno);
843 return -1;
844 }
845
846 ret = read_all(fd, buf, sizeof(buf) - 1);
847 close(fd);
848 if (ret < 0) {
849 ALOGE("%s error: errno=%d", path, errno);
850 return -1;
851 }
852 sscanf(buf, "%" SCNd64, &mem_usage);
853 if (mem_usage == 0) {
854 ALOGE("No memory!");
855 return -1;
856 }
857 return mem_usage;
858}
859
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800860void record_low_pressure_levels(struct mem_size *free_mem) {
861 if (low_pressure_mem.min_free == -1 ||
862 low_pressure_mem.min_free > free_mem->free_mem) {
863 if (debug_process_killing) {
864 ALOGI("Low pressure min memory update from %d to %d",
865 low_pressure_mem.min_free, free_mem->free_mem);
866 }
867 low_pressure_mem.min_free = free_mem->free_mem;
868 }
869 /*
870 * Free memory at low vmpressure events occasionally gets spikes,
871 * possibly a stale low vmpressure event with memory already
872 * freed up (no memory pressure should have been reported).
873 * Ignore large jumps in max_free that would mess up our stats.
874 */
875 if (low_pressure_mem.max_free == -1 ||
876 (low_pressure_mem.max_free < free_mem->free_mem &&
877 free_mem->free_mem - low_pressure_mem.max_free < low_pressure_mem.max_free * 0.1)) {
878 if (debug_process_killing) {
879 ALOGI("Low pressure max memory update from %d to %d",
880 low_pressure_mem.max_free, free_mem->free_mem);
881 }
882 low_pressure_mem.max_free = free_mem->free_mem;
883 }
884}
885
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800886enum vmpressure_level upgrade_level(enum vmpressure_level level) {
887 return (enum vmpressure_level)((level < VMPRESS_LEVEL_CRITICAL) ?
888 level + 1 : level);
889}
890
891enum vmpressure_level downgrade_level(enum vmpressure_level level) {
892 return (enum vmpressure_level)((level > VMPRESS_LEVEL_LOW) ?
893 level - 1 : level);
894}
895
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -0800896static inline unsigned long get_time_diff_ms(struct timeval *from,
897 struct timeval *to) {
898 return (to->tv_sec - from->tv_sec) * 1000 +
899 (to->tv_usec - from->tv_usec) / 1000;
900}
901
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800902static void mp_event_common(int data, uint32_t events __unused) {
Todd Poynor3948f802013-07-09 19:35:14 -0700903 int ret;
904 unsigned long long evcount;
Robert Beneac47f2992017-08-21 15:18:31 -0700905 int64_t mem_usage, memsw_usage;
Robert Benea6e8e7102017-09-13 15:20:30 -0700906 int64_t mem_pressure;
Suren Baghdasaryane82e15c2018-01-04 09:16:21 -0800907 enum vmpressure_level lvl;
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800908 struct mem_size free_mem;
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -0800909 static struct timeval last_report_tm;
910 static unsigned long skip_count = 0;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -0800911 enum vmpressure_level level = (enum vmpressure_level)data;
Todd Poynor3948f802013-07-09 19:35:14 -0700912
Suren Baghdasaryane82e15c2018-01-04 09:16:21 -0800913 /*
914 * Check all event counters from low to critical
915 * and upgrade to the highest priority one. By reading
916 * eventfd we also reset the event counters.
917 */
918 for (lvl = VMPRESS_LEVEL_LOW; lvl < VMPRESS_LEVEL_COUNT; lvl++) {
919 if (mpevfd[lvl] != -1 &&
920 read(mpevfd[lvl], &evcount, sizeof(evcount)) > 0 &&
921 evcount > 0 && lvl > level) {
922 level = lvl;
923 }
924 }
Todd Poynor3948f802013-07-09 19:35:14 -0700925
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -0800926 if (kill_timeout_ms) {
927 struct timeval curr_tm;
928 gettimeofday(&curr_tm, NULL);
929 if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) {
930 skip_count++;
931 return;
932 }
933 }
934
935 if (skip_count > 0) {
936 if (debug_process_killing) {
937 ALOGI("%lu memory pressure events were skipped after a kill!",
938 skip_count);
939 }
940 skip_count = 0;
941 }
942
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800943 if (get_free_memory(&free_mem) == 0) {
944 if (level == VMPRESS_LEVEL_LOW) {
945 record_low_pressure_levels(&free_mem);
946 }
947 } else {
948 ALOGE("Failed to get free memory!");
949 return;
950 }
951
952 if (level_oomadj[level] > OOM_SCORE_ADJ_MAX) {
953 /* Do not monitor this pressure level */
954 return;
955 }
956
Robert Benea6e8e7102017-09-13 15:20:30 -0700957 mem_usage = get_memory_usage(MEMCG_MEMORY_USAGE);
958 memsw_usage = get_memory_usage(MEMCG_MEMORYSW_USAGE);
959 if (memsw_usage < 0 || mem_usage < 0) {
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800960 goto do_kill;
Robert Benea6e8e7102017-09-13 15:20:30 -0700961 }
Robert Beneac47f2992017-08-21 15:18:31 -0700962
Robert Benea6e8e7102017-09-13 15:20:30 -0700963 // Calculate percent for swappinness.
964 mem_pressure = (mem_usage * 100) / memsw_usage;
965
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800966 if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {
Robert Benea6e8e7102017-09-13 15:20:30 -0700967 // We are swapping too much.
968 if (mem_pressure < upgrade_pressure) {
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800969 level = upgrade_level(level);
970 if (debug_process_killing) {
971 ALOGI("Event upgraded to %s", level_name[level]);
972 }
Robert Beneac47f2992017-08-21 15:18:31 -0700973 }
974 }
975
Robert Benea6e8e7102017-09-13 15:20:30 -0700976 // If the pressure is larger than downgrade_pressure lmk will not
977 // kill any process, since enough memory is available.
978 if (mem_pressure > downgrade_pressure) {
979 if (debug_process_killing) {
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800980 ALOGI("Ignore %s memory pressure", level_name[level]);
Robert Benea6e8e7102017-09-13 15:20:30 -0700981 }
982 return;
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800983 } else if (level == VMPRESS_LEVEL_CRITICAL &&
984 mem_pressure > upgrade_pressure) {
Robert Benea6e8e7102017-09-13 15:20:30 -0700985 if (debug_process_killing) {
986 ALOGI("Downgrade critical memory pressure");
987 }
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800988 // Downgrade event, since enough memory available.
989 level = downgrade_level(level);
Robert Benea6e8e7102017-09-13 15:20:30 -0700990 }
991
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -0800992do_kill:
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -0800993 if (is_go_device) {
994 /* For Go devices kill only one task */
995 if (find_and_kill_processes(level, 0) == 0) {
996 if (debug_process_killing) {
997 ALOGI("Nothing to kill");
998 }
999 }
1000 } else {
1001 /* If pressure level is less than critical and enough free swap then ignore */
1002 if (level < VMPRESS_LEVEL_CRITICAL && free_mem.free_swap > low_pressure_mem.max_free) {
1003 if (debug_process_killing) {
1004 ALOGI("Ignoring pressure since %d swap pages are available ", free_mem.free_swap);
1005 }
1006 return;
1007 }
1008
1009 /* Free up enough memory to downgrate the memory pressure to low level */
1010 if (free_mem.free_mem < low_pressure_mem.max_free) {
1011 int pages_to_free = low_pressure_mem.max_free - free_mem.free_mem;
1012 if (debug_process_killing) {
1013 ALOGI("Trying to free %d pages", pages_to_free);
1014 }
1015 int pages_freed = find_and_kill_processes(level, pages_to_free);
1016 if (pages_freed < pages_to_free) {
1017 if (debug_process_killing) {
1018 ALOGI("Unable to free enough memory (pages freed=%d)",
1019 pages_freed);
1020 }
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -08001021 } else {
1022 gettimeofday(&last_report_tm, NULL);
Suren Baghdasaryan65f54a22018-01-17 17:17:44 -08001023 }
Robert Beneacaeaa652017-08-11 16:03:20 -07001024 }
Colin Crossf8857cc2014-07-11 17:16:56 -07001025 }
Todd Poynor3948f802013-07-09 19:35:14 -07001026}
1027
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001028static bool init_mp_common(enum vmpressure_level level) {
Todd Poynor3948f802013-07-09 19:35:14 -07001029 int mpfd;
1030 int evfd;
1031 int evctlfd;
1032 char buf[256];
1033 struct epoll_event epev;
1034 int ret;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001035 int level_idx = (int)level;
1036 const char *levelstr = level_name[level_idx];
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001037
Nick Kralevichc68c8862015-12-18 20:52:37 -08001038 mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
Todd Poynor3948f802013-07-09 19:35:14 -07001039 if (mpfd < 0) {
1040 ALOGI("No kernel memory.pressure_level support (errno=%d)", errno);
1041 goto err_open_mpfd;
1042 }
1043
Nick Kralevichc68c8862015-12-18 20:52:37 -08001044 evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY | O_CLOEXEC);
Todd Poynor3948f802013-07-09 19:35:14 -07001045 if (evctlfd < 0) {
1046 ALOGI("No kernel memory cgroup event control (errno=%d)", errno);
1047 goto err_open_evctlfd;
1048 }
1049
Nick Kralevichc68c8862015-12-18 20:52:37 -08001050 evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
Todd Poynor3948f802013-07-09 19:35:14 -07001051 if (evfd < 0) {
1052 ALOGE("eventfd failed for level %s; errno=%d", levelstr, errno);
1053 goto err_eventfd;
1054 }
1055
1056 ret = snprintf(buf, sizeof(buf), "%d %d %s", evfd, mpfd, levelstr);
1057 if (ret >= (ssize_t)sizeof(buf)) {
1058 ALOGE("cgroup.event_control line overflow for level %s", levelstr);
1059 goto err;
1060 }
1061
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001062 ret = TEMP_FAILURE_RETRY(write(evctlfd, buf, strlen(buf) + 1));
Todd Poynor3948f802013-07-09 19:35:14 -07001063 if (ret == -1) {
1064 ALOGE("cgroup.event_control write failed for level %s; errno=%d",
1065 levelstr, errno);
1066 goto err;
1067 }
1068
1069 epev.events = EPOLLIN;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001070 /* use data to store event level */
1071 vmpressure_hinfo[level_idx].data = level_idx;
1072 vmpressure_hinfo[level_idx].handler = mp_event_common;
1073 epev.data.ptr = (void *)&vmpressure_hinfo[level_idx];
Todd Poynor3948f802013-07-09 19:35:14 -07001074 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, evfd, &epev);
1075 if (ret == -1) {
1076 ALOGE("epoll_ctl for level %s failed; errno=%d", levelstr, errno);
1077 goto err;
1078 }
1079 maxevents++;
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001080 mpevfd[level] = evfd;
Suren Baghdasaryan1bd2fc42018-01-04 08:54:53 -08001081 close(evctlfd);
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001082 return true;
Todd Poynor3948f802013-07-09 19:35:14 -07001083
1084err:
1085 close(evfd);
1086err_eventfd:
1087 close(evctlfd);
1088err_open_evctlfd:
1089 close(mpfd);
1090err_open_mpfd:
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001091 return false;
Robert Benea673e2762017-06-01 16:32:31 -07001092}
1093
Todd Poynor3948f802013-07-09 19:35:14 -07001094static int init(void) {
1095 struct epoll_event epev;
1096 int i;
1097 int ret;
1098
1099 page_k = sysconf(_SC_PAGESIZE);
1100 if (page_k == -1)
1101 page_k = PAGE_SIZE;
1102 page_k /= 1024;
1103
1104 epollfd = epoll_create(MAX_EPOLL_EVENTS);
1105 if (epollfd == -1) {
1106 ALOGE("epoll_create failed (errno=%d)", errno);
1107 return -1;
1108 }
1109
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001110 // mark data connections as not connected
1111 for (int i = 0; i < MAX_DATA_CONN; i++) {
1112 data_sock[i].sock = -1;
1113 }
1114
1115 ctrl_sock.sock = android_get_control_socket("lmkd");
1116 if (ctrl_sock.sock < 0) {
Todd Poynor3948f802013-07-09 19:35:14 -07001117 ALOGE("get lmkd control socket failed");
1118 return -1;
1119 }
1120
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001121 ret = listen(ctrl_sock.sock, MAX_DATA_CONN);
Todd Poynor3948f802013-07-09 19:35:14 -07001122 if (ret < 0) {
1123 ALOGE("lmkd control socket listen failed (errno=%d)", errno);
1124 return -1;
1125 }
1126
1127 epev.events = EPOLLIN;
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001128 ctrl_sock.handler_info.handler = ctrl_connect_handler;
1129 epev.data.ptr = (void *)&(ctrl_sock.handler_info);
1130 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ctrl_sock.sock, &epev) == -1) {
Todd Poynor3948f802013-07-09 19:35:14 -07001131 ALOGE("epoll_ctl for lmkd control socket failed (errno=%d)", errno);
1132 return -1;
1133 }
1134 maxevents++;
1135
Robert Benea164baeb2017-09-11 16:53:28 -07001136 has_inkernel_module = !access(INKERNEL_MINFREE_PATH, W_OK);
Suren Baghdasaryan979591b2018-01-18 17:27:30 -08001137 use_inkernel_interface = has_inkernel_module;
Todd Poynor3948f802013-07-09 19:35:14 -07001138
1139 if (use_inkernel_interface) {
1140 ALOGI("Using in-kernel low memory killer interface");
1141 } else {
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001142 if (!init_mp_common(VMPRESS_LEVEL_LOW) ||
1143 !init_mp_common(VMPRESS_LEVEL_MEDIUM) ||
1144 !init_mp_common(VMPRESS_LEVEL_CRITICAL)) {
Todd Poynor3948f802013-07-09 19:35:14 -07001145 ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer");
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001146 return -1;
1147 }
Todd Poynor3948f802013-07-09 19:35:14 -07001148 }
1149
Chong Zhang0a4acdf2015-10-14 16:19:53 -07001150 for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
Todd Poynor3948f802013-07-09 19:35:14 -07001151 procadjslot_list[i].next = &procadjslot_list[i];
1152 procadjslot_list[i].prev = &procadjslot_list[i];
1153 }
1154
1155 return 0;
1156}
1157
1158static void mainloop(void) {
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001159 struct event_handler_info* handler_info;
1160 struct epoll_event *evt;
1161
Todd Poynor3948f802013-07-09 19:35:14 -07001162 while (1) {
1163 struct epoll_event events[maxevents];
1164 int nevents;
1165 int i;
1166
Todd Poynor3948f802013-07-09 19:35:14 -07001167 nevents = epoll_wait(epollfd, events, maxevents, -1);
1168
1169 if (nevents == -1) {
1170 if (errno == EINTR)
1171 continue;
1172 ALOGE("epoll_wait failed (errno=%d)", errno);
1173 continue;
1174 }
1175
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001176 /*
1177 * First pass to see if any data socket connections were dropped.
1178 * Dropped connection should be handled before any other events
1179 * to deallocate data connection and correctly handle cases when
1180 * connection gets dropped and reestablished in the same epoll cycle.
1181 * In such cases it's essential to handle connection closures first.
1182 */
1183 for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
1184 if ((evt->events & EPOLLHUP) && evt->data.ptr) {
1185 ALOGI("lmkd data connection dropped");
1186 handler_info = (struct event_handler_info*)evt->data.ptr;
1187 ctrl_data_close(handler_info->data);
1188 }
1189 }
1190
1191 /* Second pass to handle all other events */
1192 for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
1193 if (evt->events & EPOLLERR)
Todd Poynor3948f802013-07-09 19:35:14 -07001194 ALOGD("EPOLLERR on event #%d", i);
Suren Baghdasaryan3cfb2c82018-01-26 12:51:19 -08001195 if (evt->events & EPOLLHUP) {
1196 /* This case was handled in the first pass */
1197 continue;
1198 }
1199 if (evt->data.ptr) {
1200 handler_info = (struct event_handler_info*)evt->data.ptr;
1201 handler_info->handler(handler_info->data, evt->events);
1202 }
Todd Poynor3948f802013-07-09 19:35:14 -07001203 }
1204 }
1205}
1206
Mark Salyzyne6ed68b2014-04-30 13:36:35 -07001207int main(int argc __unused, char **argv __unused) {
Colin Cross1a0d9be2014-07-14 14:31:15 -07001208 struct sched_param param = {
1209 .sched_priority = 1,
1210 };
1211
Suren Baghdasaryan96bf3a62017-12-08 12:58:52 -08001212 /* By default disable low level vmpressure events */
1213 level_oomadj[VMPRESS_LEVEL_LOW] =
1214 property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);
1215 level_oomadj[VMPRESS_LEVEL_MEDIUM] =
1216 property_get_int32("ro.lmk.medium", 800);
1217 level_oomadj[VMPRESS_LEVEL_CRITICAL] =
1218 property_get_int32("ro.lmk.critical", 0);
Robert Beneacaeaa652017-08-11 16:03:20 -07001219 debug_process_killing = property_get_bool("ro.lmk.debug", false);
Suren Baghdasaryanad2fd912017-12-08 13:08:41 -08001220
1221 /* By default disable upgrade/downgrade logic */
1222 enable_pressure_upgrade =
1223 property_get_bool("ro.lmk.critical_upgrade", false);
1224 upgrade_pressure =
1225 (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 100);
1226 downgrade_pressure =
1227 (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 100);
Suren Baghdasaryan662492a2017-12-08 13:17:06 -08001228 kill_heaviest_task =
1229 property_get_bool("ro.lmk.kill_heaviest_task", true);
Robert Benea164baeb2017-09-11 16:53:28 -07001230 is_go_device = property_get_bool("ro.config.low_ram", false);
Suren Baghdasaryancaa2dc52018-01-17 17:28:01 -08001231 kill_timeout_ms =
1232 (unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
Robert Benea58891d52017-07-31 17:15:20 -07001233
Rajeev Kumar70450032018-01-31 17:54:56 -08001234#ifdef LMKD_LOG_STATS
Rajeev Kumarfb25ddd2018-03-09 15:20:56 -08001235 statslog_init(&log_ctx, &enable_stats_log);
Rajeev Kumar70450032018-01-31 17:54:56 -08001236#endif
1237
Daniel Colascioned39adf22018-01-05 14:59:55 -08001238 // MCL_ONFAULT pins pages as they fault instead of loading
1239 // everything immediately all at once. (Which would be bad,
1240 // because as of this writing, we have a lot of mapped pages we
1241 // never use.) Old kernels will see MCL_ONFAULT and fail with
1242 // EINVAL; we ignore this failure.
1243 //
1244 // N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
1245 // pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
1246 // in pages.
1247 if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && errno != EINVAL)
Daniel Colascione4dd5d002018-01-03 12:01:02 -08001248 ALOGW("mlockall failed: errno=%d", errno);
1249
Colin Cross1a0d9be2014-07-14 14:31:15 -07001250 sched_setscheduler(0, SCHED_FIFO, &param);
Todd Poynor3948f802013-07-09 19:35:14 -07001251 if (!init())
1252 mainloop();
1253
Rajeev Kumar70450032018-01-31 17:54:56 -08001254#ifdef LMKD_LOG_STATS
Rajeev Kumarfb25ddd2018-03-09 15:20:56 -08001255 statslog_destroy(&log_ctx);
Rajeev Kumar70450032018-01-31 17:54:56 -08001256#endif
1257
Todd Poynor3948f802013-07-09 19:35:14 -07001258 ALOGI("exiting");
1259 return 0;
1260}