diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-11-29 15:19:57 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-11-29 15:19:57 +0000 |
commit | a52c32123d772ba317a8a26b60b321fa3790b969 (patch) | |
tree | 4b3a4720e937cdaab91a27bd3f5e5fbcb1842868 /src/procmap-store.c | |
parent | 37e5ae98be10037b8e123aac0fbba704494eb9f9 (diff) |
Quick and dirty smap info using libgtop.
Diffstat (limited to 'src/procmap-store.c')
-rw-r--r-- | src/procmap-store.c | 295 |
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; +} |