diff options
Diffstat (limited to 'sysdeps/linux/procmap.c')
-rw-r--r-- | sysdeps/linux/procmap.c | 105 |
1 files changed, 74 insertions, 31 deletions
diff --git a/sysdeps/linux/procmap.c b/sysdeps/linux/procmap.c index f5638bda..52043cc6 100644 --- a/sysdeps/linux/procmap.c +++ b/sysdeps/linux/procmap.c @@ -66,49 +66,78 @@ _glibtop_init_proc_map_s (glibtop *server) /* Provides detailed information about a process. */ -static void -add_smaps(glibtop *server, FILE *smaps, glibtop_map_entry *entry) + +struct smap_value { + char name[16]; + size_t name_len; + ptrdiff_t offset; +}; + +static int +compare(const void* a_key, const void* a_smap) { -#define SMAP_OFFSET(MEMBER) offsetof(glibtop_map_entry, MEMBER) + const char* key = a_key; + const struct smap_value* smap = a_smap; + return strncmp(key, smap->name, smap->name_len); +} - struct smap_value { - char name[15]; - ptrdiff_t offset; - }; +static gboolean +is_smap_value(const char* s) +{ + for ( ; *s; ++s) { + + if (isspace(*s)) + return FALSE; + + if (*s == ':') + return TRUE; + } + + return FALSE; +} + + +/* + Returns whether line is a 'value' line + and add if we know its meaning +*/ +static gboolean +parse_smaps(glibtop_map_entry *entry, const char* line) +{ +#define SMAP_OFFSET(MEMBER) offsetof(glibtop_map_entry, MEMBER) +#define STR_AND_LEN(X) (X), (sizeof X - 1) + + /* keep sorted */ const struct smap_value values[] = { - { "Size:", SMAP_OFFSET(size) }, - { "Rss:", SMAP_OFFSET(rss) }, - { "Shared_Clean:", SMAP_OFFSET(shared_clean) }, - { "Shared_Dirty:", SMAP_OFFSET(shared_dirty) }, - { "Private_Clean:", SMAP_OFFSET(private_clean) }, - { "Private_Dirty:", SMAP_OFFSET(private_dirty) } + { STR_AND_LEN("Private_Clean:"), SMAP_OFFSET(private_clean) }, + { STR_AND_LEN("Private_Dirty:"), SMAP_OFFSET(private_dirty) }, + { STR_AND_LEN("Rss:"), SMAP_OFFSET(rss) }, + { STR_AND_LEN("Shared_Clean:"), SMAP_OFFSET(shared_clean) }, + { STR_AND_LEN("Shared_Dirty:"), SMAP_OFFSET(shared_dirty) }, + { STR_AND_LEN("Size:"), SMAP_OFFSET(size) } }; - size_t i; +#undef STR_AND_LEN +#undef SMAP_OFFSET - for (i = 0; i < G_N_ELEMENTS(values); ++i) { - char line[80]; + struct smap_value* smap; + + smap = bsearch(line, values, G_N_ELEMENTS(values), sizeof values[0], compare); + + if (smap) { char *offset; guint64 *value; - if (!fgets(line, sizeof line, smaps) || !g_str_has_prefix(line, values[i].name)) { - glibtop_warn_io_r(server, - "Could not read smaps value %s", - values[i].name); - return; - } - offset = (void*) entry; - offset += values[i].offset; + offset += smap->offset; value = (void*) offset; - *value = get_scaled(line, values[i].name); + *value = get_scaled(line + smap->name_len, NULL); + return TRUE; } - entry->flags |= _glibtop_sysdeps_map_entry_smaps; - -#undef SMAP_OFFSET + return is_smap_value(line); } @@ -150,7 +179,7 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) while(TRUE) { - unsigned long perm = 0; + unsigned long perm; guint len; int line_end; @@ -164,6 +193,8 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) if (getline(&line, &line_size, maps) == -1) break; + new_entry_line: + if (sscanf(line, PROC_MAPS_FORMAT, &start, &end, flags, &offset, &dev_major, &dev_minor, &inode, &line_end) != 7) @@ -173,6 +204,7 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) g_strstrip(filename); /* Compute access permissions. */ + perm = 0; if (flags [0] == 'r') perm |= GLIBTOP_MAP_PERM_READ; @@ -205,11 +237,22 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid) entry->inode = inode; g_strlcpy(entry->filename, filename, sizeof entry->filename); - if (has_smaps) - add_smaps(server, maps, entry); + if (has_smaps) { + ssize_t ret; + entry->flags |= _glibtop_sysdeps_map_entry_smaps; + while ((ret = getline(&line, &line_size, maps)) != -1) { + if (!parse_smaps(entry, line)) + goto new_entry_line; + } + + if (ret == -1) + goto eof; + } } +eof: + free(line); fclose (maps); |