perf cpumap: Add new map type for aggregation
[linux-2.6-microblaze.git] / tools / perf / util / block-info.c
index fbbb6d6..423ec69 100644 (file)
@@ -65,8 +65,7 @@ struct block_info *block_info__new(void)
        return bi;
 }
 
-int64_t block_info__cmp(struct perf_hpp_fmt *fmt __maybe_unused,
-                       struct hist_entry *left, struct hist_entry *right)
+int64_t __block_info__cmp(struct hist_entry *left, struct hist_entry *right)
 {
        struct block_info *bi_l = left->block_info;
        struct block_info *bi_r = right->block_info;
@@ -74,30 +73,27 @@ int64_t block_info__cmp(struct perf_hpp_fmt *fmt __maybe_unused,
 
        if (!bi_l->sym || !bi_r->sym) {
                if (!bi_l->sym && !bi_r->sym)
-                       return 0;
+                       return -1;
                else if (!bi_l->sym)
                        return -1;
                else
                        return 1;
        }
 
-       if (bi_l->sym == bi_r->sym) {
-               if (bi_l->start == bi_r->start) {
-                       if (bi_l->end == bi_r->end)
-                               return 0;
-                       else
-                               return (int64_t)(bi_r->end - bi_l->end);
-               } else
-                       return (int64_t)(bi_r->start - bi_l->start);
-       } else {
-               cmp = strcmp(bi_l->sym->name, bi_r->sym->name);
+       cmp = strcmp(bi_l->sym->name, bi_r->sym->name);
+       if (cmp)
                return cmp;
-       }
 
-       if (bi_l->sym->start != bi_r->sym->start)
-               return (int64_t)(bi_r->sym->start - bi_l->sym->start);
+       if (bi_l->start != bi_r->start)
+               return (int64_t)(bi_r->start - bi_l->start);
 
-       return (int64_t)(bi_r->sym->end - bi_l->sym->end);
+       return (int64_t)(bi_r->end - bi_l->end);
+}
+
+int64_t block_info__cmp(struct perf_hpp_fmt *fmt __maybe_unused,
+                       struct hist_entry *left, struct hist_entry *right)
+{
+       return __block_info__cmp(left, right);
 }
 
 static void init_block_info(struct block_info *bi, struct symbol *sym,
@@ -185,6 +181,17 @@ static int block_column_width(struct perf_hpp_fmt *fmt,
        return block_fmt->width;
 }
 
+static int color_pct(struct perf_hpp *hpp, int width, double pct)
+{
+#ifdef HAVE_SLANG_SUPPORT
+       if (use_browser) {
+               return __hpp__slsmg_color_printf(hpp, "%*.2f%%",
+                                                width - 1, pct);
+       }
+#endif
+       return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, pct);
+}
+
 static int block_total_cycles_pct_entry(struct perf_hpp_fmt *fmt,
                                        struct perf_hpp *hpp,
                                        struct hist_entry *he)
@@ -192,14 +199,11 @@ static int block_total_cycles_pct_entry(struct perf_hpp_fmt *fmt,
        struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
        struct block_info *bi = he->block_info;
        double ratio = 0.0;
-       char buf[16];
 
        if (block_fmt->total_cycles)
                ratio = (double)bi->cycles / (double)block_fmt->total_cycles;
 
-       sprintf(buf, "%.2f%%", 100.0 * ratio);
-
-       return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, buf);
+       return color_pct(hpp, block_fmt->width, 100.0 * ratio);
 }
 
 static int64_t block_total_cycles_pct_sort(struct perf_hpp_fmt *fmt,
@@ -252,16 +256,13 @@ static int block_cycles_pct_entry(struct perf_hpp_fmt *fmt,
        struct block_info *bi = he->block_info;
        double ratio = 0.0;
        u64 avg;
-       char buf[16];
 
        if (block_fmt->block_cycles && bi->num_aggr) {
                avg = bi->cycles_aggr / bi->num_aggr;
                ratio = (double)avg / (double)block_fmt->block_cycles;
        }
 
-       sprintf(buf, "%.2f%%", 100.0 * ratio);
-
-       return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, buf);
+       return color_pct(hpp, block_fmt->width, 100.0 * ratio);
 }
 
 static int block_avg_cycles_entry(struct perf_hpp_fmt *fmt,
@@ -349,7 +350,7 @@ static void hpp_register(struct block_fmt *block_fmt, int idx,
 
        switch (idx) {
        case PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT:
-               fmt->entry = block_total_cycles_pct_entry;
+               fmt->color = block_total_cycles_pct_entry;
                fmt->cmp = block_info__cmp;
                fmt->sort = block_total_cycles_pct_sort;
                break;
@@ -357,7 +358,7 @@ static void hpp_register(struct block_fmt *block_fmt, int idx,
                fmt->entry = block_cycles_lbr_entry;
                break;
        case PERF_HPP_REPORT__BLOCK_CYCLES_PCT:
-               fmt->entry = block_cycles_pct_entry;
+               fmt->color = block_cycles_pct_entry;
                break;
        case PERF_HPP_REPORT__BLOCK_AVG_CYCLES:
                fmt->entry = block_avg_cycles_entry;
@@ -377,33 +378,41 @@ static void hpp_register(struct block_fmt *block_fmt, int idx,
 }
 
 static void register_block_columns(struct perf_hpp_list *hpp_list,
-                                  struct block_fmt *block_fmts)
+                                  struct block_fmt *block_fmts,
+                                  int *block_hpps, int nr_hpps)
 {
-       for (int i = 0; i < PERF_HPP_REPORT__BLOCK_MAX_INDEX; i++)
-               hpp_register(&block_fmts[i], i, hpp_list);
+       for (int i = 0; i < nr_hpps; i++)
+               hpp_register(&block_fmts[i], block_hpps[i], hpp_list);
 }
 
-static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts)
+static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts,
+                           int *block_hpps, int nr_hpps)
 {
        __hists__init(&bh->block_hists, &bh->block_list);
        perf_hpp_list__init(&bh->block_list);
        bh->block_list.nr_header_lines = 1;
 
-       register_block_columns(&bh->block_list, block_fmts);
+       register_block_columns(&bh->block_list, block_fmts,
+                              block_hpps, nr_hpps);
 
-       perf_hpp_list__register_sort_field(&bh->block_list,
-               &block_fmts[PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT].fmt);
+       /* Sort by the first fmt */
+       perf_hpp_list__register_sort_field(&bh->block_list, &block_fmts[0].fmt);
 }
 
-static void process_block_report(struct hists *hists,
-                                struct block_report *block_report,
-                                u64 total_cycles)
+static int process_block_report(struct hists *hists,
+                               struct block_report *block_report,
+                               u64 total_cycles, int *block_hpps,
+                               int nr_hpps)
 {
        struct rb_node *next = rb_first_cached(&hists->entries);
        struct block_hist *bh = &block_report->hist;
        struct hist_entry *he;
 
-       init_block_hist(bh, block_report->fmts);
+       if (nr_hpps > PERF_HPP_REPORT__BLOCK_MAX_INDEX)
+               return -1;
+
+       block_report->nr_fmts = nr_hpps;
+       init_block_hist(bh, block_report->fmts, block_hpps, nr_hpps);
 
        while (next) {
                he = rb_entry(next, struct hist_entry, rb_node);
@@ -412,16 +421,19 @@ static void process_block_report(struct hists *hists,
                next = rb_next(&he->rb_node);
        }
 
-       for (int i = 0; i < PERF_HPP_REPORT__BLOCK_MAX_INDEX; i++) {
+       for (int i = 0; i < nr_hpps; i++) {
                block_report->fmts[i].total_cycles = total_cycles;
                block_report->fmts[i].block_cycles = block_report->cycles;
        }
 
        hists__output_resort(&bh->block_hists, NULL);
+       return 0;
 }
 
 struct block_report *block_info__create_report(struct evlist *evlist,
-                                              u64 total_cycles)
+                                              u64 total_cycles,
+                                              int *block_hpps, int nr_hpps,
+                                              int *nr_reps)
 {
        struct block_report *block_reports;
        int nr_hists = evlist->core.nr_entries, i = 0;
@@ -434,13 +446,23 @@ struct block_report *block_info__create_report(struct evlist *evlist,
        evlist__for_each_entry(evlist, pos) {
                struct hists *hists = evsel__hists(pos);
 
-               process_block_report(hists, &block_reports[i], total_cycles);
+               process_block_report(hists, &block_reports[i], total_cycles,
+                                    block_hpps, nr_hpps);
                i++;
        }
 
+       *nr_reps = nr_hists;
        return block_reports;
 }
 
+void block_info__free_report(struct block_report *reps, int nr_reps)
+{
+       for (int i = 0; i < nr_reps; i++)
+               hists__delete_entries(&reps[i].hist.block_hists);
+
+       free(reps);
+}
+
 int report__browse_block_hists(struct block_hist *bh, float min_percent,
                               struct evsel *evsel, struct perf_env *env,
                               struct annotation_options *annotation_opts)
@@ -452,13 +474,11 @@ int report__browse_block_hists(struct block_hist *bh, float min_percent,
                symbol_conf.report_individual_block = true;
                hists__fprintf(&bh->block_hists, true, 0, 0, min_percent,
                               stdout, true);
-               hists__delete_entries(&bh->block_hists);
                return 0;
        case 1:
                symbol_conf.report_individual_block = true;
                ret = block_hists_tui_browse(bh, evsel, min_percent,
                                             env, annotation_opts);
-               hists__delete_entries(&bh->block_hists);
                return ret;
        default:
                return -1;