summaryrefslogtreecommitdiff
path: root/sysdeps/linux
diff options
context:
space:
mode:
authorBenoît Dejean <bdejean@src.gnome.org>2005-12-12 13:37:15 +0000
committerBenoît Dejean <bdejean@src.gnome.org>2005-12-12 13:37:15 +0000
commitba7355df9ec7bb5f1df2146d2e1d8009d97eb1f6 (patch)
treeae66915d225176438e6d55217bf53c57cc41d6f3 /sysdeps/linux
parent451f9f9d6cd066f792c5600ed8852dddcbb18234 (diff)
downloadlibgtop-ba7355df9ec7bb5f1df2146d2e1d8009d97eb1f6.tar.gz
Implemented smap support. Closes #320710.
* procmap.c: (add_smaps), (glibtop_get_proc_map_s): Implemented smap support. Closes #320710.
Diffstat (limited to 'sysdeps/linux')
-rw-r--r--sysdeps/linux/ChangeLog7
-rw-r--r--sysdeps/linux/procmap.c84
2 files changed, 87 insertions, 4 deletions
diff --git a/sysdeps/linux/ChangeLog b/sysdeps/linux/ChangeLog
index 3ff090dc..d75a5161 100644
--- a/sysdeps/linux/ChangeLog
+++ b/sysdeps/linux/ChangeLog
@@ -1,5 +1,12 @@
2005-12-12 Benoît Dejean <benoit@placenet.org>
+ * procmap.c: (add_smaps), (glibtop_get_proc_map_s):
+
+ Implemented smap support.
+ Closes #320710.
+
+2005-12-12 Benoît Dejean <benoit@placenet.org>
+
* proclist.c: (glibtop_get_proclist_s):
Improved so that it doesn't stat(2) every /proc/<PID>/.
diff --git a/sysdeps/linux/procmap.c b/sysdeps/linux/procmap.c
index c6752f2b..5b16d349 100644
--- a/sysdeps/linux/procmap.c
+++ b/sysdeps/linux/procmap.c
@@ -29,6 +29,13 @@
#include <glibtop/procmap.h>
#include <linux/kdev_t.h>
+#include <stddef.h>
+
+#include "glibtop_private.h"
+
+
+#define MAPS_FILE "/proc/%u/maps"
+#define SMAPS_FILE "/proc/%u/smaps"
#define PROC_MAPS_FORMAT ((sizeof(void*) == 8) \
@@ -46,6 +53,12 @@ static const unsigned long _glibtop_sysdeps_map_entry =
(1L << GLIBTOP_MAP_ENTRY_INODE) + (1L << GLIBTOP_MAP_ENTRY_DEVICE) +
(1L << GLIBTOP_MAP_ENTRY_FILENAME);
+static const unsigned long _glibtop_sysdeps_map_entry_smaps =
+(1UL << GLIBTOP_MAP_ENTRY_SIZE) + (1UL << GLIBTOP_MAP_ENTRY_RSS) +
+(1UL << GLIBTOP_MAP_ENTRY_SHARED_DIRTY) + (1UL << GLIBTOP_MAP_ENTRY_SHARED_CLEAN) +
+(1UL << GLIBTOP_MAP_ENTRY_PRIVATE_DIRTY) + (1UL << GLIBTOP_MAP_ENTRY_PRIVATE_CLEAN);
+
+
/* Init function. */
void
@@ -56,6 +69,55 @@ 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)
+{
+#define SMAP_OFFSET(MEMBER) offsetof(glibtop_map_entry, MEMBER)
+
+ struct smap_value {
+ const char *name;
+ ptrdiff_t offset;
+ };
+
+ 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) }
+ };
+
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS(values); ++i) {
+ char line[80];
+ char *offset;
+ guint64 *value;
+
+ if (!fgets(line, sizeof line, smaps)) {
+ glibtop_warn_io_r(server,
+ "Could not read smaps value %s",
+ values[i].name);
+ return;
+ }
+
+ offset = (void*) entry;
+ offset += values[i].offset;
+ value = (void*) offset;
+
+ *value = get_scaled(line, values[i].name);
+ }
+
+ entry->flags |= _glibtop_sysdeps_map_entry_smaps;
+
+#undef SMAP_OFFSET
+}
+
+
+
+
glibtop_map_entry *
glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid)
{
@@ -70,12 +132,18 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid)
sizeof(glibtop_map_entry),
100);
FILE *maps;
+ const char *filename;
glibtop_init_s (&server, GLIBTOP_SYSDEPS_PROC_MAP, 0);
memset (buf, 0, sizeof (glibtop_proc_map));
- snprintf (procfilename, sizeof procfilename, "/proc/%d/maps", pid);
+ if (server->os_version_code >= LINUX_VERSION_CODE(2, 6, 0))
+ filename = SMAPS_FILE;
+ else
+ filename = MAPS_FILE;
+
+ snprintf (procfilename, sizeof procfilename, filename, (unsigned)pid);
if((maps = fopen (procfilename, "r")) == NULL) {
return (glibtop_map_entry*) g_array_free(entry_list, TRUE);
@@ -83,6 +151,8 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid)
while(TRUE)
{
+ char line[1024];
+
unsigned long perm = 0;
int rv;
guint len;
@@ -94,11 +164,13 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid)
glibtop_map_entry *entry;
+ if (!fgets(line, sizeof line, maps))
+ break;
/* 8 arguments */
- rv = fscanf (maps, PROC_MAPS_FORMAT,
- &start, &end, flags, &offset,
- &dev_major, &dev_minor, &inode, filename);
+ rv = sscanf(line, PROC_MAPS_FORMAT,
+ &start, &end, flags, &offset,
+ &dev_major, &dev_minor, &inode, filename);
if(rv == EOF || rv < 7)
break;
@@ -138,6 +210,10 @@ glibtop_get_proc_map_s (glibtop *server, glibtop_proc_map *buf, pid_t pid)
entry->device = (guint64) MKDEV(dev_major, dev_minor);
entry->inode = (guint64) inode;
g_strlcpy(entry->filename, filename, sizeof entry->filename);
+
+ if (server->os_version_code >= LINUX_VERSION_CODE(2, 6, 0))
+ add_smaps(server, maps, entry);
+
}
fclose (maps);