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;
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);
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;
}