diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-10-26 20:57:46 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-10-26 20:57:46 +0000 |
commit | 1b94df53de6780b22662d14f51aaeb927c30fa8c (patch) | |
tree | 1c30c6add9880e38509e2a6c07b6d29726f04f9c | |
parent | 1797c6976fdc4e475a5fcba18ede7fde395ea21b (diff) | |
parent | 04675d7781c99cb68e41c251645b2df0ff8d81e5 (diff) | |
download | core-pie-qpr1-s3-release.tar.gz |
Merge cherrypicks of [5371217, 5371218, 5370861, 5369688, 5370512, 5370513, 5371204, 5371205] into pi-qpr1-releaseandroid-9.0.0_r30android-9.0.0_r22android-9.0.0_r21pie-qpr1-s3-releasepie-qpr1-release
Change-Id: I9e0dd4a5cedf8eeba4a67c49e7fb4e93c7ce21ad
-rw-r--r-- | lmkd/lmkd.c | 104 | ||||
-rw-r--r-- | lmkd/tests/lmkd_test.cpp | 2 |
2 files changed, 71 insertions, 35 deletions
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index cc5a7c2cf..6e2945376 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c @@ -27,8 +27,8 @@ #include <sys/eventfd.h> #include <sys/mman.h> #include <sys/socket.h> -#include <sys/types.h> #include <sys/sysinfo.h> +#include <sys/types.h> #include <unistd.h> #include <cutils/properties.h> @@ -79,6 +79,8 @@ #define STRINGIFY(x) STRINGIFY_INTERNAL(x) #define STRINGIFY_INTERNAL(x) #x +#define FAIL_REPORT_RLIMIT_MS 1000 + /* default to old in-kernel interface if no memory pressure events */ static int use_inkernel_interface = 1; static bool has_inkernel_module; @@ -955,9 +957,10 @@ static struct proc *proc_get_heaviest(int oomadj) { return maxprocp; } +static int last_killed_pid = -1; + /* Kill one process specified by procp. Returns the size of the process killed */ -static int kill_one_process(struct proc* procp, int min_score_adj, - enum vmpressure_level level) { +static int kill_one_process(struct proc* procp) { int pid = procp->pid; uid_t uid = procp->uid; char *taskname; @@ -990,15 +993,14 @@ static int kill_one_process(struct proc* procp, int min_score_adj, TRACE_KILL_START(pid); r = kill(pid, SIGKILL); - ALOGI( - "Killing '%s' (%d), uid %d, adj %d\n" - " to free %ldkB because system is under %s memory pressure oom_adj %d\n", - taskname, pid, uid, procp->oomadj, tasksize * page_k, - level_name[level], min_score_adj); + ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", + taskname, pid, uid, procp->oomadj, tasksize * page_k); pid_remove(pid); TRACE_KILL_END(); + last_killed_pid = pid; + if (r) { ALOGE("kill(%d): errno=%d", pid, errno); return -1; @@ -1021,8 +1023,7 @@ static int kill_one_process(struct proc* procp, int min_score_adj, * If pages_to_free is set to 0 only one process will be killed. * Returns the size of the killed processes. */ -static int find_and_kill_processes(enum vmpressure_level level, - int min_score_adj, int pages_to_free) { +static int find_and_kill_processes(int min_score_adj, int pages_to_free) { int i; int killed_size; int pages_freed = 0; @@ -1041,7 +1042,7 @@ static int find_and_kill_processes(enum vmpressure_level level, if (!procp) break; - killed_size = kill_one_process(procp, min_score_adj, level); + killed_size = kill_one_process(procp); if (killed_size >= 0) { #ifdef LMKD_LOG_STATS if (enable_stats_log && !lmk_state_change_start) { @@ -1138,6 +1139,22 @@ static inline unsigned long get_time_diff_ms(struct timeval *from, (to->tv_usec - from->tv_usec) / 1000; } +static bool is_kill_pending(void) { + char buf[24]; + if (last_killed_pid < 0) { + return false; + } + + snprintf(buf, sizeof(buf), "/proc/%d/", last_killed_pid); + if (access(buf, F_OK) == 0) { + return true; + } + + // reset last killed PID because there's nothing pending + last_killed_pid = -1; + return false; +} + static void mp_event_common(int data, uint32_t events __unused) { int ret; unsigned long long evcount; @@ -1146,8 +1163,9 @@ static void mp_event_common(int data, uint32_t events __unused) { enum vmpressure_level lvl; union meminfo mi; union zoneinfo zi; - static struct timeval last_report_tm; - static unsigned long skip_count = 0; + struct timeval curr_tm; + static struct timeval last_kill_tm; + static unsigned long kill_skip_count = 0; enum vmpressure_level level = (enum vmpressure_level)data; long other_free = 0, other_file = 0; int min_score_adj; @@ -1176,19 +1194,22 @@ static void mp_event_common(int data, uint32_t events __unused) { } } + gettimeofday(&curr_tm, NULL); if (kill_timeout_ms) { - struct timeval curr_tm; - gettimeofday(&curr_tm, NULL); - if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) { - skip_count++; + // If we're within the timeout, see if there's pending reclaim work + // from the last killed process. If there is (as evidenced by + // /proc/<pid> continuing to exist), skip killing for now. + if ((get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) && + (low_ram_device || is_kill_pending())) { + kill_skip_count++; return; } } - if (skip_count > 0) { + if (kill_skip_count > 0) { ALOGI("%lu memory pressure events were skipped after a kill!", - skip_count); - skip_count = 0; + kill_skip_count); + kill_skip_count = 0; } if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) { @@ -1280,13 +1301,15 @@ static void mp_event_common(int data, uint32_t events __unused) { do_kill: if (low_ram_device) { /* For Go devices kill only one task */ - if (find_and_kill_processes(level, level_oomadj[level], 0) == 0) { + if (find_and_kill_processes(level_oomadj[level], 0) == 0) { if (debug_process_killing) { ALOGI("Nothing to kill"); } } } else { int pages_freed; + static struct timeval last_report_tm; + static unsigned long report_skip_count = 0; if (!use_minfree_levels) { /* If pressure level is less than critical and enough free swap then ignore */ @@ -1314,24 +1337,37 @@ do_kill: min_score_adj = level_oomadj[level]; } - pages_freed = find_and_kill_processes(level, min_score_adj, pages_to_free); + pages_freed = find_and_kill_processes(min_score_adj, 0); - if (use_minfree_levels) { - ALOGI("Killing because cache %ldkB is below " - "limit %ldkB for oom_adj %d\n" - " Free memory is %ldkB %s reserved", - other_file * page_k, minfree * page_k, min_score_adj, - other_free * page_k, other_free >= 0 ? "above" : "below"); + if (pages_freed == 0) { + /* Rate limit kill reports when nothing was reclaimed */ + if (get_time_diff_ms(&last_report_tm, &curr_tm) < FAIL_REPORT_RLIMIT_MS) { + report_skip_count++; + return; + } + } else { + /* If we killed anything, update the last killed timestamp. */ + last_kill_tm = curr_tm; } - if (pages_freed < pages_to_free) { - ALOGI("Unable to free enough memory (pages to free=%d, pages freed=%d)", - pages_to_free, pages_freed); + if (use_minfree_levels) { + ALOGI("Killing to reclaim %ldkB, reclaimed %ldkB, cache(%ldkB) and " + "free(%" PRId64 "kB)-reserved(%" PRId64 "kB) below min(%ldkB) for oom_adj %d", + pages_to_free * page_k, pages_freed * page_k, + other_file * page_k, mi.field.nr_free_pages * page_k, + zi.field.totalreserve_pages * page_k, + minfree * page_k, min_score_adj); } else { - ALOGI("Reclaimed enough memory (pages to free=%d, pages freed=%d)", - pages_to_free, pages_freed); - gettimeofday(&last_report_tm, NULL); + ALOGI("Killing to reclaim %ldkB, reclaimed %ldkB at oom_adj %d", + pages_to_free * page_k, pages_freed * page_k, min_score_adj); } + + if (report_skip_count > 0) { + ALOGI("Suppressed %lu failed kill reports", report_skip_count); + report_skip_count = 0; + } + + last_report_tm = curr_tm; } } diff --git a/lmkd/tests/lmkd_test.cpp b/lmkd/tests/lmkd_test.cpp index 4afaeb81f..c2ad74a71 100644 --- a/lmkd/tests/lmkd_test.cpp +++ b/lmkd/tests/lmkd_test.cpp @@ -39,7 +39,7 @@ using namespace android::base; #define LMKDTEST_RESPAWN_FLAG "LMKDTEST_RESPAWN" #define LMKD_LOGCAT_MARKER "lowmemorykiller" -#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Killing '%s'" +#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Kill '%s'" #define OOM_MARKER "Out of memory" #define OOM_KILL_MARKER "Killed process" #define MIN_LOG_SIZE 100 |