Snap for 5180536 from cddcc0d9cf7cbba53e54d67455737a3900ae5d9f to pi-platform-release

Change-Id: Ie01971579962cce36d3170df9c1cb09f8b152520
This commit is contained in:
android-build-team Robot 2019-02-09 02:22:24 +00:00
commit 8600b07f2a
3 changed files with 122 additions and 25 deletions

View File

@ -30,6 +30,7 @@ enum lmk_cmd {
LMK_TARGET = 0, /* Associate minfree with oom_adj_score */ LMK_TARGET = 0, /* Associate minfree with oom_adj_score */
LMK_PROCPRIO, /* Register a process and set its oom_adj_score */ LMK_PROCPRIO, /* Register a process and set its oom_adj_score */
LMK_PROCREMOVE, /* Unregister a process */ LMK_PROCREMOVE, /* Unregister a process */
LMK_PROCPURGE, /* Purge all registered processes */
}; };
/* /*
@ -142,6 +143,15 @@ inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
return 2 * sizeof(int); return 2 * sizeof(int);
} }
/*
* Prepare LMK_PROCPURGE packet and return packet size in bytes.
* Warning: no checks performed, caller should ensure valid parameters.
*/
inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
packet[0] = htonl(LMK_PROCPURGE);
return sizeof(int);
}
__END_DECLS __END_DECLS
#endif /* _LMKD_H_ */ #endif /* _LMKD_H_ */

134
lmkd.c
View File

