summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-10-26 20:57:46 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-10-26 20:57:46 +0000
commit1b94df53de6780b22662d14f51aaeb927c30fa8c (patch)
tree1c30c6add9880e38509e2a6c07b6d29726f04f9c
parent1797c6976fdc4e475a5fcba18ede7fde395ea21b (diff)
parent04675d7781c99cb68e41c251645b2df0ff8d81e5 (diff)
downloadcore-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.c104
-rw-r--r--lmkd/tests/lmkd_test.cpp2
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