if (self != NULL) {
self->pid = pid;
- self->comm = malloc(30);
+ self->comm = malloc(32);
if (self->comm)
- sprintf(self->comm, ":%d", pid);
+ snprintf(self->comm, 32, ":%d", self->pid);
INIT_LIST_HEAD(&self->maps);
}
static int thread__set_comm(struct thread *self, const char *comm)
{
+ if (self->comm)
+ free(self->comm);
self->comm = strdup(comm);
return self->comm ? 0 : -ENOMEM;
}
char *header;
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
+ int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
size_t (*print)(FILE *fp, struct hist_entry *);
};
+/* --sort pid */
+
static int64_t
sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
{
.print = sort__thread_print,
};
+/* --sort comm */
+
static int64_t
sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ return right->thread->pid - left->thread->pid;
+}
+
+static int64_t
+sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
{
char *comm_l = left->thread->comm;
char *comm_r = right->thread->comm;
}
static struct sort_entry sort_comm = {
- .header = " Command",
- .cmp = sort__comm_cmp,
- .print = sort__comm_print,
+ .header = " Command",
+ .cmp = sort__comm_cmp,
+ .collapse = sort__comm_collapse,
+ .print = sort__comm_print,
};
+/* --sort dso */
+
static int64_t
sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
{
.print = sort__dso_print,
};
+/* --sort symbol */
+
static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
.print = sort__sym_print,
};
+static int sort__need_collapse = 0;
+
struct sort_dimension {
char *name;
struct sort_entry *entry;
if (strncasecmp(tok, sd->name, strlen(tok)))
continue;
+ if (sd->entry->collapse)
+ sort__need_collapse = 1;
+
list_add_tail(&sd->entry->list, &hist_entry__sort_list);
sd->taken = 1;
return cmp;
}
+static int64_t
+hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
+{
+ struct sort_entry *se;
+ int64_t cmp = 0;
+
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ int64_t (*f)(struct hist_entry *, struct hist_entry *);
+
+ f = se->collapse ?: se->cmp;
+
+ cmp = f(left, right);
+ if (cmp)
+ break;
+ }
+
+ return cmp;
+}
+
static size_t
hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
{
return 0;
}
+static void hist_entry__free(struct hist_entry *he)
+{
+ free(he);
+}
+
+/*
+ * collapse the histogram
+ */
+
+static struct rb_root collapse_hists;
+
+static void collapse__insert_entry(struct hist_entry *he)
+{
+ struct rb_node **p = &collapse_hists.rb_node;
+ struct rb_node *parent = NULL;
+ struct hist_entry *iter;
+ int64_t cmp;
+
+ while (*p != NULL) {
+ parent = *p;
+ iter = rb_entry(parent, struct hist_entry, rb_node);
+
+ cmp = hist_entry__collapse(iter, he);
+
+ if (!cmp) {
+ iter->count += he->count;
+ hist_entry__free(he);
+ return;
+ }
+
+ if (cmp < 0)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, &collapse_hists);
+}
+
+static void collapse__resort(void)
+{
+ struct rb_node *next;
+ struct hist_entry *n;
+
+ if (!sort__need_collapse)
+ return;
+
+ next = rb_first(&hist);
+ while (next) {
+ n = rb_entry(next, struct hist_entry, rb_node);
+ next = rb_next(&n->rb_node);
+
+ rb_erase(&n->rb_node, &hist);
+ collapse__insert_entry(n);
+ }
+}
+
/*
* reverse the map, sort on count.
*/
static void output__resort(void)
{
- struct rb_node *next = rb_first(&hist);
+ struct rb_node *next;
struct hist_entry *n;
+ if (sort__need_collapse)
+ next = rb_first(&collapse_hists);
+ else
+ next = rb_first(&hist);
+
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node);
if (verbose >= 2)
dsos__fprintf(stdout);
+ collapse__resort();
output__resort();
output__fprintf(stdout, total);