diff options
author | Colin Cross <ccross@android.com> | 2014-07-14 12:39:56 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2014-07-14 17:41:17 -0700 |
commit | 16b0946da1745877311562b8cbce08584c6a1b37 (patch) | |
tree | 91e380d2fbc77615c3f0d514587660abef09c178 /lmkd | |
parent | ce85d955a3ce73abffbdde1f5fdb41580d70cffc (diff) | |
download | system_core-16b0946da1745877311562b8cbce08584c6a1b37.zip system_core-16b0946da1745877311562b8cbce08584c6a1b37.tar.gz system_core-16b0946da1745877311562b8cbce08584c6a1b37.tar.bz2 |
lmkd: kill multiple tasks
The task selected to die may be small, add its approximate size
to other_free and other_file and keep killing until all thresholds
are met.
Bug: 16236289
Change-Id: Iceeca4c63fec98cae2bf53e258f7707cea408b07
Diffstat (limited to 'lmkd')
-rw-r--r-- | lmkd/lmkd.c | 141 |
1 files changed, 88 insertions, 53 deletions
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index b276f0a..2362cbf 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c @@ -560,29 +560,57 @@ static struct proc *proc_adj_lru(int oomadj) { return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]); } -static void mp_event(uint32_t events __unused) { - int i; - int ret; - unsigned long long evcount; - struct sysmeminfo mi; - int other_free; - int other_file; - int minfree = 0; - int min_score_adj = OOM_ADJUST_MAX + 1; +/* Kill one process specified by procp. Returns the size of the process killed */ +static int kill_one_process(struct proc *procp, int other_free, int other_file, + int minfree, int min_score_adj, bool first) +{ + int pid = procp->pid; + uid_t uid = procp->uid; + char *taskname; + int tasksize; + int r; + + taskname = proc_get_name(pid); + if (!taskname) { + pid_remove(pid); + return -1; + } - ret = read(mpevfd, &evcount, sizeof(evcount)); - if (ret < 0) - ALOGE("Error reading memory pressure event fd; errno=%d", - errno); + tasksize = proc_get_size(pid); + if (tasksize <= 0) { + pid_remove(pid); + return -1; + } - if (time(NULL) - kill_lasttime < KILL_TIMEOUT) - return; + ALOGI("Killing '%s' (%d), uid %d, adj %d\n" + " to free %ldkB because cache %s%ldkB is below limit %ldkB for oom_adj %d\n" + " Free memory is %s%ldkB %s reserved", + taskname, pid, uid, procp->oomadj, tasksize * page_k, + first ? "" : "~", other_file * page_k, minfree * page_k, min_score_adj, + first ? "" : "~", other_free * page_k, other_free >= 0 ? "above" : "below"); + r = kill(pid, SIGKILL); + killProcessGroup(uid, pid, SIGKILL); + pid_remove(pid); - if (zoneinfo_parse(&mi) < 0) - return; + if (r) { + ALOGE("kill(%d): errno=%d", procp->pid, errno); + return -1; + } else { + return tasksize; + } +} - other_free = mi.nr_free_pages - mi.totalreserve_pages; - other_file = mi.nr_file_pages - mi.nr_shmem; +/* + * Find a process to kill based on the current (possibly estimated) free memory + * and cached memory sizes. Returns the size of the killed processes. + */ +static int find_and_kill_process(int other_free, int other_file, bool first) +{ + int i; + int r; + int min_score_adj = OOM_ADJUST_MAX + 1; + int minfree = 0; + int killed_size = 0; for (i = 0; i < lowmem_targets_size; i++) { minfree = lowmem_minfree[i]; @@ -593,52 +621,59 @@ static void mp_event(uint32_t events __unused) { } if (min_score_adj == OOM_ADJUST_MAX + 1) - return; + return 0; for (i = OOM_ADJUST_MAX; i >= min_score_adj; i--) { struct proc *procp; - retry: +retry: procp = proc_adj_lru(i); if (procp) { - int pid = procp->pid; - uid_t uid = procp->uid; - char *taskname; - int tasksize; - int r; - - taskname = proc_get_name(pid); - if (!taskname) { - pid_remove(pid); - goto retry; - } - - tasksize = proc_get_size(pid); - if (tasksize < 0) { - pid_remove(pid); - goto retry; - } - - ALOGI("Killing '%s' (%d), uid %d, adj %d\n" - " to free %ldkB because cache %ldkB is below limit %ldkB for oom_adj %d\n" - " Free memory is %ldkB %s reserved", - taskname, pid, uid, procp->oomadj, tasksize * page_k, - other_file * page_k, minfree * page_k, min_score_adj, - other_free * page_k, other_free >= 0 ? "above" : "below"); - r = kill(pid, SIGKILL); - killProcessGroup(uid, pid, SIGKILL); - pid_remove(pid); - - if (r) { - ALOGE("kill(%d): errno=%d", procp->pid, errno); + killed_size = kill_one_process(procp, other_free, other_file, minfree, min_score_adj, first); + if (killed_size < 0) { goto retry; } else { - time(&kill_lasttime); - break; + return killed_size; } } } + + return 0; +} + +static void mp_event(uint32_t events __unused) { + int i; + int ret; + unsigned long long evcount; + struct sysmeminfo mi; + int other_free; + int other_file; + int killed_size; + bool first = true; + + ret = read(mpevfd, &evcount, sizeof(evcount)); + if (ret < 0) + ALOGE("Error reading memory pressure event fd; errno=%d", + errno); + + if (time(NULL) - kill_lasttime < KILL_TIMEOUT) + return; + + if (zoneinfo_parse(&mi) < 0) + return; + + other_free = mi.nr_free_pages - mi.totalreserve_pages; + other_file = mi.nr_file_pages - mi.nr_shmem; + + do { + killed_size = find_and_kill_process(other_free, other_file, first); + if (killed_size > 0) { + first = false; + other_free += killed_size; + other_file += killed_size; + } + } while (killed_size > 0); } static int init_mp(char *levelstr, void *event_handler) |