lmkd.c revision 3948f80f2af84016013cc674140ac5066a58fb4d
1/* 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> 20#include <signal.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <time.h> 25#include <unistd.h> 26#include <arpa/inet.h> 27#include <sys/epoll.h> 28#include <sys/eventfd.h> 29#include <sys/socket.h> 30#include <sys/types.h> 31#include <cutils/log.h> 32#include <cutils/sockets.h> 33 34#define MEMCG_SYSFS_PATH "/dev/memcg/" 35#define MEMPRESSURE_WATCH_LEVEL "medium" 36#define ZONEINFO_PATH "/proc/zoneinfo" 37#define LINE_MAX 128 38 39#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree" 40#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj" 41 42#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 43 44enum lmk_cmd { 45 LMK_TARGET, 46 LMK_PROCPRIO, 47 LMK_PROCREMOVE, 48}; 49 50#define MAX_TARGETS 6 51/* 52 * longest is LMK_TARGET followed by MAX_TARGETS each minfree and minkillprio 53 * values 54 */ 55#define CTRL_PACKET_MAX (sizeof(int) * (MAX_TARGETS * 2 + 1)) 56 57/* default to old in-kernel interface if no memory pressure events */ 58static int use_inkernel_interface = 1; 59 60/* memory pressure level medium event */ 61static int mpevfd; 62 63/* control socket listen and data */ 64static int ctrl_lfd; 65static int ctrl_dfd = -1; 66static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */ 67 68/* 1 memory pressure level, 1 ctrl listen socket, 1 ctrl data socket */ 69#define MAX_EPOLL_EVENTS 3 70static int epollfd; 71static int maxevents; 72 73#define OOM_DISABLE (-17) 74/* inclusive */ 75#define OOM_ADJUST_MIN (-16) 76#define OOM_ADJUST_MAX 15 77 78static int lowmem_adj[MAX_TARGETS]; 79static int lowmem_minfree[MAX_TARGETS]; 80static int lowmem_targets_size; 81 82struct sysmeminfo { 83 int nr_free_pages; 84 int nr_file_pages; 85 int nr_shmem; 86 int totalreserve_pages; 87}; 88 89struct adjslot_list { 90 struct adjslot_list *next; 91 struct adjslot_list *prev; 92}; 93 94struct proc { 95 struct adjslot_list asl; 96 int pid; 97 int oomadj; 98 struct proc *pidhash_next; 99}; 100 101#define PIDHASH_SZ 1024 102static struct proc *pidhash[PIDHASH_SZ]; 103#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) 104 105#define ADJTOSLOT(adj) (adj + -OOM_ADJUST_MIN) 106static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_ADJUST_MAX) + 1]; 107 108/* 109 * Wait 1-2 seconds for the death report of a killed process prior to 110 * considering killing more processes. 111 */ 112#define KILL_TIMEOUT 2 113/* Time of last process kill we initiated, stop me before I kill again */ 114static time_t kill_lasttime; 115 116/* PAGE_SIZE / 1024 */ 117static long page_k; 118 119static struct proc *pid_lookup(int pid) { 120 struct proc *procp; 121 122 for (procp = pidhash[pid_hashfn(pid)]; procp && procp->pid != pid; 123 procp = procp->pidhash_next) 124 ; 125 126 return procp; 127} 128 129static void adjslot_insert(struct adjslot_list *head, struct adjslot_list *new) 130{ 131 struct adjslot_list *next = head->next; 132 new->prev = head; 133 new->next = next; 134 next->prev = new; 135 head->next = new; 136} 137 138static void adjslot_remove(struct adjslot_list *old) 139{ 140 struct adjslot_list *prev = old->prev; 141 struct adjslot_list *next = old->next; 142 next->prev = prev; 143 prev->next = next; 144} 145 146static struct adjslot_list *adjslot_tail(struct adjslot_list *head) { 147 struct adjslot_list *asl = head->prev; 148 149 return asl == head ? NULL : asl; 150} 151 152static void proc_slot(struct proc *procp) { 153 int adjslot = ADJTOSLOT(procp->oomadj); 154 155 adjslot_insert(&procadjslot_list[adjslot], &procp->asl); 156} 157 158static void proc_unslot(struct proc *procp) { 159 adjslot_remove(&procp->asl); 160} 161 162static void proc_insert(struct proc *procp) { 163 int hval = pid_hashfn(procp->pid); 164 165 procp->pidhash_next = pidhash[hval]; 166 pidhash[hval] = procp; 167 proc_slot(procp); 168} 169 170static int pid_remove(int pid) { 171 int hval = pid_hashfn(pid); 172 struct proc *procp; 173 struct proc *prevp; 174 175 for (procp = pidhash[hval], prevp = NULL; procp && procp->pid != pid; 176 procp = procp->pidhash_next) 177 prevp = procp; 178 179 if (!procp) 180 return -1; 181 182 if (!prevp) 183 pidhash[hval] = procp->pidhash_next; 184 else 185 prevp->pidhash_next = procp->pidhash_next; 186 187 proc_unslot(procp); 188 free(procp); 189 return 0; 190} 191 192static void writefilestring(char *path, char *s) { 193 int fd = open(path, O_WRONLY); 194 int len = strlen(s); 195 int ret; 196 197 if (fd < 0) { 198 ALOGE("Error opening %s; errno=%d", path, errno); 199 return; 200 } 201 202 ret = write(fd, s, len); 203 if (ret < 0) { 204 ALOGE("Error writing %s; errno=%d", path, errno); 205 } else if (ret < len) { 206 ALOGE("Short write on %s; length=%d", path, ret); 207 } 208 209 close(fd); 210} 211 212static void cmd_procprio(int pid, int oomadj) { 213 struct proc *procp; 214 char path[80]; 215 char val[20]; 216 217 if (oomadj < OOM_DISABLE || oomadj > OOM_ADJUST_MAX) { 218 ALOGE("Invalid PROCPRIO oomadj argument %d", oomadj); 219 return; 220 } 221 222 snprintf(path, sizeof(path), "/proc/%d/oom_adj", pid); 223 snprintf(val, sizeof(val), "%d", oomadj); 224 writefilestring(path, val); 225 226 if (use_inkernel_interface) 227 return; 228 229 procp = pid_lookup(pid); 230 if (!procp) { 231 procp = malloc(sizeof(struct proc)); 232 if (!procp) { 233 // Oh, the irony. May need to rebuild our state. 234 return; 235 } 236 237 procp->pid = pid; 238 procp->oomadj = oomadj; 239 proc_insert(procp); 240 } else { 241 proc_unslot(procp); 242 procp->oomadj = oomadj; 243 proc_slot(procp); 244 } 245} 246 247static void cmd_procremove(int pid) { 248 struct proc *procp; 249 250 if (use_inkernel_interface) 251 return; 252 253 pid_remove(pid); 254 kill_lasttime = 0; 255} 256 257static void cmd_target(int ntargets, int *params) { 258 int i; 259 260 if (ntargets > (int)ARRAY_SIZE(lowmem_adj)) 261 return; 262 263 for (i = 0; i < ntargets; i++) { 264 lowmem_minfree[i] = ntohl(*params++); 265 lowmem_adj[i] = ntohl(*params++); 266 } 267 268 lowmem_targets_size = ntargets; 269 270 if (use_inkernel_interface) { 271 char minfreestr[128]; 272 char killpriostr[128]; 273 274 minfreestr[0] = '\0'; 275 killpriostr[0] = '\0'; 276 277 for (i = 0; i < lowmem_targets_size; i++) { 278 char val[40]; 279 280 if (i) { 281 strlcat(minfreestr, ",", sizeof(minfreestr)); 282 strlcat(killpriostr, ",", sizeof(killpriostr)); 283 } 284 285 snprintf(val, sizeof(val), "%d", lowmem_minfree[i]); 286 strlcat(minfreestr, val, sizeof(minfreestr)); 287 snprintf(val, sizeof(val), "%d", lowmem_adj[i]); 288 strlcat(killpriostr, val, sizeof(killpriostr)); 289 } 290 291 writefilestring(INKERNEL_MINFREE_PATH, minfreestr); 292 writefilestring(INKERNEL_ADJ_PATH, killpriostr); 293 } 294} 295 296static void ctrl_data_close(void) { 297 ALOGI("Closing Activity Manager data connection"); 298 close(ctrl_dfd); 299 ctrl_dfd = -1; 300 maxevents--; 301} 302 303static int ctrl_data_read(char *buf, size_t bufsz) { 304 int ret = 0; 305 306 ret = read(ctrl_dfd, buf, bufsz); 307 308 if (ret == -1) { 309 ALOGE("control data socket read failed; errno=%d", errno); 310 } else if (ret == 0) { 311 ALOGE("Got EOF on control data socket"); 312 ret = -1; 313 } 314 315 return ret; 316} 317 318static void ctrl_command_handler(void) { 319 int ibuf[CTRL_PACKET_MAX / sizeof(int)]; 320 int len; 321 int cmd = -1; 322 int nargs; 323 int targets; 324 325 len = ctrl_data_read((char *)ibuf, CTRL_PACKET_MAX); 326 if (len <= 0) 327 return; 328 329 nargs = len / sizeof(int) - 1; 330 if (nargs < 0) 331 goto wronglen; 332 333 cmd = ntohl(ibuf[0]); 334 335 switch(cmd) { 336 case LMK_TARGET: 337 targets = nargs / 2; 338 if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj)) 339 goto wronglen; 340 cmd_target(targets, &ibuf[1]); 341 break; 342 case LMK_PROCPRIO: 343 if (nargs != 2) 344 goto wronglen; 345 cmd_procprio(ntohl(ibuf[1]), ntohl(ibuf[2])); 346 break; 347 case LMK_PROCREMOVE: 348 if (nargs != 1) 349 goto wronglen; 350 cmd_procremove(ntohl(ibuf[1])); 351 break; 352 default: 353 ALOGE("Received unknown command code %d", cmd); 354 return; 355 } 356 357 return; 358 359wronglen: 360 ALOGE("Wrong control socket read length cmd=%d len=%d", cmd, len); 361} 362 363static void ctrl_data_handler(uint32_t events) { 364 if (events & EPOLLHUP) { 365 ALOGI("ActivityManager disconnected"); 366 if (!ctrl_dfd_reopened) 367 ctrl_data_close(); 368 } else if (events & EPOLLIN) { 369 ctrl_command_handler(); 370 } 371} 372 373static void ctrl_connect_handler(uint32_t events) { 374 struct sockaddr addr; 375 socklen_t alen; 376 struct epoll_event epev; 377 378 if (ctrl_dfd >= 0) { 379 ctrl_data_close(); 380 ctrl_dfd_reopened = 1; 381 } 382 383 alen = sizeof(addr); 384 ctrl_dfd = accept(ctrl_lfd, &addr, &alen); 385 386 if (ctrl_dfd < 0) { 387 ALOGE("lmkd control socket accept failed; errno=%d", errno); 388 return; 389 } 390 391 ALOGI("ActivityManager connected"); 392 maxevents++; 393 epev.events = EPOLLIN; 394 epev.data.ptr = (void *)ctrl_data_handler; 395 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ctrl_dfd, &epev) == -1) { 396 ALOGE("epoll_ctl for data connection socket failed; errno=%d", errno); 397 ctrl_data_close(); 398 return; 399 } 400} 401 402static int zoneinfo_parse_protection(char *cp) { 403 int max = 0; 404 int zoneval; 405 406 if (*cp++ != '(') 407 return 0; 408 409 do { 410 zoneval = strtol(cp, &cp, 0); 411 if ((*cp != ',') && (*cp != ')')) 412 return 0; 413 if (zoneval > max) 414 max = zoneval; 415 } while (cp = strtok(NULL, " ")); 416 417 return max; 418} 419 420static void zoneinfo_parse_line(char *line, struct sysmeminfo *mip) { 421 char *cp = line; 422 char *ap; 423 424 cp = strtok(line, " "); 425 if (!cp) 426 return; 427 428 ap = strtok(NULL, " "); 429 if (!ap) 430 return; 431 432 if (!strcmp(cp, "nr_free_pages")) 433 mip->nr_free_pages += strtol(ap, NULL, 0); 434 else if (!strcmp(cp, "nr_file_pages")) 435 mip->nr_file_pages += strtol(ap, NULL, 0); 436 else if (!strcmp(cp, "nr_shmem")) 437 mip->nr_shmem += strtol(ap, NULL, 0); 438 else if (!strcmp(cp, "high")) 439 mip->totalreserve_pages += strtol(ap, NULL, 0); 440 else if (!strcmp(cp, "protection:")) 441 mip->totalreserve_pages += zoneinfo_parse_protection(ap); 442} 443 444static int zoneinfo_parse(struct sysmeminfo *mip) { 445 FILE *f; 446 char *cp; 447 char line[LINE_MAX]; 448 449 memset(mip, 0, sizeof(struct sysmeminfo)); 450 f = fopen(ZONEINFO_PATH, "r"); 451 if (!f) { 452 ALOGE("%s open: errno=%d", ZONEINFO_PATH, errno); 453 return -1; 454 } 455 456 while (fgets(line, LINE_MAX, f)) 457 zoneinfo_parse_line(line, mip); 458 459 fclose(f); 460 return 0; 461} 462 463static int proc_get_size(int pid) { 464 char path[PATH_MAX]; 465 char line[LINE_MAX]; 466 FILE *f; 467 int rss = 0; 468 int total; 469 470 snprintf(path, PATH_MAX, "/proc/%d/statm", pid); 471 f = fopen(path, "r"); 472 if (!f) 473 return -1; 474 if (!fgets(line, LINE_MAX, f)) { 475 fclose(f); 476 return -1; 477 } 478 479 sscanf(line, "%d %d ", &total, &rss); 480 fclose(f); 481 return rss; 482} 483 484static char *proc_get_name(int pid) { 485 char path[PATH_MAX]; 486 static char line[LINE_MAX]; 487 FILE *f; 488 char *cp; 489 490 snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid); 491 f = fopen(path, "r"); 492 if (!f) 493 return NULL; 494 if (!fgets(line, LINE_MAX, f)) { 495 fclose(f); 496 return NULL; 497 } 498 499 cp = strchr(line, ' '); 500 if (cp) 501 *cp = '\0'; 502 503 return line; 504} 505 506static struct proc *proc_adj_lru(int oomadj) { 507 return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]); 508} 509 510static void mp_event(uint32_t events) { 511 int i; 512 int ret; 513 unsigned long long evcount; 514 struct sysmeminfo mi; 515 int other_free; 516 int other_file; 517 int minfree = 0; 518 int min_score_adj = OOM_ADJUST_MAX + 1; 519 520 ret = read(mpevfd, &evcount, sizeof(evcount)); 521 if (ret < 0) 522 ALOGE("Error reading memory pressure event fd; errno=%d", 523 errno); 524 525 if (time(NULL) - kill_lasttime < KILL_TIMEOUT) 526 return; 527 528 if (zoneinfo_parse(&mi) < 0) 529 return; 530 531 other_free = mi.nr_free_pages - mi.totalreserve_pages; 532 other_file = mi.nr_file_pages - mi.nr_shmem; 533 534 for (i = 0; i < lowmem_targets_size; i++) { 535 minfree = lowmem_minfree[i]; 536 if (other_free < minfree && other_file < minfree) { 537 min_score_adj = lowmem_adj[i]; 538 break; 539 } 540 } 541 542 if (min_score_adj == OOM_ADJUST_MAX + 1) 543 return; 544 545 for (i = OOM_ADJUST_MAX; i >= min_score_adj; i--) { 546 struct proc *procp; 547 548 retry: 549 procp = proc_adj_lru(i); 550 551 if (procp) { 552 int pid = procp->pid; 553 char *taskname; 554 int tasksize; 555 int r; 556 557 taskname = proc_get_name(pid); 558 if (!taskname) { 559 pid_remove(pid); 560 goto retry; 561 } 562 563 tasksize = proc_get_size(pid); 564 if (tasksize < 0) { 565 pid_remove(pid); 566 goto retry; 567 } 568 569 ALOGI("Killing '%s' (%d), adj %d\n" 570 " to free %ldkB because cache %ldkB is below limit %ldkB for oom_adj %d\n" 571 " Free memory is %ldkB %s reserved", 572 taskname, pid, procp->oomadj, tasksize * page_k, 573 other_file * page_k, minfree * page_k, min_score_adj, 574 other_free * page_k, other_free >= 0 ? "above" : "below"); 575 r = kill(pid, SIGKILL); 576 pid_remove(pid); 577 578 if (r) { 579 ALOGE("kill(%d): errno=%d", procp->pid, errno); 580 goto retry; 581 } else { 582 time(&kill_lasttime); 583 break; 584 } 585 } 586 } 587} 588 589static int init_mp(char *levelstr, void *event_handler) 590{ 591 int mpfd; 592 int evfd; 593 int evctlfd; 594 char buf[256]; 595 struct epoll_event epev; 596 int ret; 597 598 mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY); 599 if (mpfd < 0) { 600 ALOGI("No kernel memory.pressure_level support (errno=%d)", errno); 601 goto err_open_mpfd; 602 } 603 604 evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY); 605 if (evctlfd < 0) { 606 ALOGI("No kernel memory cgroup event control (errno=%d)", errno); 607 goto err_open_evctlfd; 608 } 609 610 evfd = eventfd(0, EFD_NONBLOCK); 611 if (evfd < 0) { 612 ALOGE("eventfd failed for level %s; errno=%d", levelstr, errno); 613 goto err_eventfd; 614 } 615 616 ret = snprintf(buf, sizeof(buf), "%d %d %s", evfd, mpfd, levelstr); 617 if (ret >= (ssize_t)sizeof(buf)) { 618 ALOGE("cgroup.event_control line overflow for level %s", levelstr); 619 goto err; 620 } 621 622 ret = write(evctlfd, buf, strlen(buf) + 1); 623 if (ret == -1) { 624 ALOGE("cgroup.event_control write failed for level %s; errno=%d", 625 levelstr, errno); 626 goto err; 627 } 628 629 epev.events = EPOLLIN; 630 epev.data.ptr = event_handler; 631 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, evfd, &epev); 632 if (ret == -1) { 633 ALOGE("epoll_ctl for level %s failed; errno=%d", levelstr, errno); 634 goto err; 635 } 636 maxevents++; 637 mpevfd = evfd; 638 return 0; 639 640err: 641 close(evfd); 642err_eventfd: 643 close(evctlfd); 644err_open_evctlfd: 645 close(mpfd); 646err_open_mpfd: 647 return -1; 648} 649 650static int init(void) { 651 struct epoll_event epev; 652 int i; 653 int ret; 654 655 page_k = sysconf(_SC_PAGESIZE); 656 if (page_k == -1) 657 page_k = PAGE_SIZE; 658 page_k /= 1024; 659 660 epollfd = epoll_create(MAX_EPOLL_EVENTS); 661 if (epollfd == -1) { 662 ALOGE("epoll_create failed (errno=%d)", errno); 663 return -1; 664 } 665 666 ctrl_lfd = android_get_control_socket("lmkd"); 667 if (ctrl_lfd < 0) { 668 ALOGE("get lmkd control socket failed"); 669 return -1; 670 } 671 672 ret = listen(ctrl_lfd, 1); 673 if (ret < 0) { 674 ALOGE("lmkd control socket listen failed (errno=%d)", errno); 675 return -1; 676 } 677 678 epev.events = EPOLLIN; 679 epev.data.ptr = (void *)ctrl_connect_handler; 680 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ctrl_lfd, &epev) == -1) { 681 ALOGE("epoll_ctl for lmkd control socket failed (errno=%d)", errno); 682 return -1; 683 } 684 maxevents++; 685 686 use_inkernel_interface = !access(INKERNEL_MINFREE_PATH, W_OK); 687 688 if (use_inkernel_interface) { 689 ALOGI("Using in-kernel low memory killer interface"); 690 } else { 691 ret = init_mp(MEMPRESSURE_WATCH_LEVEL, (void *)&mp_event); 692 if (ret) 693 ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer"); 694 } 695 696 for (i = 0; i <= ADJTOSLOT(OOM_ADJUST_MAX); i++) { 697 procadjslot_list[i].next = &procadjslot_list[i]; 698 procadjslot_list[i].prev = &procadjslot_list[i]; 699 } 700 701 return 0; 702} 703 704static void mainloop(void) { 705 while (1) { 706 struct epoll_event events[maxevents]; 707 int nevents; 708 int i; 709 710 ctrl_dfd_reopened = 0; 711 nevents = epoll_wait(epollfd, events, maxevents, -1); 712 713 if (nevents == -1) { 714 if (errno == EINTR) 715 continue; 716 ALOGE("epoll_wait failed (errno=%d)", errno); 717 continue; 718 } 719 720 for (i = 0; i < nevents; ++i) { 721 if (events[i].events & EPOLLERR) 722 ALOGD("EPOLLERR on event #%d", i); 723 if (events[i].data.ptr) 724 (*(void (*)(uint32_t))events[i].data.ptr)(events[i].events); 725 } 726 } 727} 728 729int main(int argc, char **argv) { 730 if (!init()) 731 mainloop(); 732 733 ALOGI("exiting"); 734 return 0; 735} 736