diff options
author | Benoît Dejean <bdejean@src.gnome.org> | 2008-03-07 18:14:47 +0000 |
---|---|---|
committer | Benoît Dejean <bdejean@src.gnome.org> | 2008-03-07 18:14:47 +0000 |
commit | a33e7854849c8d4614945a4ceee88c86b99edce7 (patch) | |
tree | 7509438409c2460640bf8d678971b0bc384f8b9c | |
parent | 40f849475b6eba715fce31be1300dcfc5fe66561 (diff) | |
download | libgtop-a33e7854849c8d4614945a4ceee88c86b99edce7.tar.gz |
Released 2.20.2LIBGTOP_2_20_2
svn path=/branches/gnome-2-20/; revision=2721
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | sysdeps/linux/glibtop_private.c | 40 | ||||
-rw-r--r-- | sysdeps/linux/procmap.c | 105 |
4 files changed, 103 insertions, 50 deletions
@@ -1,3 +1,9 @@ +05 Mars 2008: Overview of changes in 2.20.2 +=========================================== +* linux: + - fixed smaps parsing on >= 2.6.24.x. + backport of svn+ssh://svn.gnome.org/svn/libgtop/trunk@2713. + 7 January 2008: Overview of changes in 2.20.1 ============================================= * freebsd: diff --git a/configure.in b/configure.in index a5a0e555..089e7a9f 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl m4_define([libgtop_major_version], [2]) m4_define([libgtop_minor_version], [20]) -m4_define([libgtop_micro_version], [1]) +m4_define([libgtop_micro_version], [2]) m4_define([libgtop_version], [libgtop_major_version.libgtop_minor_version.libgtop_micro_version]) dnl increment if the interface has additions, changes, removals. diff --git a/sysdeps/linux/glibtop_private.c b/sysdeps/linux/glibtop_private.c index ac1a0e19..1029173c 100644 --- a/sysdeps/linux/glibtop_private.c +++ b/sysdeps/linux/glibtop_private.c @@ -17,27 +17,31 @@ unsigned long long get_scaled(const char *buffer, const char *key) { - const char *ptr; + const char *ptr = buffer;; char *next; - unsigned long long value = 0; + unsigned long long value; + + if (key) { + if (G_LIKELY((ptr = strstr(buffer, key)))) + ptr += strlen(key); + else { + g_warning("Could not read key '%s' in buffer '%s'", + key, buffer); + return 0; + } + } - if (G_LIKELY((ptr = strstr(buffer, key)))) - { - ptr += strlen(key); - value = strtoull(ptr, &next, 0); - - for ( ; *next; ++next) { - if (*next == 'k') { - value *= 1024; - break; - } else if (*next == 'M') { - value *= 1024 * 1024; - break; - } + value = strtoull(ptr, &next, 0); + + for ( ; *next; ++next) { + if (*next == 'k') { + value *= 1024; + break; + } else if (*next == 'M') { + value *= 1024 * 1024; + break; } - } else - g_warning("Could not read key '%s' in buffer '%s'", - key, buffer); + } return value; } 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); |