From 01441af5df438a171bce36bc3c7cfb588bc98a7a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:23:59 +0100 Subject: perf hists: Factor output_resort from hists__output_resort Currently hists__output_resort() depends on hists based on hists_evsel struct, but we need to be able to sort common hists as well. Cutting out the sorting base sorting code into output_resort function, so it can be reused in following patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 098310b..7797d06 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1197,19 +1197,13 @@ static void __hists__insert_output_entry(struct rb_root *entries, rb_insert_color(&he->rb_node, entries); } -void hists__output_resort(struct hists *hists, struct ui_progress *prog) +static void output_resort(struct hists *hists, struct ui_progress *prog, + bool use_callchain) { struct rb_root *root; struct rb_node *next; struct hist_entry *n; u64 min_callchain_hits; - struct perf_evsel *evsel = hists_to_evsel(hists); - bool use_callchain; - - if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) - use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; - else - use_callchain = symbol_conf.use_callchain; min_callchain_hits = hists__total_period(hists) * (callchain_param.min_percent / 100); @@ -1239,6 +1233,19 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) } } +void hists__output_resort(struct hists *hists, struct ui_progress *prog) +{ + struct perf_evsel *evsel = hists_to_evsel(hists); + bool use_callchain; + + if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) + use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; + else + use_callchain = symbol_conf.use_callchain; + + output_resort(hists, prog, use_callchain); +} + static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, enum hist_filter filter) { -- cgit v0.10.2 From 452ce03b1e686f0b2da6c1644dce7cdc71e3c69c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:00 +0100 Subject: perf hists: Introduce perf_evsel__output_resort function Adding evsel specific function to sort hists_evsel based hists. The hists__output_resort can be now used to sort common hists object. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cc5c126..cfe3663 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -245,7 +245,7 @@ static int __cmd_annotate(struct perf_annotate *ann) hists__collapse_resort(hists, NULL); /* Don't sort callchain */ perf_evsel__reset_sample_bit(pos, CALLCHAIN); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(pos, NULL); if (symbol_conf.event_group && !perf_evsel__is_group_leader(pos)) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 72ed0b4..54ce047 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -507,7 +507,7 @@ static void report__output_resort(struct report *rep) ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); evlist__for_each(rep->session->evlist, pos) - hists__output_resort(evsel__hists(pos), &prog); + perf_evsel__output_resort(pos, &prog); ui_progress__finish(); } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index bf01cbb..f1bbe2a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -252,7 +252,8 @@ static void perf_top__print_sym_table(struct perf_top *top) char bf[160]; int printed = 0; const int win_width = top->winsize.ws_col - 1; - struct hists *hists = evsel__hists(top->sym_evsel); + struct perf_evsel *evsel = top->sym_evsel; + struct hists *hists = evsel__hists(evsel); puts(CONSOLE_CLEAR); @@ -288,7 +289,7 @@ static void perf_top__print_sym_table(struct perf_top *top) } hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); hists__output_recalc_col_len(hists, top->print_entries - printed); putchar('\n'); @@ -540,6 +541,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) static void perf_top__sort_new_samples(void *arg) { struct perf_top *t = arg; + struct perf_evsel *evsel = t->sym_evsel; struct hists *hists; perf_top__reset_sample_counters(t); @@ -547,7 +549,7 @@ static void perf_top__sort_new_samples(void *arg) if (t->evlist->selected != NULL) t->sym_evsel = t->evlist->selected; - hists = evsel__hists(t->sym_evsel); + hists = evsel__hists(evsel); if (t->evlist->enabled) { if (t->zero) { @@ -559,7 +561,7 @@ static void perf_top__sort_new_samples(void *arg) } hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); } static void *display_thread_tui(void *arg) diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 5e6a86e..ecf136c 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -191,7 +191,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec * function since TEST_ASSERT_VAL() returns in case of failure. */ hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(hists_to_evsel(hists), NULL); if (verbose > 2) { pr_info("use callchain: %d, cumulate callchain: %d\n", diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 351a424..34b945a 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -145,7 +145,7 @@ int test__hists_filter(int subtest __maybe_unused) struct hists *hists = evsel__hists(evsel); hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("Normal histogram\n"); diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index b231265..23cce67 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -156,7 +156,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -256,7 +256,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -310,7 +310,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -388,7 +388,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -491,7 +491,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 7797d06..d07955c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1233,9 +1233,8 @@ static void output_resort(struct hists *hists, struct ui_progress *prog, } } -void hists__output_resort(struct hists *hists, struct ui_progress *prog) +void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog) { - struct perf_evsel *evsel = hists_to_evsel(hists); bool use_callchain; if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) @@ -1243,7 +1242,12 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) else use_callchain = symbol_conf.use_callchain; - output_resort(hists, prog, use_callchain); + output_resort(evsel__hists(evsel), prog, use_callchain); +} + +void hists__output_resort(struct hists *hists, struct ui_progress *prog) +{ + output_resort(hists, prog, symbol_conf.use_callchain); } static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d4ec482..bc24997 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -128,6 +128,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, struct hists *hists); void hist_entry__delete(struct hist_entry *he); +void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); void hists__output_resort(struct hists *hists, struct ui_progress *prog); void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); -- cgit v0.10.2 From b21a763edd5f832c6d966d9e60376f3d21009859 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:01 +0100 Subject: perf hists: Add _idx fields into struct perf_hpp_fmt Currently there's no way of comparing hpp format entries, which is needed in following patches. Adding _idx fields into struct perf_hpp_fmt to recognize and be able to compare hpp format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index bf2a66e..d392801 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -371,7 +371,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, return 0; } -#define HPP__COLOR_PRINT_FNS(_name, _fn) \ +#define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -381,9 +381,10 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } -#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \ +#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -393,9 +394,10 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } -#define HPP__PRINT_FNS(_name, _fn) \ +#define HPP__PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -404,17 +406,18 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } struct perf_hpp_fmt perf_hpp__format[] = { - HPP__COLOR_PRINT_FNS("Overhead", overhead), - HPP__COLOR_PRINT_FNS("sys", overhead_sys), - HPP__COLOR_PRINT_FNS("usr", overhead_us), - HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys), - HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us), - HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc), - HPP__PRINT_FNS("Samples", samples), - HPP__PRINT_FNS("Period", period) + HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD), + HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS), + HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US), + HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS), + HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US), + HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC), + HPP__PRINT_FNS("Samples", samples, SAMPLES), + HPP__PRINT_FNS("Period", period, PERIOD) }; LIST_HEAD(perf_hpp__list); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bc24997..8a0cbde 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -221,6 +221,7 @@ struct perf_hpp_fmt { bool elide; int len; int user_len; + int idx; }; extern struct list_head perf_hpp__list; -- cgit v0.10.2 From 2e8b79e706f504801fbce19fa9f16f3c858a105e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:02 +0100 Subject: perf hists: Use struct perf_hpp_fmt::idx in perf_hpp__reset_width We are going to add dynamic hpp format fields, so we need to make the 'len' change for the format itself, not in the perf_hpp__format template. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index d392801..5a11bf0 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -629,20 +629,12 @@ unsigned int hists__sort_list_width(struct hists *hists) void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) { - int idx; - if (perf_hpp__is_sort_entry(fmt)) return perf_hpp__reset_sort_width(fmt, hists); - for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { - if (fmt == &perf_hpp__format[idx]) - break; - } - - if (idx == PERF_HPP__MAX_INDEX) - return; + BUG_ON(fmt->idx >= PERF_HPP__MAX_INDEX); - switch (idx) { + switch (fmt->idx) { case PERF_HPP__OVERHEAD: case PERF_HPP__OVERHEAD_SYS: case PERF_HPP__OVERHEAD_US: -- cgit v0.10.2 From 97358084b91e94e5f8fcf0379f0430c0ea16bd3b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:03 +0100 Subject: perf hists: Add 'equal' method to perf_hpp_fmt struct To easily compare format entries and make it available for all kinds of format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 5a11bf0..71c8bb7 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -524,6 +524,11 @@ void perf_hpp__cancel_cumulate(void) perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead"; } +static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + return a->equal && a->equal(a, b); +} + void perf_hpp__setup_output_field(void) { struct perf_hpp_fmt *fmt; @@ -542,7 +547,7 @@ void perf_hpp__setup_output_field(void) struct perf_hpp_fmt *pos; perf_hpp__for_each_format(pos) { - if (perf_hpp__same_sort_entry(pos, fmt)) + if (fmt_equal(fmt, pos)) goto next; } } @@ -571,7 +576,7 @@ void perf_hpp__append_sort_keys(void) struct perf_hpp_fmt *pos; perf_hpp__for_each_sort_list(pos) { - if (perf_hpp__same_sort_entry(pos, fmt)) + if (fmt_equal(fmt, pos)) goto next; } } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 8a0cbde..9a240d7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -215,6 +215,7 @@ struct perf_hpp_fmt { struct hist_entry *a, struct hist_entry *b); int64_t (*sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b); + bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); struct list_head list; struct list_head sort_list; @@ -268,7 +269,6 @@ void perf_hpp__reset_output_field(void); void perf_hpp__append_sort_keys(void); bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); -bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format); bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 898e4b0..170f7f7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1441,20 +1441,6 @@ struct hpp_sort_entry { struct sort_entry *se; }; -bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) -{ - struct hpp_sort_entry *hse_a; - struct hpp_sort_entry *hse_b; - - if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) - return false; - - hse_a = container_of(a, struct hpp_sort_entry, hpp); - hse_b = container_of(b, struct hpp_sort_entry, hpp); - - return hse_a->se == hse_b->se; -} - void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists) { struct hpp_sort_entry *hse; @@ -1540,6 +1526,25 @@ static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt, return sort_fn(a, b); } +bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) +{ + return format->header == __sort__hpp_header; +} + +static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + struct hpp_sort_entry *hse_a; + struct hpp_sort_entry *hse_b; + + if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) + return false; + + hse_a = container_of(a, struct hpp_sort_entry, hpp); + hse_b = container_of(b, struct hpp_sort_entry, hpp); + + return hse_a->se == hse_b->se; +} + static struct hpp_sort_entry * __sort_dimension__alloc_hpp(struct sort_dimension *sd) { @@ -1561,6 +1566,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.cmp = __sort__hpp_cmp; hse->hpp.collapse = __sort__hpp_collapse; hse->hpp.sort = __sort__hpp_sort; + hse->hpp.equal = __sort__hpp_equal; INIT_LIST_HEAD(&hse->hpp.list); INIT_LIST_HEAD(&hse->hpp.sort_list); @@ -1571,11 +1577,6 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } -bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) -{ - return format->header == __sort__hpp_header; -} - static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); -- cgit v0.10.2 From c0020efa079c5fc2388945ae7e856b362731442d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:04 +0100 Subject: perf hists: Add 'hpp__equal' callback function Adding 'hpp__equal' callback function to compare hpp output format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 71c8bb7..b543f4b 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -371,6 +371,19 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, return 0; } +static bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a) +{ + return a->header == hpp__header_fn; +} + +static bool hpp__equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + if (!perf_hpp__is_hpp_entry(a) || !perf_hpp__is_hpp_entry(b)) + return false; + + return a->idx == b->idx; +} + #define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ @@ -382,6 +395,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } #define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \ @@ -395,6 +409,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } #define HPP__PRINT_FNS(_name, _fn, _idx) \ @@ -407,6 +422,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } struct perf_hpp_fmt perf_hpp__format[] = { -- cgit v0.10.2 From 3f931f2c4274565fd6c6a642b16387358cbe6266 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:05 +0100 Subject: perf hists: Make hpp setup function generic Now that we have the 'equal' method implemented for hpp format entries we can ease up the logic in the following functions and make them generic wrt comparing format entries: perf_hpp__setup_output_field perf_hpp__append_sort_keys Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b543f4b..b0fcaec 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -551,21 +551,11 @@ void perf_hpp__setup_output_field(void) /* append sort keys to output field */ perf_hpp__for_each_sort_list(fmt) { - if (!list_empty(&fmt->list)) - continue; + struct perf_hpp_fmt *pos; - /* - * sort entry fields are dynamically created, - * so they can share a same sort key even though - * the list is empty. - */ - if (perf_hpp__is_sort_entry(fmt)) { - struct perf_hpp_fmt *pos; - - perf_hpp__for_each_format(pos) { - if (fmt_equal(fmt, pos)) - goto next; - } + perf_hpp__for_each_format(pos) { + if (fmt_equal(fmt, pos)) + goto next; } perf_hpp__column_register(fmt); @@ -580,21 +570,11 @@ void perf_hpp__append_sort_keys(void) /* append output fields to sort keys */ perf_hpp__for_each_format(fmt) { - if (!list_empty(&fmt->sort_list)) - continue; + struct perf_hpp_fmt *pos; - /* - * sort entry fields are dynamically created, - * so they can share a same sort key even though - * the list is empty. - */ - if (perf_hpp__is_sort_entry(fmt)) { - struct perf_hpp_fmt *pos; - - perf_hpp__for_each_sort_list(pos) { - if (fmt_equal(fmt, pos)) - goto next; - } + perf_hpp__for_each_sort_list(pos) { + if (fmt_equal(fmt, pos)) + goto next; } perf_hpp__register_sort_field(fmt); -- cgit v0.10.2 From 9887804d01abf7a4e03cfd6be0312d0a5c4e4aba Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:06 +0100 Subject: perf report: Move UI initialization ahead of sort setup The ui initialization changes hpp format callbacks, based on the used browser. Thus we need this init being processed before setup_sorting. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 54ce047..1eab50a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -912,15 +912,6 @@ repeat: symbol_conf.cumulate_callchain = false; } - if (setup_sorting(session->evlist) < 0) { - if (sort_order) - parse_options_usage(report_usage, options, "s", 1); - if (field_order) - parse_options_usage(sort_order ? NULL : report_usage, - options, "F", 1); - goto error; - } - /* Force tty output for header output and per-thread stat. */ if (report.header || report.header_only || report.show_threads) use_browser = 0; @@ -930,6 +921,15 @@ repeat: else use_browser = 0; + if (setup_sorting(session->evlist) < 0) { + if (sort_order) + parse_options_usage(report_usage, options, "s", 1); + if (field_order) + parse_options_usage(sort_order ? NULL : report_usage, + options, "F", 1); + goto error; + } + if (report.header || report.header_only) { perf_session__fprintf_info(session, stdout, report.show_full_info); -- cgit v0.10.2 From 3ee60c3b18bd4bf30ea9b70e7542116bb5c205ba Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Jan 2016 10:24:06 +0100 Subject: perf top: Move UI initialization ahead of sort setup The ui initialization changes hpp format callbacks, based on the used browser. Thus we need this init being processed before setup_sorting. Replica of a patch by Jiri for 'perf report'. Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f1bbe2a..a75de39 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1245,6 +1245,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) /* display thread wants entries to be collapsed in a different tree */ sort__need_collapse = 1; + if (top.use_stdio) + use_browser = 0; + else if (top.use_tui) + use_browser = 1; + + setup_browser(false); + if (setup_sorting(top.evlist) < 0) { if (sort_order) parse_options_usage(top_usage, options, "s", 1); @@ -1254,13 +1261,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) goto out_delete_evlist; } - if (top.use_stdio) - use_browser = 0; - else if (top.use_tui) - use_browser = 1; - - setup_browser(false); - status = target__validate(target); if (status) { target__strerror(target, status, errbuf, BUFSIZ); -- cgit v0.10.2 From 1945c3e734cd1f01535dc76de47c38bbe9a87352 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:07 +0100 Subject: perf hists: Allocate output sort field Currently we use static output fields, because we have single global list of all sort/output fields. We will add hists specific sort and output lists in following patches, so we need all format entries to be dynamically allocated. Adding support to allocate output sort field. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-10-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b0fcaec..c877c52 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -533,11 +533,23 @@ void perf_hpp__column_disable(unsigned col) void perf_hpp__cancel_cumulate(void) { + struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; + if (is_strict_order(field_order)) return; - perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); - perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead"; + ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; + acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; + + perf_hpp__for_each_format_safe(fmt, tmp) { + if (acc->equal(acc, fmt)) { + perf_hpp__column_unregister(fmt); + continue; + } + + if (ovh->equal(ovh, fmt)) + fmt->name = "Overhead"; + } } static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 170f7f7..52e4a36 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1577,6 +1577,19 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } +static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) +{ + struct perf_hpp_fmt *fmt; + + fmt = memdup(hd->fmt, sizeof(*fmt)); + if (fmt) { + INIT_LIST_HEAD(&fmt->list); + INIT_LIST_HEAD(&fmt->sort_list); + } + + return fmt; +} + static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); @@ -2066,11 +2079,17 @@ static int __sort_dimension__add(struct sort_dimension *sd) static int __hpp_dimension__add(struct hpp_dimension *hd) { - if (!hd->taken) { - hd->taken = 1; + struct perf_hpp_fmt *fmt; - perf_hpp__register_sort_field(hd->fmt); - } + if (hd->taken) + return 0; + + fmt = __hpp_dimension__alloc_hpp(hd); + if (!fmt) + return -1; + + hd->taken = 1; + perf_hpp__register_sort_field(fmt); return 0; } @@ -2088,11 +2107,17 @@ static int __sort_dimension__add_output(struct sort_dimension *sd) static int __hpp_dimension__add_output(struct hpp_dimension *hd) { - if (!hd->taken) { - hd->taken = 1; + struct perf_hpp_fmt *fmt; - perf_hpp__column_register(hd->fmt); - } + if (hd->taken) + return 0; + + fmt = __hpp_dimension__alloc_hpp(hd); + if (!fmt) + return -1; + + hd->taken = 1; + perf_hpp__column_register(fmt); return 0; } -- cgit v0.10.2 From 12cb4397fb398545207acf772b219bd751786015 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:08 +0100 Subject: perf hists: Remove perf_hpp__column_(disable|enable) Those functions are no longer needed. They operate over perf_hpp__format array which is now used only as template for dynamic entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-11-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index c877c52..80d63a9 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -519,18 +519,6 @@ void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) list_add_tail(&format->sort_list, &perf_hpp__sort_list); } -void perf_hpp__column_enable(unsigned col) -{ - BUG_ON(col >= PERF_HPP__MAX_INDEX); - perf_hpp__column_register(&perf_hpp__format[col]); -} - -void perf_hpp__column_disable(unsigned col) -{ - BUG_ON(col >= PERF_HPP__MAX_INDEX); - perf_hpp__column_unregister(&perf_hpp__format[col]); -} - void perf_hpp__cancel_cumulate(void) { struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9a240d7..1f9e21dd 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -259,8 +259,6 @@ enum { void perf_hpp__init(void); void perf_hpp__column_register(struct perf_hpp_fmt *format); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); -void perf_hpp__column_enable(unsigned col); -void perf_hpp__column_disable(unsigned col); void perf_hpp__cancel_cumulate(void); void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); -- cgit v0.10.2 From 564132f3116cf376fdc04b2380e621f35efbb6c7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:09 +0100 Subject: perf hists: Properly release format fields With multiple list holding format entries, we need the support properly releasing format output/sort fields. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-12-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 80d63a9..2cd1a03 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -583,6 +583,12 @@ next: } } +static void fmt_free(struct perf_hpp_fmt *fmt) +{ + if (fmt->free) + fmt->free(fmt); +} + void perf_hpp__reset_output_field(void) { struct perf_hpp_fmt *fmt, *tmp; @@ -591,12 +597,14 @@ void perf_hpp__reset_output_field(void) perf_hpp__for_each_format_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } /* reset sort keys */ perf_hpp__for_each_sort_list_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1f9e21dd..f3bcf2d 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -216,6 +216,7 @@ struct perf_hpp_fmt { int64_t (*sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b); bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); + void (*free)(struct perf_hpp_fmt *fmt); struct list_head list; struct list_head sort_list; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 52e4a36..b5389a5 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1545,6 +1545,14 @@ static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) return hse_a->se == hse_b->se; } +static void hse_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_sort_entry *hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + free(hse); +} + static struct hpp_sort_entry * __sort_dimension__alloc_hpp(struct sort_dimension *sd) { @@ -1567,6 +1575,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.collapse = __sort__hpp_collapse; hse->hpp.sort = __sort__hpp_sort; hse->hpp.equal = __sort__hpp_equal; + hse->hpp.free = hse_free; INIT_LIST_HEAD(&hse->hpp.list); INIT_LIST_HEAD(&hse->hpp.sort_list); @@ -1577,6 +1586,11 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } +static void hpp_free(struct perf_hpp_fmt *fmt) +{ + free(fmt); +} + static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) { struct perf_hpp_fmt *fmt; @@ -1585,6 +1599,7 @@ static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) if (fmt) { INIT_LIST_HEAD(&fmt->list); INIT_LIST_HEAD(&fmt->sort_list); + fmt->free = hpp_free; } return fmt; @@ -1818,6 +1833,14 @@ bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt) return fmt->cmp == __sort__hde_cmp; } +static void hde_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_dynamic_entry *hde; + + hde = container_of(fmt, struct hpp_dynamic_entry, hpp); + free(hde); +} + static struct hpp_dynamic_entry * __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) { @@ -1842,6 +1865,7 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) hde->hpp.cmp = __sort__hde_cmp; hde->hpp.collapse = __sort__hde_cmp; hde->hpp.sort = __sort__hde_cmp; + hde->hpp.free = hde_free; INIT_LIST_HEAD(&hde->hpp.list); INIT_LIST_HEAD(&hde->hpp.sort_list); -- cgit v0.10.2 From 2fbaa39079672bf52a9208ec1263385b48933cc3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:10 +0100 Subject: perf hists: Separate sort fields parsing into setup_sort_list function Separating sort fields parsing into setup_sort_list function, so it's separated from sort_order string setup and could be reused later in following patches. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-13-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index b5389a5..ab1c21a 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2241,6 +2241,26 @@ static int sort_dimension__add(const char *tok, return -ESRCH; } +static int setup_sort_list(char *str, struct perf_evlist *evlist) +{ + char *tmp, *tok; + int ret = 0; + + for (tok = strtok_r(str, ", ", &tmp); + tok; tok = strtok_r(NULL, ", ", &tmp)) { + ret = sort_dimension__add(tok, evlist); + if (ret == -EINVAL) { + error("Invalid --sort key: `%s'", tok); + break; + } else if (ret == -ESRCH) { + error("Unknown --sort key: `%s'", tok); + break; + } + } + + return ret; +} + static const char *get_default_sort_order(struct perf_evlist *evlist) { const char *default_sort_orders[] = { @@ -2335,7 +2355,7 @@ static char *setup_overhead(char *keys) static int __setup_sorting(struct perf_evlist *evlist) { - char *tmp, *tok, *str; + char *str; const char *sort_keys; int ret = 0; @@ -2373,17 +2393,7 @@ static int __setup_sorting(struct perf_evlist *evlist) } } - for (tok = strtok_r(str, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = sort_dimension__add(tok, evlist); - if (ret == -EINVAL) { - error("Invalid --sort key: `%s'", tok); - break; - } else if (ret == -ESRCH) { - error("Unknown --sort key: `%s'", tok); - break; - } - } + ret = setup_sort_list(str, evlist); free(str); return ret; -- cgit v0.10.2 From 6d3375efebe906ad0ce55ddaa883bf41fd8c444b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:11 +0100 Subject: perf hists: Separate output fields parsing into setup_output_list function Separating output fields parsing into setup_output_list function, so it's separated from field_order string setup and could be reused later in following patches. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-14-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index ab1c21a..36dbd55 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2535,6 +2535,26 @@ static int output_field_add(char *tok) return -ESRCH; } +static int setup_output_list(char *str) +{ + char *tmp, *tok; + int ret = 0; + + for (tok = strtok_r(str, ", ", &tmp); + tok; tok = strtok_r(NULL, ", ", &tmp)) { + ret = output_field_add(tok); + if (ret == -EINVAL) { + error("Invalid --fields key: `%s'", tok); + break; + } else if (ret == -ESRCH) { + error("Unknown --fields key: `%s'", tok); + break; + } + } + + return ret; +} + static void reset_dimensions(void) { unsigned int i; @@ -2559,7 +2579,7 @@ bool is_strict_order(const char *order) static int __setup_output_field(void) { - char *tmp, *tok, *str, *strp; + char *str, *strp; int ret = -EINVAL; if (field_order == NULL) @@ -2579,17 +2599,7 @@ static int __setup_output_field(void) goto out; } - for (tok = strtok_r(strp, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = output_field_add(tok); - if (ret == -EINVAL) { - error("Invalid --fields key: `%s'", tok); - break; - } else if (ret == -ESRCH) { - error("Unknown --fields key: `%s'", tok); - break; - } - } + ret = setup_output_list(strp); out: free(str); -- cgit v0.10.2 From 7c31e10266bd18de163d5c60899591c0540bb002 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:12 +0100 Subject: perf hists: Introduce struct perf_hpp_list Gather output and sort lists under struct perf_hpp_list, so we could have multiple instancies of sort/output format entries. Replacing current perf_hpp__list and perf_hpp__sort_list lists with single perf_hpp_list instance. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-15-git-send-email-jolsa@kernel.org [ Renamed fields to .{fields,sorts} as suggested by Namhyung and acked by Jiri ] Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 2cd1a03..74dbeac 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -436,9 +436,10 @@ struct perf_hpp_fmt perf_hpp__format[] = { HPP__PRINT_FNS("Period", period, PERIOD) }; -LIST_HEAD(perf_hpp__list); -LIST_HEAD(perf_hpp__sort_list); - +struct perf_hpp_list perf_hpp_list = { + .fields = LIST_HEAD_INIT(perf_hpp_list.fields), + .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), +}; #undef HPP__COLOR_PRINT_FNS #undef HPP__COLOR_ACC_PRINT_FNS @@ -506,7 +507,7 @@ void perf_hpp__init(void) void perf_hpp__column_register(struct perf_hpp_fmt *format) { - list_add_tail(&format->list, &perf_hpp__list); + list_add_tail(&format->list, &perf_hpp_list.fields); } void perf_hpp__column_unregister(struct perf_hpp_fmt *format) @@ -516,7 +517,7 @@ void perf_hpp__column_unregister(struct perf_hpp_fmt *format) void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) { - list_add_tail(&format->sort_list, &perf_hpp__sort_list); + list_add_tail(&format->sort_list, &perf_hpp_list.sorts); } void perf_hpp__cancel_cumulate(void) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f3bcf2d..203397a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -226,20 +226,24 @@ struct perf_hpp_fmt { int idx; }; -extern struct list_head perf_hpp__list; -extern struct list_head perf_hpp__sort_list; +struct perf_hpp_list { + struct list_head fields; + struct list_head sorts; +}; + +extern struct perf_hpp_list perf_hpp_list; #define perf_hpp__for_each_format(format) \ - list_for_each_entry(format, &perf_hpp__list, list) + list_for_each_entry(format, &perf_hpp_list.fields, list) #define perf_hpp__for_each_format_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp__list, list) + list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) #define perf_hpp__for_each_sort_list(format) \ - list_for_each_entry(format, &perf_hpp__sort_list, sort_list) + list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) #define perf_hpp__for_each_sort_list_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp__sort_list, sort_list) + list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) extern struct perf_hpp_fmt perf_hpp__format[]; -- cgit v0.10.2 From 94b3dc3865097e11073f1abf5b20b5f80af223af Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:13 +0100 Subject: perf hists: Introduce perf_hpp_list__init function Introducing perf_hpp_list__init function to have an easy way to initialize perf_hpp_list struct. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-16-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index d07955c..b762ecc 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1642,3 +1642,9 @@ int hists__init(void) return err; } + +void perf_hpp_list__init(struct perf_hpp_list *list) +{ + INIT_LIST_HEAD(&list->fields); + INIT_LIST_HEAD(&list->sorts); +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 203397a..e22f98e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -386,4 +386,6 @@ int parse_filter_percentage(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused); int perf_hist_config(const char *var, const char *value); +void perf_hpp_list__init(struct perf_hpp_list *list); + #endif /* __PERF_HIST_H */ -- cgit v0.10.2 From ebdd98e030f5ed6dd1bae9ab01b084f97685bd60 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:14 +0100 Subject: perf hists: Add perf_hpp_list register helpers Adding 2 perf_hpp_list register helpers: perf_hpp_list__column_register() perf_hpp_list__register_sort_field() to be called within existing helpers: perf_hpp__column_register() perf_hpp__register_sort_field() to register format entries within global perf_hpp_list object. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-17-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 74dbeac..1655c0d 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -505,19 +505,21 @@ void perf_hpp__init(void) hpp_dimension__add_output(PERF_HPP__PERIOD); } -void perf_hpp__column_register(struct perf_hpp_fmt *format) +void perf_hpp_list__column_register(struct perf_hpp_list *list, + struct perf_hpp_fmt *format) { - list_add_tail(&format->list, &perf_hpp_list.fields); + list_add_tail(&format->list, &list->fields); } -void perf_hpp__column_unregister(struct perf_hpp_fmt *format) +void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, + struct perf_hpp_fmt *format) { - list_del(&format->list); + list_add_tail(&format->sort_list, &list->sorts); } -void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) +void perf_hpp__column_unregister(struct perf_hpp_fmt *format) { - list_add_tail(&format->sort_list, &perf_hpp_list.sorts); + list_del(&format->list); } void perf_hpp__cancel_cumulate(void) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index e22f98e..a7769d7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -233,6 +233,21 @@ struct perf_hpp_list { extern struct perf_hpp_list perf_hpp_list; +void perf_hpp_list__column_register(struct perf_hpp_list *list, + struct perf_hpp_fmt *format); +void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, + struct perf_hpp_fmt *format); + +static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) +{ + perf_hpp_list__column_register(&perf_hpp_list, format); +} + +static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) +{ + perf_hpp_list__register_sort_field(&perf_hpp_list, format); +} + #define perf_hpp__for_each_format(format) \ list_for_each_entry(format, &perf_hpp_list.fields, list) @@ -262,11 +277,8 @@ enum { }; void perf_hpp__init(void); -void perf_hpp__column_register(struct perf_hpp_fmt *format); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); void perf_hpp__cancel_cumulate(void); - -void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); void perf_hpp__setup_output_field(void); void perf_hpp__reset_output_field(void); void perf_hpp__append_sort_keys(void); -- cgit v0.10.2 From 07600027fb7114bf7bcabdd121e5178f200d8a44 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:16 +0100 Subject: perf hists: Pass perf_hpp_list all the way through setup_output_list Passing perf_hpp_list all the way through setup_output_list so the output entry could be added on the arbitrary list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-19-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 36dbd55..f643bed 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1616,14 +1616,15 @@ static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) return 0; } -static int __sort_dimension__add_hpp_output(struct sort_dimension *sd) +static int __sort_dimension__add_hpp_output(struct perf_hpp_list *list, + struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); if (hse == NULL) return -1; - perf_hpp__column_register(&hse->hpp); + perf_hpp_list__column_register(list, &hse->hpp); return 0; } @@ -2117,19 +2118,21 @@ static int __hpp_dimension__add(struct hpp_dimension *hd) return 0; } -static int __sort_dimension__add_output(struct sort_dimension *sd) +static int __sort_dimension__add_output(struct perf_hpp_list *list, + struct sort_dimension *sd) { if (sd->taken) return 0; - if (__sort_dimension__add_hpp_output(sd) < 0) + if (__sort_dimension__add_hpp_output(list, sd) < 0) return -1; sd->taken = 1; return 0; } -static int __hpp_dimension__add_output(struct hpp_dimension *hd) +static int __hpp_dimension__add_output(struct perf_hpp_list *list, + struct hpp_dimension *hd) { struct perf_hpp_fmt *fmt; @@ -2141,14 +2144,14 @@ static int __hpp_dimension__add_output(struct hpp_dimension *hd) return -1; hd->taken = 1; - perf_hpp__column_register(fmt); + perf_hpp_list__column_register(list, fmt); return 0; } int hpp_dimension__add_output(unsigned col) { BUG_ON(col >= PERF_HPP__MAX_INDEX); - return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); + return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); } static int sort_dimension__add(const char *tok, @@ -2492,7 +2495,7 @@ void sort__setup_elide(FILE *output) } } -static int output_field_add(char *tok) +static int output_field_add(struct perf_hpp_list *list, char *tok) { unsigned int i; @@ -2502,7 +2505,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { @@ -2511,7 +2514,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, hd->name, strlen(tok))) continue; - return __hpp_dimension__add_output(hd); + return __hpp_dimension__add_output(list, hd); } for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { @@ -2520,7 +2523,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { @@ -2529,20 +2532,20 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } return -ESRCH; } -static int setup_output_list(char *str) +static int setup_output_list(struct perf_hpp_list *list, char *str) { char *tmp, *tok; int ret = 0; for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = output_field_add(tok); + ret = output_field_add(list, tok); if (ret == -EINVAL) { error("Invalid --fields key: `%s'", tok); break; @@ -2599,7 +2602,7 @@ static int __setup_output_field(void) goto out; } - ret = setup_output_list(strp); + ret = setup_output_list(&perf_hpp_list, strp); out: free(str); -- cgit v0.10.2 From cf094045d718437e3d5cd42ac09d77561cb2f368 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:17 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_format macro Introducing perf_hpp_list__for_each_format macro to iterate perf_hpp_list object's output entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-20-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 61d578b..df0aedf 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1095,7 +1095,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, hist_browser__gotorc(browser, row, 0); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, entry->hists) || column++ < browser->b.horiz_scroll) continue; @@ -1175,7 +1175,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * return ret; } - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) continue; @@ -1441,7 +1441,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) printed += fprintf(fp, "%c ", folded_sign); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -2104,7 +2104,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, memset(options, 0, sizeof(options)); memset(actions, 0, sizeof(actions)); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { perf_hpp__reset_width(fmt, hists); /* * This is done just once, and activates the horizontal scrolling diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 0f8dcfd..eca5151 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -306,7 +306,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, nr_cols = 0; - perf_hpp__for_each_format(fmt) + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) col_types[nr_cols++] = G_TYPE_STRING; store = gtk_tree_store_newv(nr_cols, col_types); @@ -317,7 +317,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -367,7 +367,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, h->hists)) continue; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 1655c0d..7b5e8ce 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -556,7 +556,7 @@ void perf_hpp__setup_output_field(void) perf_hpp__for_each_sort_list(fmt) { struct perf_hpp_fmt *pos; - perf_hpp__for_each_format(pos) { + perf_hpp_list__for_each_format(&perf_hpp_list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -572,7 +572,7 @@ void perf_hpp__append_sort_keys(void) struct perf_hpp_fmt *fmt; /* append output fields to sort keys */ - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; perf_hpp__for_each_sort_list(pos) { @@ -621,7 +621,7 @@ unsigned int hists__sort_list_width(struct hists *hists) bool first = true; struct perf_hpp dummy_hpp; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -674,7 +674,7 @@ void perf_hpp__set_user_width(const char *width_list_str) struct perf_hpp_fmt *fmt; const char *ptr = width_list_str; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { char *p; int len = strtol(ptr, &p, 10); diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 691e52c..83e0bf2 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -384,7 +384,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) if (symbol_conf.exclude_other && !he->parent) return 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -453,7 +453,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, init_rem_hits(); - perf_hpp__for_each_format(fmt) + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) perf_hpp__reset_width(fmt, hists); if (symbol_conf.col_width_list_str) @@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -488,7 +488,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { unsigned int i; if (perf_hpp__should_skip(fmt, hists)) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index a7769d7..eadffca 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -248,8 +248,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) perf_hpp_list__register_sort_field(&perf_hpp_list, format); } -#define perf_hpp__for_each_format(format) \ - list_for_each_entry(format, &perf_hpp_list.fields, list) +#define perf_hpp_list__for_each_format(_list, format) \ + list_for_each_entry(format, &(_list)->fields, list) #define perf_hpp__for_each_format_safe(format, tmp) \ list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index f643bed..1e134ff 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2407,7 +2407,7 @@ void perf_hpp__set_elide(int idx, bool elide) struct perf_hpp_fmt *fmt; struct hpp_sort_entry *hse; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2467,7 +2467,7 @@ void sort__setup_elide(FILE *output) struct perf_hpp_fmt *fmt; struct hpp_sort_entry *hse; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2479,7 +2479,7 @@ void sort__setup_elide(FILE *output) * It makes no sense to elide all of sort entries. * Just revert them to show up again. */ - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2487,7 +2487,7 @@ void sort__setup_elide(FILE *output) return; } - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; -- cgit v0.10.2 From 7a1799e0a276069d8b903ba17179b4983b98c04b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:18 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_format_safe macro Introducing perf_hpp_list__for_each_format_safe macro to iterate perf_hpp_list object's output entries safely. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-21-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 7b5e8ce..348706a 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -532,7 +532,7 @@ void perf_hpp__cancel_cumulate(void) ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; - perf_hpp__for_each_format_safe(fmt, tmp) { + perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { if (acc->equal(acc, fmt)) { perf_hpp__column_unregister(fmt); continue; @@ -597,7 +597,7 @@ void perf_hpp__reset_output_field(void) struct perf_hpp_fmt *fmt, *tmp; /* reset output fields */ - perf_hpp__for_each_format_safe(fmt, tmp) { + perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index eadffca..f5b2309 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -251,8 +251,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_format(_list, format) \ list_for_each_entry(format, &(_list)->fields, list) -#define perf_hpp__for_each_format_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) +#define perf_hpp_list__for_each_format_safe(_list, format, tmp) \ + list_for_each_entry_safe(format, tmp, &(_list)->fields, list) #define perf_hpp__for_each_sort_list(format) \ list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) -- cgit v0.10.2 From d29a497090845002ee449c8dc682dd59ad8bab42 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:19 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_sort_list macro Introducing perf_hpp_list__for_each_sort_list macro to iterate perf_hpp_list object's sort entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-22-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 348706a..f09eabe 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -553,7 +553,7 @@ void perf_hpp__setup_output_field(void) struct perf_hpp_fmt *fmt; /* append sort keys to output field */ - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; perf_hpp_list__for_each_format(&perf_hpp_list, pos) { @@ -575,7 +575,7 @@ void perf_hpp__append_sort_keys(void) perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp__for_each_sort_list(pos) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, pos) { if (fmt_equal(fmt, pos)) goto next; } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b762ecc..dea475d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -961,7 +961,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { cmp = fmt->cmp(fmt, left, right); if (cmp) break; @@ -976,7 +976,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { cmp = fmt->collapse(fmt, left, right); if (cmp) break; @@ -1120,7 +1120,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, a->hists)) continue; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f5b2309..c9b2ea4 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -254,8 +254,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_format_safe(_list, format, tmp) \ list_for_each_entry_safe(format, tmp, &(_list)->fields, list) -#define perf_hpp__for_each_sort_list(format) \ - list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) +#define perf_hpp_list__for_each_sort_list(_list, format) \ + list_for_each_entry(format, &(_list)->sorts, sort_list) #define perf_hpp__for_each_sort_list_safe(format, tmp) \ list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) -- cgit v0.10.2 From 1a8ebd243a0b65c2a6d1458705d04dece937ab52 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:20 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_sort_list_safe macro Introducing perf_hpp_list__for_each_sort_list_safe macro to iterate perf_hpp_list object's sort entries safely. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-23-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f09eabe..9cda51e 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -604,7 +604,7 @@ void perf_hpp__reset_output_field(void) } /* reset sort keys */ - perf_hpp__for_each_sort_list_safe(fmt, tmp) { + perf_hpp_list__for_each_sort_list_safe(&perf_hpp_list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index c9b2ea4..61d35a9 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -257,8 +257,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_sort_list(_list, format) \ list_for_each_entry(format, &(_list)->sorts, sort_list) -#define perf_hpp__for_each_sort_list_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) +#define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \ + list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) extern struct perf_hpp_fmt perf_hpp__format[]; -- cgit v0.10.2 From 43e0a68f13047750a3728c983a539c61fb4121c5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:21 +0100 Subject: perf hists: Add struct perf_hpp_list argument to helper functions Adding struct perf_hpp_list argument to following helper functions: void perf_hpp__setup_output_field(struct perf_hpp_list *list); void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__append_sort_keys(struct perf_hpp_list *list); so they could be used on hists's hpp_list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-24-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 9cda51e..8075d4c 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -548,15 +548,15 @@ static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) return a->equal && a->equal(a, b); } -void perf_hpp__setup_output_field(void) +void perf_hpp__setup_output_field(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt; /* append sort keys to output field */ - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + perf_hpp_list__for_each_sort_list(list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp_list__for_each_format(&perf_hpp_list, pos) { + perf_hpp_list__for_each_format(list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -567,15 +567,15 @@ next: } } -void perf_hpp__append_sort_keys(void) +void perf_hpp__append_sort_keys(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt; /* append output fields to sort keys */ - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + perf_hpp_list__for_each_format(list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, pos) { + perf_hpp_list__for_each_sort_list(list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -586,25 +586,26 @@ next: } } + static void fmt_free(struct perf_hpp_fmt *fmt) { if (fmt->free) fmt->free(fmt); } -void perf_hpp__reset_output_field(void) +void perf_hpp__reset_output_field(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt, *tmp; /* reset output fields */ - perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { + perf_hpp_list__for_each_format_safe(list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); } /* reset sort keys */ - perf_hpp_list__for_each_sort_list_safe(&perf_hpp_list, fmt, tmp) { + perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 61d35a9..a39c9c1 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -279,9 +279,10 @@ enum { void perf_hpp__init(void); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); void perf_hpp__cancel_cumulate(void); -void perf_hpp__setup_output_field(void); -void perf_hpp__reset_output_field(void); -void perf_hpp__append_sort_keys(void); +void perf_hpp__setup_output_field(struct perf_hpp_list *list); +void perf_hpp__reset_output_field(struct perf_hpp_list *list); +void perf_hpp__append_sort_keys(struct perf_hpp_list *list); + bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1e134ff..de620f7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2636,9 +2636,9 @@ int setup_sorting(struct perf_evlist *evlist) return err; /* copy sort keys to output fields */ - perf_hpp__setup_output_field(); + perf_hpp__setup_output_field(&perf_hpp_list); /* and then copy output fields to sort keys */ - perf_hpp__append_sort_keys(); + perf_hpp__append_sort_keys(&perf_hpp_list); return 0; } @@ -2654,5 +2654,5 @@ void reset_output_field(void) sort_order = NULL; reset_dimensions(); - perf_hpp__reset_output_field(); + perf_hpp__reset_output_field(&perf_hpp_list); } -- cgit v0.10.2 From 5b65855e20348a9e2772a1cb7c1e6ab477859ba6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:22 +0100 Subject: perf tools: Add hpp_list into struct hists object Adding hpp_list into struct hists object. Initializing struct hists_evsel hists object to carry global perf_hpp_list list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-25-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index dea475d..2b9cc91 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1578,7 +1578,7 @@ int perf_hist_config(const char *var, const char *value) return 0; } -int __hists__init(struct hists *hists) +int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list) { memset(hists, 0, sizeof(*hists)); hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; @@ -1587,6 +1587,7 @@ int __hists__init(struct hists *hists) hists->entries = RB_ROOT; pthread_mutex_init(&hists->lock, NULL); hists->socket_filter = -1; + hists->hpp_list = hpp_list; return 0; } @@ -1623,7 +1624,7 @@ static int hists_evsel__init(struct perf_evsel *evsel) { struct hists *hists = evsel__hists(evsel); - __hists__init(hists); + __hists__init(hists, &perf_hpp_list); return 0; } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index a39c9c1..b296ff5 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -75,6 +75,7 @@ struct hists { u64 event_stream; u16 col_len[HISTC_NR_COLS]; int socket_filter; + struct perf_hpp_list *hpp_list; }; struct hist_entry_iter; @@ -186,7 +187,7 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel) } int hists__init(void); -int __hists__init(struct hists *hists); +int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); struct rb_root *hists__get_rotate_entries_in(struct hists *hists); bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, -- cgit v0.10.2 From f0786af536bb0ba54cb516eee493af03cefdbaa3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:23 +0100 Subject: perf hists: Introduce hists__for_each_format macro With the hist object having the perf_hpp_list we can now iterate output format entries based in the hists object. Adding hists__for_each_format macro to do that. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-26-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index df0aedf..3a1e096 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1095,7 +1095,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, hist_browser__gotorc(browser, row, 0); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, entry->hists) || column++ < browser->b.horiz_scroll) continue; @@ -1175,7 +1175,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * return ret; } - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) continue; @@ -1441,7 +1441,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) printed += fprintf(fp, "%c ", folded_sign); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -2104,7 +2104,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, memset(options, 0, sizeof(options)); memset(actions, 0, sizeof(actions)); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { perf_hpp__reset_width(fmt, hists); /* * This is done just once, and activates the horizontal scrolling diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index eca5151..32cc38a 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -306,7 +306,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, nr_cols = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) + hists__for_each_format(hists, fmt) col_types[nr_cols++] = G_TYPE_STRING; store = gtk_tree_store_newv(nr_cols, col_types); @@ -317,7 +317,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -367,7 +367,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, h->hists)) continue; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 8075d4c..1ba4117 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -622,7 +622,7 @@ unsigned int hists__sort_list_width(struct hists *hists) bool first = true; struct perf_hpp dummy_hpp; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 83e0bf2..1a6e8f7 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -384,7 +384,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) if (symbol_conf.exclude_other && !he->parent) return 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(he->hists, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -453,7 +453,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, init_rem_hits(); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) + hists__for_each_format(hists, fmt) perf_hpp__reset_width(fmt, hists); if (symbol_conf.col_width_list_str) @@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -488,7 +488,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { unsigned int i; if (perf_hpp__should_skip(fmt, hists)) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b296ff5..bc90044 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -261,6 +261,9 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \ list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) +#define hists__for_each_format(hists, format) \ + perf_hpp_list__for_each_format((hists)->hpp_list, fmt) + extern struct perf_hpp_fmt perf_hpp__format[]; enum { -- cgit v0.10.2 From aa6f50af822a552b579252ecd42224e09e11e879 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:24 +0100 Subject: perf hists: Introduce hists__for_each_sort_list macro With the hist object having the perf_hpp_list we can now iterate sort format entries based in the hists object. Adding hists__for_each_sort_list macro to do that. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-27-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2b9cc91..12f2d79 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -958,10 +958,11 @@ out: int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) { + struct hists *hists = left->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { cmp = fmt->cmp(fmt, left, right); if (cmp) break; @@ -973,10 +974,11 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) { + struct hists *hists = left->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { cmp = fmt->collapse(fmt, left, right); if (cmp) break; @@ -1117,10 +1119,11 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) { + struct hists *hists = a->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { if (perf_hpp__should_skip(fmt, a->hists)) continue; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bc90044..1c7544a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -264,6 +264,9 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define hists__for_each_format(hists, format) \ perf_hpp_list__for_each_format((hists)->hpp_list, fmt) +#define hists__for_each_sort_list(hists, format) \ + perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt) + extern struct perf_hpp_fmt perf_hpp__format[]; enum { -- cgit v0.10.2 From c6f5f6b662719ded53700deefec7dbc4227c9778 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:20 +0900 Subject: perf report: Update documentation of --sort option The description of the memory sort key (used by --mem-mode) was misplaced. Move it under the --sort option so that it can be referenced properly. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8a301f6..1cb8fac 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -117,6 +117,22 @@ OPTIONS And default sort keys are changed to comm, dso_from, symbol_from, dso_to and symbol_to, see '--branch-stack'. + If the --mem-mode option is used, the following sort keys are also available + (incompatible with --branch-stack): + symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. + + - symbol_daddr: name of data symbol being executed on at the time of sample + - dso_daddr: name of library or module containing the data being executed + on at the time of the sample + - locked: whether the bus was locked at the time of the sample + - tlb: type of tlb access for the data at the time of the sample + - mem: type of memory access for the data at the time of the sample + - snoop: type of snoop (if any) for the data at the time of the sample + - dcacheline: the cacheline the data address is on at the time of the sample + + And the default sort keys are changed to local_weight, mem, sym, dso, + symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. + If the data file has tracepoint event(s), following (dynamic) sort keys are also available: trace, trace_fields, [.][/raw] @@ -151,22 +167,6 @@ OPTIONS By default, every sort keys not specified in -F will be appended automatically. - If --mem-mode option is used, following sort keys are also available - (incompatible with --branch-stack): - symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. - - - symbol_daddr: name of data symbol being executed on at the time of sample - - dso_daddr: name of library or module containing the data being executed - on at the time of sample - - locked: whether the bus was locked at the time of sample - - tlb: type of tlb access for the data at the time of sample - - mem: type of memory access for the data at the time of sample - - snoop: type of snoop (if any) for the data at the time of sample - - dcacheline: the cacheline the data address is on at the time of sample - - And default sort keys are changed to local_weight, mem, sym, dso, - symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. - -p:: --parent=:: A regex filter to identify parent. The parent is a caller of this -- cgit v0.10.2 From 1ba2fc6de4ac1a87e3ece65651795760ea5cf658 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:21 +0900 Subject: perf report: Update documention of --percent-limit option The --percent-limit option was changed to be applied to callchains as well as to hist entries recently, but it missed to update the doc. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 1cb8fac..89cab84 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -351,7 +351,10 @@ OPTIONS --percent-limit:: Do not show entries which have an overhead under that percent. - (Default: 0). + (Default: 0). Note that this option also sets the percent limit (threshold) + of callchains. However the default value of callchain threshold is + different than the default value of hist entries. Please see the + --call-graph option for details. --percentage:: Determine how to display the overhead percentage of filtered entries. -- cgit v0.10.2 From b62e8dfcda8cb133c062c0e1207afea2476eb7fd Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:23 +0900 Subject: perf hists browser: Add 'L' hotkey to change percent limit Add 'L' key action to change the percent limit applied to both of hist entries and callchains. Suggested-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 3a1e096..a5a5390 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2029,6 +2029,42 @@ static void hist_browser__update_nr_entries(struct hist_browser *hb) hb->nr_non_filtered_entries = nr_entries; } +static void hist_browser__update_percent_limit(struct hist_browser *hb, + double percent) +{ + struct hist_entry *he; + struct rb_node *nd = rb_first(&hb->hists->entries); + u64 total = hists__total_period(hb->hists); + u64 min_callchain_hits = total * (percent / 100); + + hb->min_pcnt = callchain_param.min_percent = percent; + + if (!symbol_conf.use_callchain) + return; + + while ((nd = hists__filter_entries(nd, hb->min_pcnt)) != NULL) { + he = rb_entry(nd, struct hist_entry, rb_node); + + if (callchain_param.mode == CHAIN_GRAPH_REL) { + total = he->stat.period; + + if (symbol_conf.cumulate_callchain) + total = he->stat_acc->period; + + min_callchain_hits = total * (percent / 100); + } + + callchain_param.sort(&he->sorted_chain, he->callchain, + min_callchain_hits, &callchain_param); + + /* force to re-evaluate folding state of callchains */ + he->init_have_children = false; + hist_entry__set_folding(he, false); + + nd = rb_next(nd); + } +} + static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, bool left_exits, @@ -2064,6 +2100,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "E Expand all callchains\n" \ "F Toggle percentage of filtered entries\n" \ "H Display column headers\n" \ + "L Change percent limit\n" \ "m Display context menu\n" \ "S Zoom into current Processor Socket\n" \ @@ -2219,6 +2256,24 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, top->zero = !top->zero; } continue; + case 'L': + if (ui_browser__input_window("Percent Limit", + "Please enter the value you want to hide entries under that percent.", + buf, "ENTER: OK, ESC: Cancel", + delay_secs * 2) == K_ENTER) { + char *end; + double new_percent = strtod(buf, &end); + + if (new_percent < 0 || new_percent > 100) { + ui_browser__warning(&browser->b, delay_secs * 2, + "Invalid percent: %.2f", new_percent); + continue; + } + + hist_browser__update_percent_limit(browser, new_percent); + hist_browser__reset(browser); + } + continue; case K_F1: case 'h': case '?': -- cgit v0.10.2