Merge PQ1A.181205.006 from Pi-QPR1-Release into ToT for Pi-Platform release.\n\nBUG: 120448245
Change-Id: Ia66dd2a90e074d2fcb0dbaeb424031a41752dd03
This commit is contained in:
commit
25f1ac6be2
2 changed files with 71 additions and 35 deletions
104
lmkd/lmkd.c
104
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 (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 (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");
|
||||
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("Killing to reclaim %ldkB, reclaimed %ldkB at oom_adj %d",
|
||||
pages_to_free * page_k, pages_freed * page_k, min_score_adj);
|
||||
}
|
||||
|
||||
if (pages_freed < pages_to_free) {
|
||||
ALOGI("Unable to free enough memory (pages to free=%d, pages freed=%d)",
|
||||
pages_to_free, pages_freed);
|
||||
} else {
|
||||
ALOGI("Reclaimed enough memory (pages to free=%d, pages freed=%d)",
|
||||
pages_to_free, pages_freed);
|
||||
gettimeofday(&last_report_tm, NULL);
|
||||
if (report_skip_count > 0) {
|
||||
ALOGI("Suppressed %lu failed kill reports", report_skip_count);
|
||||
report_skip_count = 0;
|
||||
}
|
||||
|
||||
last_report_tm = curr_tm;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue