diff options
Diffstat (limited to 'tools/perf/ui/browsers/hists.c')
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index ef2f93ca749..ccc4bd16142 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -11,6 +11,7 @@ #include "../../util/pstack.h" #include "../../util/sort.h" #include "../../util/util.h" +#include "../../arch/common.h" #include "../browser.h" #include "../helpline.h" @@ -310,10 +311,11 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser) } static int hist_browser__run(struct hist_browser *browser, const char *ev_name, - void(*timer)(void *arg), void *arg, int delay_secs) + struct hist_browser_timer *hbt) { int key; char title[160]; + int delay_secs = hbt ? hbt->refresh : 0; browser->b.entries = &browser->hists->entries; browser->b.nr_entries = browser->hists->nr_entries; @@ -330,7 +332,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, switch (key) { case K_TIMER: - timer(arg); + hbt->timer(hbt->arg); ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); if (browser->hists->stats.nr_lost_warned != @@ -1127,11 +1129,17 @@ static inline void free_popup_options(char **options, int n) } } +/* Check whether the browser is for 'top' or 'report' */ +static inline bool is_report_browser(void *timer) +{ + return timer == NULL; +} + static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, const char *ev_name, bool left_exits, - void(*timer)(void *arg), void *arg, - int delay_secs) + struct hist_browser_timer *hbt, + struct perf_session_env *env) { struct hists *hists = &evsel->hists; struct hist_browser *browser = hist_browser__new(hists); @@ -1141,6 +1149,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, int nr_options = 0; int key = -1; char buf[64]; + char script_opt[64]; + int delay_secs = hbt ? hbt->refresh : 0; if (browser == NULL) return -1; @@ -1159,10 +1169,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, int choice = 0, annotate = -2, zoom_dso = -2, zoom_thread = -2, annotate_f = -2, annotate_t = -2, browse_map = -2; + int scripts_comm = -2, scripts_symbol = -2, scripts_all = -2; nr_options = 0; - key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); + key = hist_browser__run(browser, ev_name, hbt); if (browser->he_selection != NULL) { thread = hist_browser__selected_thread(browser); @@ -1211,6 +1222,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, hist_browser__reset(browser); } continue; + case 'r': + if (is_report_browser(hbt)) + goto do_scripts; + continue; case K_F1: case 'h': case '?': @@ -1229,6 +1244,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "E Expand all callchains\n" "d Zoom into current DSO\n" "t Zoom into current Thread\n" + "r Run available scripts('perf report' only)\n" "P Print histograms to perf.hist.N\n" "V Verbose (DSO names in callchains, etc)\n" "/ Filter symbol by name"); @@ -1317,6 +1333,25 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, browser->selection->map != NULL && asprintf(&options[nr_options], "Browse map details") > 0) browse_map = nr_options++; + + /* perf script support */ + if (browser->he_selection) { + struct symbol *sym; + + if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]", + browser->he_selection->thread->comm) > 0) + scripts_comm = nr_options++; + + sym = browser->he_selection->ms.sym; + if (sym && sym->namelen && + asprintf(&options[nr_options], "Run scripts for samples of symbol [%s]", + sym->name) > 0) + scripts_symbol = nr_options++; + } + + if (asprintf(&options[nr_options], "Run scripts for all samples") > 0) + scripts_all = nr_options++; + add_exit_option: options[nr_options++] = (char *)"Exit"; retry_popup_menu: @@ -1334,6 +1369,9 @@ retry_popup_menu: struct hist_entry *he; int err; do_annotate: + if (!objdump_path && perf_session_env__lookup_objdump(env)) + continue; + he = hist_browser__selected_entry(browser); if (he == NULL) continue; @@ -1356,8 +1394,7 @@ do_annotate: * Don't let this be freed, say, by hists__decay_entry. */ he->used = true; - err = hist_entry__tui_annotate(he, evsel->idx, - timer, arg, delay_secs); + err = hist_entry__tui_annotate(he, evsel->idx, hbt); he->used = false; /* * offer option to annotate the other branch source or target @@ -1411,6 +1448,20 @@ zoom_out_thread: hists__filter_by_thread(hists); hist_browser__reset(browser); } + /* perf scripts support */ + else if (choice == scripts_all || choice == scripts_comm || + choice == scripts_symbol) { +do_scripts: + memset(script_opt, 0, 64); + + if (choice == scripts_comm) + sprintf(script_opt, " -c %s ", browser->he_selection->thread->comm); + + if (choice == scripts_symbol) + sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name); + + script_browse(script_opt); + } } out_free_stack: pstack__delete(fstack); @@ -1424,6 +1475,7 @@ struct perf_evsel_menu { struct ui_browser b; struct perf_evsel *selection; bool lost_events, lost_events_warned; + struct perf_session_env *env; }; static void perf_evsel_menu__write(struct ui_browser *browser, @@ -1466,11 +1518,12 @@ static void perf_evsel_menu__write(struct ui_browser *browser, static int perf_evsel_menu__run(struct perf_evsel_menu *menu, int nr_events, const char *help, - void(*timer)(void *arg), void *arg, int delay_secs) + struct hist_browser_timer *hbt) { struct perf_evlist *evlist = menu->b.priv; struct perf_evsel *pos; const char *ev_name, *title = "Available samples"; + int delay_secs = hbt ? hbt->refresh : 0; int key; if (ui_browser__show(&menu->b, title, @@ -1482,7 +1535,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, switch (key) { case K_TIMER: - timer(arg); + hbt->timer(hbt->arg); if (!menu->lost_events_warned && menu->lost_events) { ui_browser__warn_lost_events(&menu->b); @@ -1500,12 +1553,12 @@ browse_hists: * Give the calling tool a chance to populate the non * default evsel resorted hists tree. */ - if (timer) - timer(arg); + if (hbt) + hbt->timer(hbt->arg); ev_name = perf_evsel__name(pos); key = perf_evsel__hists_browse(pos, nr_events, help, - ev_name, true, timer, - arg, delay_secs); + ev_name, true, hbt, + menu->env); ui_browser__show_title(&menu->b, title); switch (key) { case K_TAB: @@ -1553,8 +1606,8 @@ out: static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, - void(*timer)(void *arg), void *arg, - int delay_secs) + struct hist_browser_timer *hbt, + struct perf_session_env *env) { struct perf_evsel *pos; struct perf_evsel_menu menu = { @@ -1566,6 +1619,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, .nr_entries = evlist->nr_entries, .priv = evlist, }, + .env = env, }; ui_helpline__push("Press ESC to exit"); @@ -1578,23 +1632,20 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, menu.b.width = line_len; } - return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, - arg, delay_secs); + return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt); } int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, - void(*timer)(void *arg), void *arg, - int delay_secs) + struct hist_browser_timer *hbt, + struct perf_session_env *env) { if (evlist->nr_entries == 1) { struct perf_evsel *first = list_entry(evlist->entries.next, struct perf_evsel, node); const char *ev_name = perf_evsel__name(first); return perf_evsel__hists_browse(first, evlist->nr_entries, help, - ev_name, false, timer, arg, - delay_secs); + ev_name, false, hbt, env); } - return __perf_evlist__tui_browse_hists(evlist, help, - timer, arg, delay_secs); + return __perf_evlist__tui_browse_hists(evlist, help, hbt, env); } |