perf annotate: Fix up usage of the build id cache
[safe/jmp/linux-2.6] / tools / perf / builtin-report.c
index 3a70c58..a7b8760 100644 (file)
@@ -39,21 +39,22 @@ static bool         dont_use_callchains;
 static bool            show_threads;
 static struct perf_read_values show_threads_values;
 
-static char            default_pretty_printing_style[] = "normal";
-static char            *pretty_printing_style = default_pretty_printing_style;
+static const char      default_pretty_printing_style[] = "normal";
+static const char      *pretty_printing_style = default_pretty_printing_style;
 
 static char            callchain_default_opt[] = "fractal,0.5";
 
-static struct event_stat_id *get_stats(struct perf_session *self,
-                                      u64 event_stream, u32 type, u64 config)
+static struct hists *perf_session__hists_findnew(struct perf_session *self,
+                                                u64 event_stream, u32 type,
+                                                u64 config)
 {
-       struct rb_node **p = &self->stats_by_id.rb_node;
+       struct rb_node **p = &self->hists_tree.rb_node;
        struct rb_node *parent = NULL;
-       struct event_stat_id *iter, *new;
+       struct hists *iter, *new;
 
        while (*p != NULL) {
                parent = *p;
-               iter = rb_entry(parent, struct event_stat_id, rb_node);
+               iter = rb_entry(parent, struct hists, rb_node);
                if (iter->config == config)
                        return iter;
 
@@ -64,15 +65,15 @@ static struct event_stat_id *get_stats(struct perf_session *self,
                        p = &(*p)->rb_left;
        }
 
-       new = malloc(sizeof(struct event_stat_id));
+       new = malloc(sizeof(struct hists));
        if (new == NULL)
                return NULL;
-       memset(new, 0, sizeof(struct event_stat_id));
+       memset(new, 0, sizeof(struct hists));
        new->event_stream = event_stream;
        new->config = config;
        new->type = type;
        rb_link_node(&new->rb_node, parent, p);
-       rb_insert_color(&new->rb_node, &self->stats_by_id);
+       rb_insert_color(&new->rb_node, &self->hists_tree);
        return new;
 }
 
@@ -82,10 +83,9 @@ static int perf_session__add_hist_entry(struct perf_session *self,
 {
        struct map_symbol *syms = NULL;
        struct symbol *parent = NULL;
-       bool hit;
        int err = -ENOMEM;
        struct hist_entry *he;
-       struct event_stat_id *stats;
+       struct hists *hists;
        struct perf_event_attr *attr;
 
        if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) {
@@ -97,25 +97,27 @@ static int perf_session__add_hist_entry(struct perf_session *self,
 
        attr = perf_header__find_attr(data->id, &self->header);
        if (attr)
-               stats = get_stats(self, data->id, attr->type, attr->config);
+               hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config);
        else
-               stats = get_stats(self, data->id, 0, 0);
-       if (stats == NULL)
+               hists = perf_session__hists_findnew(self, data->id, 0, 0);
+       if (hists == NULL)
                goto out_free_syms;
-       he = __perf_session__add_hist_entry(&stats->hists, al, parent,
-                                           data->period, &hit);
+       he = __hists__add_entry(hists, al, parent, data->period);
        if (he == NULL)
                goto out_free_syms;
-
-       if (hit)
-               __perf_session__add_count(he, al,  data->period);
-
        err = 0;
        if (symbol_conf.use_callchain) {
-               if (!hit)
-                       callchain_init(he->callchain);
                err = append_chain(he->callchain, data->callchain, syms);
+               if (err)
+                       goto out_free_syms;
        }
+       /*
+        * Only in the newt browser we are doing integrated annotation,
+        * so we don't allocated the extra space needed because the stdio
+        * code will not use it.
+        */
+       if (use_browser > 0)
+               err = hist_entry__inc_addr_samples(he, al->addr);
 out_free_syms:
        free(syms);
        return err;
@@ -125,18 +127,25 @@ static int add_event_total(struct perf_session *session,
                           struct sample_data *data,
                           struct perf_event_attr *attr)
 {
-       struct event_stat_id *stats;
+       struct hists *hists;
 
        if (attr)
-               stats = get_stats(session, data->id, attr->type, attr->config);
+               hists = perf_session__hists_findnew(session, data->id,
+                                                   attr->type, attr->config);
        else
-               stats = get_stats(session, data->id, 0, 0);
+               hists = perf_session__hists_findnew(session, data->id, 0, 0);
 
-       if (!stats)
+       if (!hists)
                return -ENOMEM;
 
-       stats->stats.total += data->period;
-       session->events_stats.total += data->period;
+       hists->stats.total_period += data->period;
+       /*
+        * FIXME: add_event_total should be moved from here to
+        * perf_session__process_event so that the proper hist is passed to
+        * the event_op methods.
+        */
+       hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
+       session->hists.stats.total_period += data->period;
        return 0;
 }
 
@@ -179,14 +188,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
                return 0;
 
        if (perf_session__add_hist_entry(session, &al, &data)) {
-               pr_debug("problem incrementing symbol count, skipping event\n");
+               pr_debug("problem incrementing symbol period, skipping event\n");
                return -1;
        }
 
        attr = perf_header__find_attr(data.id, &session->header);
 
        if (add_event_total(session, &data, attr)) {
-               pr_debug("problem adding event count\n");
+               pr_debug("problem adding event period\n");
                return -1;
        }
 
@@ -260,11 +269,25 @@ static struct perf_event_ops event_ops = {
 
 extern volatile int session_done;
 
-static void sig_handler(int sig __attribute__((__unused__)))
+static void sig_handler(int sig __used)
 {
        session_done = 1;
 }
 
+static size_t hists__fprintf_nr_sample_events(struct hists *self,
+                                             const char *evname, FILE *fp)
+{
+       size_t ret;
+       char unit;
+       unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
+
+       nr_events = convert_unit(nr_events, &unit);
+       ret = fprintf(fp, "# Events: %lu%c", nr_events, unit);
+       if (evname != NULL)
+               ret += fprintf(fp, " %s", evname);
+       return ret + fprintf(fp, "\n#\n");
+}
+
 static int __cmd_report(void)
 {
        int ret = -EINVAL;
@@ -290,7 +313,7 @@ static int __cmd_report(void)
                goto out_delete;
 
        if (dump_trace) {
-               event__print_totals();
+               perf_session__fprintf_nr_events(session, stdout);
                goto out_delete;
        }
 
@@ -300,38 +323,31 @@ static int __cmd_report(void)
        if (verbose > 2)
                perf_session__fprintf_dsos(session, stdout);
 
-       next = rb_first(&session->stats_by_id);
+       next = rb_first(&session->hists_tree);
        while (next) {
-               struct event_stat_id *stats;
-               u64 nr_hists;
-
-               stats = rb_entry(next, struct event_stat_id, rb_node);
-               perf_session__collapse_resort(&stats->hists);
-               nr_hists = perf_session__output_resort(&stats->hists,
-                                                      stats->stats.total);
-               if (use_browser)
-                       perf_session__browse_hists(&stats->hists, nr_hists,
-                                                  stats->stats.total, help,
-                                                  input_name);
+               struct hists *hists;
+
+               hists = rb_entry(next, struct hists, rb_node);
+               hists__collapse_resort(hists);
+               hists__output_resort(hists);
+               if (use_browser > 0)
+                       hists__browse(hists, help, input_name);
                else {
-                       if (rb_first(&session->stats_by_id) ==
-                           rb_last(&session->stats_by_id))
-                               fprintf(stdout, "# Samples: %Ld\n#\n",
-                                       stats->stats.total);
-                       else
-                               fprintf(stdout, "# Samples: %Ld %s\n#\n",
-                                       stats->stats.total,
-                                       __event_name(stats->type, stats->config));
-
-                       perf_session__fprintf_hists(&stats->hists, NULL, false, stdout,
-                                           stats->stats.total);
+                       const char *evname = NULL;
+                       if (rb_first(&session->hists.entries) !=
+                           rb_last(&session->hists.entries))
+                               evname = __event_name(hists->type, hists->config);
+
+                       hists__fprintf_nr_sample_events(hists, evname, stdout);
+
+                       hists__fprintf(hists, NULL, false, stdout);
                        fprintf(stdout, "\n\n");
                }
 
-               next = rb_next(&stats->rb_node);
+               next = rb_next(&hists->rb_node);
        }
 
-       if (!use_browser && sort_order == default_sort_order &&
+       if (use_browser <= 0 && sort_order == default_sort_order &&
            parent_pattern == default_parent_pattern) {
                fprintf(stdout, "#\n# (%s)\n#\n", help);
 
@@ -351,7 +367,7 @@ static int
 parse_callchain_opt(const struct option *opt __used, const char *arg,
                    int unset)
 {
-       char *tok;
+       char *tok, *tok2;
        char *endptr;
 
        /*
@@ -396,10 +412,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
        if (!tok)
                goto setup;
 
+       tok2 = strtok(NULL, ",");
        callchain_param.min_percent = strtod(tok, &endptr);
        if (tok == endptr)
                return -1;
 
+       if (tok2)
+               callchain_param.print_limit = strtod(tok2, &endptr);
 setup:
        if (register_callchain_param(&callchain_param) < 0) {
                fprintf(stderr, "Can't register callchain params\n");
@@ -467,6 +486,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 
        if (strcmp(input_name, "-") != 0)
                setup_browser();
+       /*
+        * Only in the newt browser we are doing integrated annotation,
+        * so don't allocate extra space that won't be used in the stdio
+        * implementation.
+        */
+       if (use_browser > 0)
+               symbol_conf.priv_size = sizeof(struct sym_priv);
 
        if (symbol__init() < 0)
                return -1;