From f2d09ea79367552cc9e8efd884fb021292e88dfd Mon Sep 17 00:00:00 2001 From: Vitaliy Cherepanov Date: Mon, 31 Oct 2016 17:34:01 +0300 Subject: [PATCH] Update memps functionality Change-Id: Ifdf5b265f85ecc4c7a05bd9d4650c777ba5c020f Signed-off-by: Vitaliy Cherepanov --- daemon/sys_stat.c | 269 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 175 insertions(+), 94 deletions(-) diff --git a/daemon/sys_stat.c b/daemon/sys_stat.c index dd111cd..4ce7c0f 100644 --- a/daemon/sys_stat.c +++ b/daemon/sys_stat.c @@ -741,9 +741,72 @@ static uint64_t total_gem_memory(void) return total_gem_mem; } -static int ignore_smaps_field = 0; +static int smaps_field_lcnt = 0; -void init_read_mapinfo(void) +#define BUF_INC_SIZE (512 * 1024) /* maximal SMAPS I saw 2 MB */ +/* reads file contents into memory */ +static char* cread(const char* path) +{ + /* once allocated area for reads */ + static char* text = NULL; + static size_t size = 0; + + ssize_t ret; + char* ptr = text; + size_t cap = size; + int fd = open(path, O_RDONLY); + + if (fd < 0) { + return NULL; + } + + do { + /* ensure we have enough space */ + if (cap == 0) { + ptr = (char*)realloc(text, size + BUF_INC_SIZE); + if (ptr == NULL) { + ret = -1; + break; + } + + text = ptr; + ptr = text + size; + cap = BUF_INC_SIZE; + size += BUF_INC_SIZE; + } + ret = read(fd, ptr, cap); + if (ret == 0) { + *ptr = 0; + } else if (ret > 0) { + cap -= ret; + ptr += ret; + } + } while (ret > 0); + close(fd); + + return (ret < 0 ? NULL : text); +} /* cread */ + +/* like fgets/gets but adjusting contents pointer */ +static inline char* cgets(char** contents) +{ + if (contents && *contents && **contents) { + char* bos = *contents; /* begin of string */ + char* eos = strchr(bos, '\n'); /* end of string */ + + if (eos) { + *contents = eos + 1; + *eos = 0; + } else { + *contents = NULL; + } + return bos; + } + + return NULL; +} /* cgets */ + +int get_fixed_smaps_lcnt(void) { struct utsname buf; int ret; @@ -751,48 +814,116 @@ void init_read_mapinfo(void) ret = uname(&buf); if (!ret) { - if (buf.release[0] == '3') { - char *pch; - char str[3]; - int sub_version; - pch = strstr(buf.release, "."); - strncpy(str, pch+1, 2); - sub_version = atoi(str); - - if (sub_version >= 10) { - /* Referenced, Anonymous, AnonHugePages, - * Swap, KernelPageSize, MMUPageSize, - * Locked, VmFlags - */ - ignore_smaps_field = 8; - } else { - /* Referenced, Anonymous, AnonHugePages, - * Swap, KernelPageSize, MMUPageSize, - * Locked - */ - ignore_smaps_field = 7; - } - } else { - /* Referenced, Swap, KernelPageSize, MMUPageSize */ - ignore_smaps_field = 4; - } + char *pch; + char str[3]; + int sub_version; + pch = strstr(buf.release, "."); + strncpy(str, pch+1, 2); + sub_version = atoi(str); + + if (buf.release[0] >= '4') { + if (sub_version >= 4) + ret = 18; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Anonymous, AnonHugePages, Shared_Hugetlb, + * Private_Hugetlb, Swap, SwapPss, KernelPageSize, + * MMUPageSize, Locked, VmFlags */ + else if (sub_version == 3) + ret = 16; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Anonymous, AnonHugePages, Swap, SwapPss, + * KernelPageSize, MMUPageSize, Locked, VmFlags */ + else + ret = 15; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Anonymous, AnonHugePages, Swap, + * KernelPageSize, MMUPageSize, Locked, VmFlags */ + } else if (buf.release[0] == '3') { + if (sub_version >= 10) + ret = 15; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Anonymous, AnonHugePages, Swap, + * KernelPageSize, MMUPageSize, Locked, VmFlags */ + else + ret = 14; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Anonymous, AnonHugePages, Swap, + * KernelPageSize, MMUPageSize, Locked */ + } else { + ret = 11; + /* Size, Rss, Pss, Shared_Clean, Shard_Dirty, + * Private_Clean, Private_Drity, + * Referenced, Swap, KernelPageSize, MMUPageSize */ + } + } + return ret; +} + +int get_smaps_lcnt(void) +{ + char *buf, *buf_start, *line; + char cmd[64] = "/proc/self/smaps"; + int line_count = 0; + long start_addr, end_addr; + unsigned long pg_off; + int major, minor; + char flags[4]; + + buf_start = cread(cmd); + if (buf_start == NULL) + goto error; + + buf = buf_start; + line = cgets(&buf); + if (!line) + goto error; + + if (sscanf(line, "%lx-%lx %s %lx %x:%x", &start_addr, &end_addr, + flags, &pg_off, &major, &minor) != 6) + goto error; + + while ((line = cgets(&buf)) != NULL) { + line_count++; + if (sscanf(line, "%lx-%lx %s %lx %x:%x", &start_addr, + &end_addr, flags, &pg_off, &major, &minor) == 6) + break; } + + free(buf_start); + return line_count; + +error: + free(buf_start); /*TODO redesign it*/ + return get_fixed_smaps_lcnt(); } -/* 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /android/lib/libcomposer.so - * 012345678901234567890123456789012345678901234567890123456789 - * 0 1 2 3 4 5 - */ +void init_read_mapinfo() +{ + smaps_field_lcnt = get_smaps_lcnt(); +} + +/* b6e82000-b6e83000 rw-p 00020000 b3:19 714 /usr/lib/ld-2.20-2014.11.so : TM1 + * 7fae2e4b2000-7fae2e4b3000 r--p 00021000 fe:01 603 /usr/lib64/ld-2.20-2014.11.so : x86-64 Emulator + * 7f9389d000-7f9389e000 rw-p 0001f000 b3:12 618 /usr/lib64/ld-2.20-2014.11.so : Note4 + * 01234567890123456789012345678901234567890123456789012345678901234567890123456789 + * 0 1 2 3 4 5 6 7 + */ #define NAME_OFFSET 49 int read_mapinfo_section(FILE* fp, proc_t *proc) { char* line; int len; int tmp; - int rest_line; + int line_cnt; char buf[LARGE_BUFFER]; - if ((line = fgets(buf, sizeof(buf), fp)) == 0) + line_cnt = smaps_field_lcnt; + if ((--line_cnt <= 0) || (line = fgets(buf, sizeof(buf), fp)) == 0) return -EOF; len = strlen(buf); @@ -806,70 +937,20 @@ int read_mapinfo_section(FILE* fp, proc_t *proc) strncpy(proc->command, buf + NAME_OFFSET, len + 1); } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Size: %lu kB", &proc->size) != 1) { - LOGE("Get section error\n"); - goto oops; - } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Rss: %d kB", &tmp) != 1) { - LOGE("Get section error\n"); - goto oops; - } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Pss: %lu kB", &proc->pss) == 1) - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Shared_Clean: %lu kB", &proc->sh_mem_clean) != 1) { - LOGE("Get section error\n"); - goto oops; - } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Shared_Dirty: %lu kB", &proc->sh_mem_dirty) != 1) { - LOGE("Get section error\n"); - goto oops; - } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Private_Clean: %d kB", &tmp) != 1) { - LOGE("Get section error\n"); - goto oops; - } - if ((line = fgets(buf, sizeof(buf), fp)) == 0) { - LOGE("Get section error\n"); - goto oops; - } - if (sscanf(buf, "Private_Dirty: %d kB", &tmp) != 1) { - LOGE("Get section error\n"); - goto oops; - } - rest_line = ignore_smaps_field; - while (rest_line-- && (line = fgets(buf, sizeof(buf), fp))) { - if (sscanf(buf, "PSwap: %d kB", &tmp) == 1) - rest_line++; + while (line_cnt-- && (line = fgets(buf, sizeof(buf), fp))) { + if (sscanf(line, "Size: %lu kB", &proc->size) == 1) {} + else if (sscanf(line, "Rss: %d kB", &tmp) == 1) {} + else if (sscanf(line, "Pss: %lu kB", &proc->pss) == 1) {} + else if (sscanf(line, "Shared_Clean: %lu kB", + &proc->sh_mem_clean) == 1) {} + else if (sscanf(line, "Shared_Dirty: %lu kB", + &proc->sh_mem_dirty) == 1) {} + else if (sscanf(line, "Private_Clean: %d kB", &tmp) == 1) {} + else if (sscanf(line, "Private_Dirty: %d kB", &tmp) == 1) {} + else if (sscanf(line, "Swap: %d kB", &tmp) == 1) {} } - return 0; -oops: - LOGE("Get section error\n"); - return -1; } -- 2.7.4