From e7cfa67a0573a3680ce63dfc48121bf6396be45d Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Fri, 5 Oct 2018 12:34:59 -0700 Subject: [PATCH] Read memory stats from /proc/pid/stat file. (cherry pick from commit 0301683e49ab255769b15469487feaab3466167a) Bug: 117333340 Test: Manual testing using alloc-stress tool Merged-In: Ie555933aafa6a6b7aa1dbf5518ebe804376e0afd Change-Id: I8ab08606dba7de2f65711204453067dbfbdcbdd8 --- lmkd/lmkd.c | 75 ++++++++++++++++++++++++++++++++++++++----------- lmkd/statslog.h | 3 ++ 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index 26f4df6bf..d6632a2f8 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c @@ -984,7 +984,7 @@ static void ctrl_connect_handler(int data __unused, uint32_t events __unused) { } #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]; int64_t value; @@ -1006,25 +1006,61 @@ static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) { mem_st->swap_in_bytes = value; } -static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) { - FILE *fp; - char buf[PATH_MAX]; +static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) { + FILE *fp; + 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) { - ALOGE("%s open failed: %s", buf, strerror(errno)); - return -1; - } + if (fp == NULL) { + ALOGE("%s open failed: %s", buf, strerror(errno)); + return -1; + } - while (fgets(buf, PAGE_SIZE, fp) != NULL ) { - memory_stat_parse_line(buf, mem_st); - } - fclose(fp); + while (fgets(buf, PAGE_SIZE, fp) != NULL) { + memory_stat_parse_line(buf, mem_st); + } + 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 @@ -1316,7 +1352,11 @@ static int kill_one_process(struct proc* procp) { #ifdef LMKD_LOG_STATS 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 @@ -1344,6 +1384,9 @@ static int kill_one_process(struct proc* procp) { 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, 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 result = tasksize; diff --git a/lmkd/statslog.h b/lmkd/statslog.h index edebb195b..84584805d 100644 --- a/lmkd/statslog.h +++ b/lmkd/statslog.h @@ -67,6 +67,9 @@ struct 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