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