summaryrefslogtreecommitdiff
path: root/src/procmap-store.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-11-29 15:19:57 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2007-11-29 15:19:57 +0000
commita52c32123d772ba317a8a26b60b321fa3790b969 (patch)
tree4b3a4720e937cdaab91a27bd3f5e5fbcb1842868 /src/procmap-store.c
parent37e5ae98be10037b8e123aac0fbba704494eb9f9 (diff)
Quick and dirty smap info using libgtop.
Diffstat (limited to 'src/procmap-store.c')
-rw-r--r--src/procmap-store.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/procmap-store.c b/src/procmap-store.c
new file mode 100644
index 0000000..5d12092
--- /dev/null
+++ b/src/procmap-store.c
@@ -0,0 +1,295 @@
+#include <gtk/gtk.h>
+#include <glibtop.h>
+#include <glibtop/procmap.h>
+
+#include "memfault.h"
+#include "procmap.h"
+
+struct _procmap_store {
+ GObject object;
+
+ GPid pid;
+ glibtop_proc_map procmap;
+ glibtop_map_entry *maps;
+
+ GCompareFunc sort_func;
+};
+
+typedef struct _procmap_store_class {
+ GObjectClass parent_class;
+} ProcmapStoreClass;
+
+static void
+procmap_store_tree_model_init (GtkTreeModelIface *iface);
+
+static GType
+procmap_store_get_type (void);
+
+G_DEFINE_TYPE_WITH_CODE (ProcmapStore, procmap_store, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+ procmap_store_tree_model_init))
+
+static void
+procmap_store_finalize (GObject *obj)
+{
+ ProcmapStore *self = (ProcmapStore *) obj;
+
+ g_free (self->maps);
+
+ G_OBJECT_CLASS (procmap_store_parent_class)->finalize (obj);
+}
+
+static void
+procmap_store_class_init (ProcmapStoreClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ object_class->finalize = procmap_store_finalize;
+}
+
+
+/* GtkTreeModelIface */
+
+static GtkTreeModelFlags
+procmap_store_get_flags (GtkTreeModel *tree_model)
+{
+ return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
+}
+
+static gint
+procmap_store_get_n_columns (GtkTreeModel *tree_model)
+{
+ return PROCMAP_N_COLUMNS;
+}
+
+static GType
+procmap_store_get_column_type (GtkTreeModel *tree_model,
+ gint index)
+{
+ switch (index) {
+ case PROCMAP_FILENAME: return G_TYPE_STRING;
+ case PROCMAP_MODE: return G_TYPE_STRING;
+
+ case PROCMAP_START: return G_TYPE_ULONG;
+ case PROCMAP_END: return G_TYPE_ULONG;
+ case PROCMAP_OFFSET: return G_TYPE_ULONG;
+
+ case PROCMAP_SIZE: return G_TYPE_ULONG;
+ case PROCMAP_RSS: return G_TYPE_ULONG;
+
+ case PROCMAP_PRIVATE_CLEAN: return G_TYPE_ULONG;
+ case PROCMAP_PRIVATE_DIRTY: return G_TYPE_ULONG;
+ default: return G_TYPE_INVALID;
+ }
+}
+
+static gboolean
+procmap_store_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ ProcmapStore *self = (ProcmapStore *) tree_model;
+ guint n;
+
+ n = gtk_tree_path_get_depth (path);
+ g_return_val_if_fail (n == 1, FALSE);
+
+ n = gtk_tree_path_get_indices (path)[0];
+ if (n >= self->procmap.number)
+ return FALSE;
+
+ iter->user_data = &self->maps[n];
+ iter->user_data2 = GUINT_TO_POINTER (n);
+ iter->stamp = 1;
+ return TRUE;
+}
+
+static GtkTreePath *
+procmap_store_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, GPOINTER_TO_UINT (iter->user_data2));
+ return path;
+}
+
+static void
+procmap_store_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value)
+{
+ glibtop_map_entry *entry = iter->user_data;
+ switch (column) {
+ case PROCMAP_FILENAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value,
+ entry->flags & (1L << GLIBTOP_MAP_ENTRY_FILENAME) ?
+ entry->filename : "");
+ break;
+ case PROCMAP_MODE: {
+ gchar perm[6];
+ perm [0] = entry->perm & GLIBTOP_MAP_PERM_READ ? 'r' : '-';
+ perm [1] = entry->perm & GLIBTOP_MAP_PERM_WRITE ? 'w' : '-';
+ perm [2] = entry->perm & GLIBTOP_MAP_PERM_EXECUTE ? 'x' : '-';
+ perm [3] = entry->perm & GLIBTOP_MAP_PERM_SHARED ? 's' : '-';
+ perm [4] = entry->perm & GLIBTOP_MAP_PERM_PRIVATE ? 'p' : '-';
+ perm [5] = '\0';
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, perm);
+ break;
+ }
+
+ case PROCMAP_START:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->start);
+ break;
+ case PROCMAP_END:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->end);
+ break;
+ case PROCMAP_OFFSET:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->offset);
+ break;
+
+ case PROCMAP_SIZE:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->size);
+ break;
+ case PROCMAP_RSS:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->rss);
+ break;
+
+ case PROCMAP_PRIVATE_CLEAN:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->private_clean);
+ break;
+ case PROCMAP_PRIVATE_DIRTY:
+ g_value_init (value, G_TYPE_ULONG);
+ g_value_set_ulong (value, entry->private_dirty);
+ break;
+ }
+}
+
+static gboolean
+procmap_store_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ ProcmapStore *self = (ProcmapStore *) tree_model;
+ guint index = GPOINTER_TO_UINT (iter->user_data2);
+
+ if (++index >= self->procmap.number)
+ return FALSE;
+
+ iter->user_data = &self->maps[index];
+ iter->user_data2 = GUINT_TO_POINTER (index);
+ return TRUE;
+}
+
+static gboolean
+procmap_store_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ return parent == NULL;
+}
+
+static gboolean
+procmap_store_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static gint
+procmap_store_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ return 0;
+}
+
+static gboolean
+procmap_store_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n)
+{
+ ProcmapStore *self = (ProcmapStore *) tree_model;
+
+ if (parent != NULL)
+ return FALSE;
+
+ if ((guint) n >= self->procmap.number)
+ return FALSE;
+
+ iter->stamp = 1;
+ iter->user_data = &self->maps[n];
+ iter->user_data2 = GUINT_TO_POINTER (n);
+ return TRUE;
+}
+
+static gboolean
+procmap_store_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static void
+procmap_store_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = procmap_store_get_flags;
+ iface->get_n_columns = procmap_store_get_n_columns;
+ iface->get_column_type = procmap_store_get_column_type;
+ iface->get_iter = procmap_store_get_iter;
+ iface->get_path = procmap_store_get_path;
+ iface->get_value = procmap_store_get_value;
+ iface->iter_next = procmap_store_iter_next;
+ iface->iter_children = procmap_store_iter_children;
+ iface->iter_has_child = procmap_store_iter_has_child;
+ iface->iter_n_children = procmap_store_iter_n_children;
+ iface->iter_nth_child = procmap_store_iter_nth_child;
+ iface->iter_parent = procmap_store_iter_parent;
+}
+
+static gint
+procmap_store_sort_by_dirty (gconstpointer A, gconstpointer B)
+{
+ const glibtop_map_entry *a = A, *b = B;
+ return b->private_dirty - a->private_dirty;
+}
+
+static void
+procmap_store_init (ProcmapStore *self)
+{
+ self->sort_func = procmap_store_sort_by_dirty;
+}
+
+
+void
+procmap_store_update (ProcmapStore *self, GPid pid)
+{
+ g_free (self->maps);
+
+ self->pid = pid;
+ self->maps = glibtop_get_proc_map (&self->procmap, (pid_t) pid);
+
+ qsort (self->maps,
+ self->procmap.number, sizeof (glibtop_map_entry),
+ self->sort_func);
+}
+
+GtkTreeModel *
+procmap_store_new (GPid pid)
+{
+ ProcmapStore *self;
+
+ self = g_object_new (procmap_store_get_type (), NULL);
+ if (pid)
+ procmap_store_update (self, pid);
+
+ return (GtkTreeModel *) self;
+}