@ -114,6 +114,7 @@ static bool low_ram_device;
static bool kill_heaviest_task; static bool kill_heaviest_task;
static unsigned long kill_timeout_ms; static unsigned long kill_timeout_ms;
static bool use_minfree_levels; static bool use_minfree_levels;
static bool per_app_memcg;
/* data required to handle events */ /* data required to handle events */
struct event_handler_info { struct event_handler_info {
@ -523,9 +524,38 @@ static void cmd_procremove(LMKD_CTRL_PACKET packet) {
return; return;
lmkd_pack_get_procremove(packet, &params); lmkd_pack_get_procremove(packet, &params);
/*
* WARNING: After pid_remove() procp is freed and can't be used!
* Therefore placed at the end of the function.
*/
pid_remove(params.pid); pid_remove(params.pid);
} }
static void cmd_procpurge() {
int i;
struct proc *procp;
struct proc *next;
if (use_inkernel_interface) {
return;
}
for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
procadjslot_list[i].next = &procadjslot_list[i];
procadjslot_list[i].prev = &procadjslot_list[i];
}
for (i = 0; i < PIDHASH_SZ; i++) {
procp = pidhash[i];
while (procp) {
next = procp->pidhash_next;
free(procp);
procp = next;
}
}
memset(&pidhash[0], 0, sizeof(pidhash));
}
static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) { static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
int i; int i;
struct lmk_target target; struct lmk_target target;
@ -634,6 +664,11 @@ static void ctrl_command_handler(int dsock_idx) {
goto wronglen; goto wronglen;
cmd_procremove(packet); cmd_procremove(packet);
break; break;
case LMK_PROCPURGE:
if (nargs != 0)
goto wronglen;
cmd_procpurge();
break;
default: default:
ALOGE("Received unknown command code %d", cmd); ALOGE("Received unknown command code %d", cmd);
return; return;
@ -699,7 +734,7 @@ static void ctrl_connect_handler(int data __unused, uint32_t events __unused) {
} }
#ifdef LMKD_LOG_STATS #ifdef LMKD_LOG_STATS
static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) { static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
char key[LINE_MAX + 1]; char key[LINE_MAX + 1];
int64_t value; int64_t value;
@ -721,25 +756,62 @@ static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
mem_st->swap_in_bytes = value; mem_st->swap_in_bytes = value;
} }
static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) { static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
FILE *fp; FILE* fp;
char buf[PATH_MAX]; char buf[PATH_MAX];
snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid); snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
fp = fopen(buf, "r"); fp = fopen(buf, "r");
if (fp == NULL) { if (fp == NULL) {
ALOGE("%s open failed: %s", buf, strerror(errno)); ALOGE("%s open failed: %s", buf, strerror(errno));
return -1; return -1;
} }
while (fgets(buf, PAGE_SIZE, fp) != NULL ) { while (fgets(buf, PAGE_SIZE, fp) != NULL) {
memory_stat_parse_line(buf, mem_st); memory_stat_parse_line(buf, mem_st);
} }
fclose(fp); fclose(fp);
return 0; return 0;
}
static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
char path[PATH_MAX];
char buffer[PROC_STAT_BUFFER_SIZE];
int fd, ret;
snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
ALOGE("%s open failed: %s", path, strerror(errno));
return -1;
}
ret = read(fd, buffer, sizeof(buffer));
if (ret < 0) {
ALOGE("%s read failed: %s", path, strerror(errno));
close(fd);
return -1;
}
close(fd);
// field 10 is pgfault
// field 12 is pgmajfault
// field 24 is rss_in_pages
int64_t pgfault = 0, pgmajfault = 0, rss_in_pages = 0;
if (sscanf(buffer,
"%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
"%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
"%*d %*d %" SCNd64 "",
&pgfault, &pgmajfault, &rss_in_pages) != 3) {
return -1;
}
mem_st->pgfault = pgfault;
mem_st->pgmajfault = pgmajfault;
mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);
return 0;
} }
#endif #endif
@ -966,6 +1038,7 @@ static int kill_one_process(struct proc* procp) {
char *taskname; char *taskname;
int tasksize; int tasksize;
int r; int r;
int result = -1;
#ifdef LMKD_LOG_STATS #ifdef LMKD_LOG_STATS
struct memory_stat mem_st = {}; struct memory_stat mem_st = {};
@ -974,28 +1047,30 @@ static int kill_one_process(struct proc* procp) {
taskname = proc_get_name(pid); taskname = proc_get_name(pid);
if (!taskname) { if (!taskname) {
pid_remove(pid); goto out;
return -1;
} }
tasksize = proc_get_size(pid); tasksize = proc_get_size(pid);
if (tasksize <= 0) { if (tasksize <= 0) {
pid_remove(pid); goto out;
return -1;
} }
#ifdef LMKD_LOG_STATS #ifdef LMKD_LOG_STATS
if (enable_stats_log) { if (enable_stats_log) {
memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid); if (per_app_memcg) {
memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
} else {
memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
}
} }
#endif #endif
TRACE_KILL_START(pid); TRACE_KILL_START(pid);
/* CAP_KILL required */
r = kill(pid, SIGKILL); r = kill(pid, SIGKILL);
ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
taskname, pid, uid, procp->oomadj, tasksize * page_k); taskname, pid, uid, procp->oomadj, tasksize * page_k);
pid_remove(pid);
TRACE_KILL_END(); TRACE_KILL_END();
@ -1003,19 +1078,28 @@ static int kill_one_process(struct proc* procp) {
if (r) { if (r) {
ALOGE("kill(%d): errno=%d", pid, errno); ALOGE("kill(%d): errno=%d", pid, errno);
return -1; goto out;
} else { } else {
#ifdef LMKD_LOG_STATS #ifdef LMKD_LOG_STATS
if (memory_stat_parse_result == 0) { if (memory_stat_parse_result == 0) {
stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes, procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
mem_st.cache_in_bytes, mem_st.swap_in_bytes); mem_st.cache_in_bytes, mem_st.swap_in_bytes);
} else if (enable_stats_log) {
stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
-1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1);
} }
#endif #endif
return tasksize; result = tasksize;
} }
return tasksize; out:
/*
* WARNING: After pid_remove() procp is freed and can't be used!
* Therefore placed at the end of the function.
*/
pid_remove(pid);
return result;
} }
/* /*
@ -1578,7 +1662,7 @@ int main(int argc __unused, char **argv __unused) {
(unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0); (unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
use_minfree_levels = use_minfree_levels =
property_get_bool("ro.lmk.use_minfree_levels", false); property_get_bool("ro.lmk.use_minfree_levels", false);
per_app_memcg = property_get_bool("ro.config.per_app_memcg", low_ram_device);
#ifdef LMKD_LOG_STATS #ifdef LMKD_LOG_STATS
statslog_init(&log_ctx, &enable_stats_log); statslog_init(&log_ctx, &enable_stats_log);
#endif #endif

View File

@ -67,6 +67,9 @@ struct memory_stat {
}; };
#define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat" #define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
#define PROC_STAT_FILE_PATH "/proc/%d/stat"
#define PROC_STAT_BUFFER_SIZE 1024
#define BYTES_IN_KILOBYTE 1024
/** /**
* Logs the change in LMKD state which is used as start/stop boundaries for logging * Logs the change in LMKD state which is used as start/stop boundaries for logging