From 62c95ae33f64ecf398f490886f026a6132fb1520 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 1 Jul 2014 11:07:54 -0300 Subject: [PATCH 01/16] perf ui browser: Add ->rows to disambiguate from ->height The ui_browser->height is about the whole browser "window", including any header, status lines or any other space needed for some "Yes", "No", etc buttons a descendent browser, like hist_browser, may have. Since the navigation is done mostly on the ui_browser methods, it needs to know how many rows are on the screen, while details about what other components are, say, if a header (that may be composed of multiple lines, etc) is present. Besides this we'll need to add a ui_browser->refresh_dimensions() hook so that browsers like hist_browser can update ->rows in response to screen resizes, this will come in a follow up patch. This patch just adds ->rows and updates it when updating ->height, keeps using ->height for the only other widget that can come with ui_browser, the scrollbar, that goes on using all the height on the rightmost column in the screen, using ->rows for the keyboard navigation needs. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-xexmwg1mv7u03j5imn66jdak@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 30 +++++++++++++++--------------- tools/perf/ui/browser.h | 2 +- tools/perf/ui/browsers/hists.c | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 9d2294efc00c20..adb294a3ec08b1 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -150,7 +150,7 @@ unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser) while (nd != NULL) { ui_browser__gotorc(browser, row, 0); browser->write(browser, nd, row); - if (++row == browser->height) + if (++row == browser->rows) break; nd = rb_next(nd); } @@ -166,7 +166,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row) void ui_browser__refresh_dimensions(struct ui_browser *browser) { browser->width = SLtt_Screen_Cols - 1; - browser->height = SLtt_Screen_Rows - 2; + browser->height = browser->rows = SLtt_Screen_Rows - 2; browser->y = 1; browser->x = 0; } @@ -389,7 +389,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) if (browser->index == browser->nr_entries - 1) break; ++browser->index; - if (browser->index == browser->top_idx + browser->height) { + if (browser->index == browser->top_idx + browser->rows) { ++browser->top_idx; browser->seek(browser, +1, SEEK_CUR); } @@ -405,10 +405,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) break; case K_PGDN: case ' ': - if (browser->top_idx + browser->height > browser->nr_entries - 1) + if (browser->top_idx + browser->rows > browser->nr_entries - 1) break; - offset = browser->height; + offset = browser->rows; if (browser->index + offset > browser->nr_entries - 1) offset = browser->nr_entries - 1 - browser->index; browser->index += offset; @@ -419,10 +419,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) if (browser->top_idx == 0) break; - if (browser->top_idx < browser->height) + if (browser->top_idx < browser->rows) offset = browser->top_idx; else - offset = browser->height; + offset = browser->rows; browser->index -= offset; browser->top_idx -= offset; @@ -432,7 +432,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) ui_browser__reset_index(browser); break; case K_END: - offset = browser->height - 1; + offset = browser->rows - 1; if (offset >= browser->nr_entries) offset = browser->nr_entries - 1; @@ -462,7 +462,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser) if (!browser->filter || !browser->filter(browser, pos)) { ui_browser__gotorc(browser, row, 0); browser->write(browser, pos, row); - if (++row == browser->height) + if (++row == browser->rows) break; } } @@ -587,7 +587,7 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser) if (!browser->filter || !browser->filter(browser, *pos)) { ui_browser__gotorc(browser, row, 0); browser->write(browser, pos, row); - if (++row == browser->height) + if (++row == browser->rows) break; } @@ -623,7 +623,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser, SLsmg_set_char_set(1); - if (start < browser->top_idx + browser->height) { + if (start < browser->top_idx + browser->rows) { row = start - browser->top_idx; ui_browser__gotorc(browser, row, column); SLsmg_write_char(SLSMG_LLCORN_CHAR); @@ -633,7 +633,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser, if (row-- == 0) goto out; } else - row = browser->height - 1; + row = browser->rows - 1; if (end > browser->top_idx) end_row = end - browser->top_idx; @@ -675,8 +675,8 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, } else row = 0; - if (end >= browser->top_idx + browser->height) - end_row = browser->height - 1; + if (end >= browser->top_idx + browser->rows) + end_row = browser->rows - 1; else end_row = end - browser->top_idx; @@ -684,7 +684,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, SLsmg_draw_vline(end_row - row + 1); ui_browser__gotorc(browser, end_row, column); - if (end < browser->top_idx + browser->height) { + if (end < browser->top_idx + browser->rows) { SLsmg_write_char(SLSMG_LLCORN_CHAR); ui_browser__gotorc(browser, end_row, column + 1); SLsmg_write_char(SLSMG_HLINE_CHAR); diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 03d4d6295f1000..cb8f39a1646fb1 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -14,7 +14,7 @@ struct ui_browser { u64 index, top_idx; void *top, *entries; - u16 y, x, width, height; + u16 y, x, width, height, rows; int current_color; void *priv; const char *title; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2185091c5227ab..e16aff45b564d0 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -392,10 +392,10 @@ static int hist_browser__run(struct hist_browser *browser, struct hist_entry *h = rb_entry(browser->b.top, struct hist_entry, rb_node); ui_helpline__pop(); - ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", + ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", seq++, browser->b.nr_entries, browser->hists->nr_entries, - browser->b.height, + browser->b.rows, browser->b.index, browser->b.top_idx, h->row_offset, h->nr_rows); @@ -514,7 +514,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse slsmg_write_nstring(str, width); free(alloc_str); - if (++row == browser->b.height) + if (++row == browser->b.rows) goto out; do_next: if (folded_sign == '+') @@ -527,7 +527,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse new_level, row, row_offset, is_current_entry); } - if (row == browser->b.height) + if (row == browser->b.rows) goto out; node = next; } @@ -573,7 +573,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, slsmg_printf("%c ", folded_sign); slsmg_write_nstring(s, width - 2); - if (++row == browser->b.height) + if (++row == browser->b.rows) goto out; } @@ -602,7 +602,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, row += hist_browser__show_callchain_node(browser, node, level, row, row_offset, is_current_entry); - if (row == browser->b.height) + if (row == browser->b.rows) break; } @@ -776,7 +776,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, } else --row_offset; - if (folded_sign == '-' && row != browser->b.height) { + if (folded_sign == '-' && row != browser->b.rows) { printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 1, row, &row_offset, ¤t_entry); @@ -817,7 +817,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) continue; row += hist_browser__show_entry(hb, h, row); - if (row == browser->height) + if (row == browser->rows) break; } From fa70b5d66d6e9de3331f57e434a16bc0eee980a8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 1 Jul 2014 16:34:42 -0300 Subject: [PATCH 02/16] perf ui browser: Allow overriding refresh_dimensions method Some browsers, like the hist_browser, may want to be notified everytime a refresh_dimensions is needed, so that it can reset ui_browser->rows, for instance, or do some other related reaction to screen resizings. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ielvluuemzn30bneh0zk3twi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 7 +++++-- tools/perf/ui/browser.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index adb294a3ec08b1..6680fa5cb9dd9b 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -250,7 +250,10 @@ int ui_browser__show(struct ui_browser *browser, const char *title, int err; va_list ap; - ui_browser__refresh_dimensions(browser); + if (browser->refresh_dimensions == NULL) + browser->refresh_dimensions = ui_browser__refresh_dimensions; + + browser->refresh_dimensions(browser); pthread_mutex_lock(&ui__lock); __ui_browser__show_title(browser, title); @@ -367,7 +370,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) if (key == K_RESIZE) { ui__refresh_dimensions(false); - ui_browser__refresh_dimensions(browser); + browser->refresh_dimensions(browser); __ui_browser__show_title(browser, browser->title); ui_helpline__puts(browser->helpline); continue; diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index cb8f39a1646fb1..92ae7211396555 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -19,6 +19,7 @@ struct ui_browser { void *priv; const char *title; char *helpline; + void (*refresh_dimensions)(struct ui_browser *browser); unsigned int (*refresh)(struct ui_browser *browser); void (*write)(struct ui_browser *browser, void *entry, int row); void (*seek)(struct ui_browser *browser, off_t offset, int whence); From ca3ff33b5c2dc67daa8d4d130e3bd6231fcb3d14 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 1 Jul 2014 16:42:24 -0300 Subject: [PATCH 03/16] perf hists browser: Introduce gotorc method That will allow us to add a row offset to open up space for the column headers. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-otc3ployokfci5qi81o7jo22@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index e16aff45b564d0..ca63564d203a4a 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -63,6 +63,11 @@ static void hist_browser__refresh_dimensions(struct hist_browser *browser) sizeof("[k]")); } +static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) +{ + ui_browser__gotorc(&browser->b, row, column); +} + static void hist_browser__reset(struct hist_browser *browser) { /* @@ -508,7 +513,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse } ui_browser__set_color(&browser->b, color); - ui_browser__gotorc(&browser->b, row, 0); + hist_browser__gotorc(browser, row, 0); slsmg_write_nstring(" ", offset + extra_offset); slsmg_printf("%c ", folded_sign); slsmg_write_nstring(str, width); @@ -567,7 +572,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso); - ui_browser__gotorc(&browser->b, row, 0); + hist_browser__gotorc(browser, row, 0); ui_browser__set_color(&browser->b, color); slsmg_write_nstring(" ", offset); slsmg_printf("%c ", folded_sign); @@ -732,7 +737,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, .ptr = &arg, }; - ui_browser__gotorc(&browser->b, row, 0); + hist_browser__gotorc(browser, row, 0); perf_hpp__for_each_format(fmt) { if (perf_hpp__should_skip(fmt)) From 357cfff1c2173b7aedc0e521a2146b78396171e0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 1 Jul 2014 17:01:01 -0300 Subject: [PATCH 04/16] perf hists browser: Override ui_browser refresh_dimensions method This requires some more work so that we can really just use the width of current entries when we want to partition the screen. Right now its just a prep patch so that we can have where to update ui_browser->rows when introducing the column headers line, that will be togglable, so we need to update it everytime we refresh the dimensions of the browser. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ovk654rx525b4657y0mh6ku9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index ca63564d203a4a..ef7abf896f5ab4 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -56,11 +56,19 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb) return nr_entries + hb->nr_callchain_rows; } -static void hist_browser__refresh_dimensions(struct hist_browser *browser) +static void hist_browser__refresh_dimensions(struct ui_browser *browser) { + struct hist_browser *hb = container_of(browser, struct hist_browser, b); + /* 3 == +/- toggle symbol before actual hist_entry rendering */ - browser->b.width = 3 + (hists__sort_list_width(browser->hists) + - sizeof("[k]")); + browser->width = 3 + (hists__sort_list_width(hb->hists) + sizeof("[k]")); + /* + * FIXME: Just keeping existing behaviour, but this really should be + * before updating browser->width, as it will invalidate the + * calculation above. Fix this and the fallout in another + * changeset. + */ + ui_browser__refresh_dimensions(browser); } static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) @@ -78,7 +86,7 @@ static void hist_browser__reset(struct hist_browser *browser) hist_browser__update_nr_entries(browser); browser->b.nr_entries = hist_browser__nr_entries(browser); - hist_browser__refresh_dimensions(browser); + hist_browser__refresh_dimensions(&browser->b); ui_browser__reset_index(&browser->b); } @@ -360,7 +368,6 @@ static int hist_browser__run(struct hist_browser *browser, browser->b.entries = &browser->hists->entries; browser->b.nr_entries = hist_browser__nr_entries(browser); - hist_browser__refresh_dimensions(browser); hists__browser_title(browser->hists, title, sizeof(title)); if (ui_browser__show(&browser->b, title, @@ -1195,6 +1202,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) if (browser) { browser->hists = hists; browser->b.refresh = hist_browser__refresh; + browser->b.refresh_dimensions = hist_browser__refresh_dimensions; browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; } From 025bf7ea0aca26df4a4b28f0b12afe1aaf91e4bd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 14 Jun 2014 15:44:52 +0200 Subject: [PATCH 05/16] perf hists browser: Add support for showing columns header Open up space to show a one-line header text whenever 'H' is pressed, hide it on another key press. Follow up patch will format this line from the set of headers used. Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-m894d6qk30h3qofw4k8neq4q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 42 ++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index ef7abf896f5ab4..2be71bf17b7111 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -26,6 +26,7 @@ struct hist_browser { struct map_symbol *selection; int print_seq; bool show_dso; + bool show_headers; float min_pcnt; u64 nr_non_filtered_entries; u64 nr_callchain_rows; @@ -56,6 +57,21 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb) return nr_entries + hb->nr_callchain_rows; } +static void hist_browser__update_rows(struct hist_browser *hb) +{ + struct ui_browser *browser = &hb->b; + u16 header_offset = hb->show_headers ? 1 : 0, index_row; + + browser->rows = browser->height - header_offset; + /* + * Verify if we were at the last line and that line isn't + * visibe because we now show the header line(s). + */ + index_row = browser->index - browser->top_idx; + if (index_row >= browser->rows) + browser->index -= index_row - browser->rows + 1; +} + static void hist_browser__refresh_dimensions(struct ui_browser *browser) { struct hist_browser *hb = container_of(browser, struct hist_browser, b); @@ -69,11 +85,14 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser) * changeset. */ ui_browser__refresh_dimensions(browser); + hist_browser__update_rows(hb); } static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) { - ui_browser__gotorc(&browser->b, row, column); + u16 header_offset = browser->show_headers ? 1 : 0; + + ui_browser__gotorc(&browser->b, row + header_offset, column); } static void hist_browser__reset(struct hist_browser *browser) @@ -421,6 +440,10 @@ static int hist_browser__run(struct hist_browser *browser, /* Expand the whole world. */ hist_browser__set_folding(browser, true); break; + case 'H': + browser->show_headers = !browser->show_headers; + hist_browser__update_rows(browser); + break; case K_ENTER: if (hist_browser__toggle_fold(browser)) break; @@ -799,6 +822,13 @@ static int hist_browser__show_entry(struct hist_browser *browser, return printed; } +static void hist_browser__show_headers(struct hist_browser *browser) +{ + ui_browser__gotorc(&browser->b, 0, 0); + ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); + slsmg_write_nstring(" ", browser->b.width + 1); +} + static void ui_browser__hists_init_top(struct ui_browser *browser) { if (browser->top == NULL) { @@ -812,9 +842,15 @@ static void ui_browser__hists_init_top(struct ui_browser *browser) static unsigned int hist_browser__refresh(struct ui_browser *browser) { unsigned row = 0; + u16 header_offset = 0; struct rb_node *nd; struct hist_browser *hb = container_of(browser, struct hist_browser, b); + if (hb->show_headers) { + hist_browser__show_headers(hb); + header_offset = 1; + } + ui_browser__hists_init_top(browser); for (nd = browser->top; nd; nd = rb_next(nd)) { @@ -833,7 +869,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) break; } - return row; + return row + header_offset; } static struct rb_node *hists__filter_entries(struct rb_node *nd, @@ -1205,6 +1241,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) browser->b.refresh_dimensions = hist_browser__refresh_dimensions; browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; + browser->show_headers = false; } return browser; @@ -1434,6 +1471,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "d Zoom into current DSO\n" \ "E Expand all callchains\n" \ "F Toggle percentage of filtered entries\n" \ + "H Display column headers\n" \ /* help messages are sorted by lexical order of the hotkey */ const char report_help[] = HIST_BROWSER_HELP_COMMON From 81a888fea2cfd727052926e95510c11981d9b1c2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 14 Jun 2014 15:44:52 +0200 Subject: [PATCH 06/16] perf hists browser: Display columns header text on 'H' press Displaying columns header text whenever 'H' is pressed, and hiding it on on another press. Signed-off-by: Jiri Olsa Cc: Arnaldo Carvalho de Melo Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-w9pcqpum5erza2a05ysvollz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 47 ++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2be71bf17b7111..5fa2e181ef0cb6 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -822,11 +822,54 @@ static int hist_browser__show_entry(struct hist_browser *browser, return printed; } +static int advance_hpp_check(struct perf_hpp *hpp, int inc) +{ + advance_hpp(hpp, inc); + return hpp->size <= 0; +} + +static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) +{ + struct perf_hpp dummy_hpp = { + .buf = buf, + .size = size, + }; + struct perf_hpp_fmt *fmt; + size_t ret = 0; + + if (symbol_conf.use_callchain) { + ret = scnprintf(buf, size, " "); + if (advance_hpp_check(&dummy_hpp, ret)) + return ret; + } + + perf_hpp__for_each_format(fmt) { + if (perf_hpp__should_skip(fmt)) + continue; + + /* We need to add the length of the columns header. */ + perf_hpp__reset_width(fmt, hists); + + ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); + if (advance_hpp_check(&dummy_hpp, ret)) + break; + + ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); + if (advance_hpp_check(&dummy_hpp, ret)) + break; + } + + return ret; +} + static void hist_browser__show_headers(struct hist_browser *browser) { + char headers[1024]; + + hists__scnprintf_headers(headers, sizeof(headers), browser->hists); ui_browser__gotorc(&browser->b, 0, 0); ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); - slsmg_write_nstring(" ", browser->b.width + 1); + slsmg_write_nstring(headers, browser->b.width + 1); } static void ui_browser__hists_init_top(struct ui_browser *browser) @@ -1241,7 +1284,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) browser->b.refresh_dimensions = hist_browser__refresh_dimensions; browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; - browser->show_headers = false; + browser->show_headers = true; } return browser; From c83023676dc34f1b4422b842e1e2dc5c21bfc4dc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 27 Jun 2014 18:26:58 +0200 Subject: [PATCH 07/16] perf hists browser: Add ui.show-headers config file option Adding ui.show-headers config file option to define if the histogram entries headers will start visible or not. Currently columns headers are displayed by default, following lines in ~/.perfconfig file will disable that: [ui] show-headers = false Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1403886418-5556-4-git-send-email-jolsa@kernel.org [ renamed symbol_conf.show_headers to .show_hist_headers ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/util/config.c | 13 +++++++++++++ tools/perf/util/symbol.c | 1 + tools/perf/util/symbol.h | 3 ++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 5fa2e181ef0cb6..a94b11fc5e0026 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1284,7 +1284,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) browser->b.refresh_dimensions = hist_browser__refresh_dimensions; browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; - browser->show_headers = true; + browser->show_headers = symbol_conf.show_hist_headers; } return browser; diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 24519e14ac569c..1e5e2e5af6b1d0 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -350,6 +350,16 @@ static int perf_default_core_config(const char *var __maybe_unused, return 0; } +static int perf_ui_config(const char *var, const char *value) +{ + /* Add other config variables here. */ + if (!strcmp(var, "ui.show-headers")) { + symbol_conf.show_hist_headers = perf_config_bool(var, value); + return 0; + } + return 0; +} + int perf_default_config(const char *var, const char *value, void *dummy __maybe_unused) { @@ -359,6 +369,9 @@ int perf_default_config(const char *var, const char *value, if (!prefixcmp(var, "hist.")) return perf_hist_config(var, value); + if (!prefixcmp(var, "ui.")) + return perf_ui_config(var, value); + /* Add other config variables here. */ return 0; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7b9096f29cdbf7..2e6a2e219eb95f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -34,6 +34,7 @@ struct symbol_conf symbol_conf = { .annotate_src = true, .demangle = true, .cumulate_callchain = true, + .show_hist_headers = true, .symfs = "", }; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 615c752dd76736..a81877b1dee0ec 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -118,7 +118,8 @@ struct symbol_conf { annotate_src, event_group, demangle, - filter_relative; + filter_relative, + show_hist_headers; const char *vmlinux_name, *kallsyms_name, *source_prefix, From 1561880d7b114a65e307d1ac9a0991dc715355b3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 7 Jul 2014 15:23:44 -0300 Subject: [PATCH 08/16] perf hists browser: Left justify column headers Looks better and avoids it moving to the end of the screen as the column width changes over time in 'perf top'. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-yc144ai5jye3yl3h5yxw0scd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1ec57dd822847c..14e5a039bc4546 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1215,7 +1215,7 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, hse = container_of(fmt, struct hpp_sort_entry, hpp); len = hists__col_len(&evsel->hists, hse->se->se_width_idx); - return scnprintf(hpp->buf, hpp->size, "%*s", len, hse->se->se_header); + return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); } static int __sort__hpp_width(struct perf_hpp_fmt *fmt, From da50ad69723111e0292f1943dad77b41bb9a25b0 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 3 Jul 2014 17:59:49 +0400 Subject: [PATCH 09/16] perf kvm: Introduce HAVE_KVM_STAT_SUPPORT flag kvm stat support is currently conditional on i386/x86_64. Let's abstract this into a HAVE_KVM_STAT_SUPPORT flag, so that other architectures can support kvm stat as well. Reviewed-by: Cornelia Huck Reviewed-by: David Ahern Signed-off-by: Alexander Yarygin Acked-by: Christian Borntraeger Cc: Christian Borntraeger Cc: Cornelia Huck Cc: David Ahern Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1404395992-17095-2-git-send-email-yarygin@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-kvm.c | 6 +++--- tools/perf/config/Makefile | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 1641542e363669..d3939014a877a6 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -15,3 +15,4 @@ endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o LIB_H += arch/$(ARCH)/util/tsc.h +HAVE_KVM_STAT_SUPPORT := 1 diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 0f1e5a2f6ad716..214ec0e7492b39 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -29,7 +29,7 @@ #include #include -#if defined(__i386__) || defined(__x86_64__) +#ifdef HAVE_KVM_STAT_SUPPORT #include #include #include @@ -1609,7 +1609,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) perf_stat: return cmd_stat(argc, argv, NULL); } -#endif +#endif /* HAVE_KVM_STAT_SUPPORT */ static int __cmd_record(const char *file_name, int argc, const char **argv) { @@ -1726,7 +1726,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) return cmd_top(argc, argv, NULL); else if (!strncmp(argv[0], "buildid-list", 12)) return __cmd_buildid_list(file_name, argc, argv); -#if defined(__i386__) || defined(__x86_64__) +#ifdef HAVE_KVM_STAT_SUPPORT else if (!strncmp(argv[0], "stat", 4)) return kvm_cmd_stat(file_name, argc, argv); #endif diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 346bdb61754468..b7f42d577c4eea 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -594,6 +594,10 @@ ifndef NO_LIBNUMA endif endif +ifdef HAVE_KVM_STAT_SUPPORT + CFLAGS += -DHAVE_KVM_STAT_SUPPORT +endif + # Among the variables below, these: # perfexecdir # template_dir From df74c13b6c53c97576652f7b2840764ad7d5f949 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 3 Jul 2014 17:59:50 +0400 Subject: [PATCH 10/16] perf kvm: Simplify exit reasons tables definitions The perf_kvm_stat struct keeps the size of a table of exit reasons in the field 'exit_reasons_size'. The field is initialized and then used by get_exit_reason() for serial access to the table, so that the calling function does not actually need to know table size. Usage of tables with 'end of sequence' marker simplifies the get_exit_reason() function. Also the patch introduces a define_exit_reasons_table, which makes it easier to define new tables. Reviewed-by: Cornelia Huck Reviewed-by: David Ahern Signed-off-by: Alexander Yarygin Acked-by: Christian Borntraeger Cc: Christian Borntraeger Cc: Cornelia Huck Cc: David Ahern Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1404395992-17095-3-git-send-email-yarygin@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 214ec0e7492b39..75f354459005cf 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -99,7 +99,6 @@ struct perf_kvm_stat { int trace_vcpu; struct exit_reasons_table *exit_reasons; - int exit_reasons_size; const char *exit_reasons_isa; struct kvm_events_ops *events_ops; @@ -158,20 +157,19 @@ static bool exit_event_end(struct perf_evsel *evsel, return kvm_entry_event(evsel); } -static struct exit_reasons_table vmx_exit_reasons[] = { - VMX_EXIT_REASONS -}; +#define define_exit_reasons_table(name, symbols) \ + static struct exit_reasons_table name[] = { \ + symbols, { -1, NULL } \ + } -static struct exit_reasons_table svm_exit_reasons[] = { - SVM_EXIT_REASONS -}; +define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); +define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); -static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code) +static const char *get_exit_reason(struct perf_kvm_stat *kvm, + struct exit_reasons_table *tbl, + u64 exit_code) { - int i = kvm->exit_reasons_size; - struct exit_reasons_table *tbl = kvm->exit_reasons; - - while (i--) { + while (tbl->reason != NULL) { if (tbl->exit_code == exit_code) return tbl->reason; tbl++; @@ -186,7 +184,8 @@ static void exit_event_decode_key(struct perf_kvm_stat *kvm, struct event_key *key, char decode[20]) { - const char *exit_reason = get_exit_reason(kvm, key->key); + const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons, + key->key); scnprintf(decode, 20, "%s", exit_reason); } @@ -862,7 +861,6 @@ static int cpu_isa_config(struct perf_kvm_stat *kvm) if (isa == 1) { kvm->exit_reasons = vmx_exit_reasons; - kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons); kvm->exit_reasons_isa = "VMX"; } @@ -1586,7 +1584,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) .sort_key = "sample", .exit_reasons = svm_exit_reasons, - .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons), .exit_reasons_isa = "SVM", }; From 65c647a65c155e69bd5765d5e454982566ac1c62 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 3 Jul 2014 17:59:51 +0400 Subject: [PATCH 11/16] perf kvm: Refactoring of cpu_isa_config() cpu_isa_config() does two different things: searching for cpuid and initializing perf_kvm_stat struct with proper parameters. Let's move initialization to a separate function cpu_isa_init(), which is used to initialize all possible ISAs and can be used to init arch-depended things. Reviewed-by: Cornelia Huck Reviewed-by: David Ahern Signed-off-by: Alexander Yarygin Acked-by: Christian Borntraeger Cc: Christian Borntraeger Cc: Cornelia Huck Cc: David Ahern Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1404395992-17095-4-git-send-email-yarygin@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 75f354459005cf..41dbeaf8cc1167 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -835,36 +835,45 @@ static int process_sample_event(struct perf_tool *tool, return 0; } +static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) +{ + if (strstr(cpuid, "Intel")) { + kvm->exit_reasons = vmx_exit_reasons; + kvm->exit_reasons_isa = "VMX"; + } else if (strstr(cpuid, "AMD")) { + kvm->exit_reasons = svm_exit_reasons; + kvm->exit_reasons_isa = "SVM"; + } else + return -ENOTSUP; + + return 0; +} + static int cpu_isa_config(struct perf_kvm_stat *kvm) { char buf[64], *cpuid; - int err, isa; + int err; if (kvm->live) { err = get_cpuid(buf, sizeof(buf)); if (err != 0) { - pr_err("Failed to look up CPU type (Intel or AMD)\n"); + pr_err("Failed to look up CPU type\n"); return err; } cpuid = buf; } else cpuid = kvm->session->header.env.cpuid; - if (strstr(cpuid, "Intel")) - isa = 1; - else if (strstr(cpuid, "AMD")) - isa = 0; - else { - pr_err("CPU %s is not supported.\n", cpuid); - return -ENOTSUP; + if (!cpuid) { + pr_err("Failed to look up CPU type\n"); + return -EINVAL; } - if (isa == 1) { - kvm->exit_reasons = vmx_exit_reasons; - kvm->exit_reasons_isa = "VMX"; - } + err = cpu_isa_init(kvm, cpuid); + if (err == -ENOTSUP) + pr_err("CPU %s is not supported.\n", cpuid); - return 0; + return err; } static bool verify_vcpu(int vcpu) @@ -1583,8 +1592,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) .report_event = "vmexit", .sort_key = "sample", - .exit_reasons = svm_exit_reasons, - .exit_reasons_isa = "SVM", }; if (argc == 1) { From f8d9ccde2be4c24bfb8787af36a59a981b00a02d Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 3 Jul 2014 18:08:22 +0400 Subject: [PATCH 12/16] perf tools: Allow to use cpuinfo on s390 This patch defines CPUINFO_PROC for s390 and implements get_cpuid(). Reviewed-by: Cornelia Huck Reviewed-by: David Ahern Signed-off-by: Alexander Yarygin Acked-by: Christian Borntraeger Cc: Christian Borntraeger Cc: Cornelia Huck Cc: David Ahern Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/87ioneo7qh.wl%yarygin@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/Makefile | 1 + tools/perf/arch/s390/util/header.c | 28 ++++++++++++++++++++++++++++ tools/perf/perf-sys.h | 1 + 3 files changed, 30 insertions(+) create mode 100644 tools/perf/arch/s390/util/header.c diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile index 15130b50dfe3be..744e629797be9c 100644 --- a/tools/perf/arch/s390/Makefile +++ b/tools/perf/arch/s390/Makefile @@ -2,3 +2,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c new file mode 100644 index 00000000000000..9fa6c3e5782c39 --- /dev/null +++ b/tools/perf/arch/s390/util/header.c @@ -0,0 +1,28 @@ +/* + * Implementation of get_cpuid(). + * + * Copyright 2014 IBM Corp. + * Author(s): Alexander Yarygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "../../util/header.h" + +int get_cpuid(char *buffer, size_t sz) +{ + const char *cpuid = "IBM/S390"; + + if (strlen(cpuid) + 1 > sz) + return -1; + + strcpy(buffer, cpuid); + return 0; +} diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h index 5268a1481d2328..937e4324ad94ed 100644 --- a/tools/perf/perf-sys.h +++ b/tools/perf/perf-sys.h @@ -54,6 +54,7 @@ #define mb() asm volatile("bcr 15,0" ::: "memory") #define wmb() asm volatile("bcr 15,0" ::: "memory") #define rmb() asm volatile("bcr 15,0" ::: "memory") +#define CPUINFO_PROC "vendor_id" #endif #ifdef __sh__ From d400a68d1f1e7a1fc7c5caf9024d4e67b218558d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 4 Jul 2014 14:43:48 +0300 Subject: [PATCH 13/16] perf tools: Convert open coded equivalents to asprintf() The following snippet V = malloc(S); if (!V) { } sprintf(V, ...) Can be easily changed to a one line: if (asprintf(&V, ...) < 0) { } Signed-off-by: Andy Shevchenko Cc: Adrian Hunter Link: http://lkml.kernel.org/r/1404474229-15272-1-git-send-email-andriy.shevchenko@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-info.c | 12 +++--------- tools/perf/util/util.c | 9 ++------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 7e6fcfe8b43853..c3bba883f5c3b3 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -191,12 +191,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps) strcmp(dent->d_name, "..") == 0 || !name_in_tp_list(dent->d_name, tps)) continue; - format = malloc(strlen(sys) + strlen(dent->d_name) + 10); - if (!format) { + if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { err = -ENOMEM; goto out; } - sprintf(format, "%s/%s/format", sys, dent->d_name); ret = stat(format, &st); free(format); if (ret < 0) @@ -217,12 +215,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps) strcmp(dent->d_name, "..") == 0 || !name_in_tp_list(dent->d_name, tps)) continue; - format = malloc(strlen(sys) + strlen(dent->d_name) + 10); - if (!format) { + if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { err = -ENOMEM; goto out; } - sprintf(format, "%s/%s/format", sys, dent->d_name); ret = stat(format, &st); if (ret >= 0) { @@ -317,12 +313,10 @@ static int record_event_files(struct tracepoint_path *tps) strcmp(dent->d_name, "ftrace") == 0 || !system_in_tp_list(dent->d_name, tps)) continue; - sys = malloc(strlen(path) + strlen(dent->d_name) + 2); - if (!sys) { + if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) { err = -ENOMEM; goto out; } - sprintf(sys, "%s/%s", path, dent->d_name); ret = stat(sys, &st); if (ret >= 0) { ssize_t size = strlen(dent->d_name) + 1; diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 95aefa78bb075a..e4132aeeb780f0 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -333,12 +333,9 @@ const char *find_tracing_dir(void) if (!debugfs) return NULL; - tracing = malloc(strlen(debugfs) + 9); - if (!tracing) + if (asprintf(&tracing, "%s/tracing", debugfs) < 0) return NULL; - sprintf(tracing, "%s/tracing", debugfs); - tracing_found = 1; return tracing; } @@ -352,11 +349,9 @@ char *get_tracing_file(const char *name) if (!tracing) return NULL; - file = malloc(strlen(tracing) + strlen(name) + 2); - if (!file) + if (asprintf(&file, "%s/%s", tracing, name) < 0) return NULL; - sprintf(file, "%s/%s", tracing, name); return file; } From 071266bf5b6a4f41250d2b26b000f1d2f9620afe Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 8 Jul 2014 12:40:11 -0300 Subject: [PATCH 14/16] perf tools: Suggest using -f to override perf.data file ownership message # id uid=0(root) gid=0(root) groups=0(root) # ls -la perf.data -rw-------. 1 acme acme 20720 Jul 8 11:35 perf.data Previously: # perf report file perf.data not owned by current user or root Now: # perf report File perf.data not owned by current user or root (use -f to override) Suggested-by: Ingo Molnar Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-0j2wuuegnhv3gljbil8ld6kx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 55de44ecebefb5..ee370a7f244498 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c @@ -65,7 +65,7 @@ static int open_file_read(struct perf_data_file *file) goto out_close; if (!file->force && st.st_uid && (st.st_uid != geteuid())) { - pr_err("file %s not owned by current user or root\n", + pr_err("File %s not owned by current user or root (use -f to override)\n", file->path); goto out_close; } From a2ea67d7b5618c868c1fe15a50af71b858d36887 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Tue, 8 Jul 2014 22:05:16 +0400 Subject: [PATCH 15/16] perf trace: Add pagefault statistics 'perf trace' can show summary of events using -S option. This commit also reports number of major/minor pagefault events in this summary. $ perf trace -s --pf all -- sleep 1 Summary of events: sleep (18604), 275 events, 99.6%, 197 minfaults, 0.000 msec syscall calls min avg max stddev (msec) (msec) (msec) (%) --------------- -------- --------- --------- --------- ------ read 2 0.000 0.001 0.002 100.00% open 3 0.004 0.005 0.007 21.13% close 3 0.001 0.001 0.001 1.37% fstat 3 0.001 0.002 0.002 10.66% mmap 8 0.002 0.004 0.006 10.69% mprotect 4 0.003 0.005 0.008 24.68% munmap 1 0.005 0.005 0.005 0.00% brk 3 0.001 0.002 0.003 28.08% access 3 0.002 0.003 0.005 24.48% nanosleep 1 1000.747 1000.747 1000.747 0.00% execve 8 0.000 0.033 0.246 91.00% arch_prctl 1 0.001 0.001 0.001 0.00% Signed-off-by: Stanislav Fomichev Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1404842716-19190-1-git-send-email-stfomichev@yandex-team.ru Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index dc7a694b61fe9a..b94dffc5fa8584 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1133,6 +1133,7 @@ struct thread_trace { u64 exit_time; bool entry_pending; unsigned long nr_events; + unsigned long pfmaj, pfmin; char *entry_str; double runtime_ms; struct { @@ -1804,8 +1805,20 @@ static int trace__pgfault(struct trace *trace, u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; struct addr_location al; char map_type = 'd'; + struct thread_trace *ttrace; thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); + ttrace = thread__trace(thread, trace->output); + if (ttrace == NULL) + return -1; + + if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) + ttrace->pfmaj++; + else + ttrace->pfmin++; + + if (trace->summary_only) + return 0; thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, sample->ip, &al); @@ -2346,6 +2359,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid); printed += fprintf(fp, "%lu events, ", ttrace->nr_events); printed += fprintf(fp, "%.1f%%", ratio); + if (ttrace->pfmaj) + printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj); + if (ttrace->pfmin) + printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin); printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); printed += thread__dump_stats(ttrace, trace, fp); From 4414a3c51028aea2ae2fe06c0377490eaa6abbfd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 8 Jul 2014 15:39:21 -0300 Subject: [PATCH 16/16] perf trace: Fix build on 32-bit systems CC /tmp/build/perf/builtin-trace.o builtin-trace.c: In function 'print_location': builtin-trace.c:1792:4: error: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'u64' [-Werror=format] builtin-trace.c:1794:3: error: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'u64' [-Werror=format] builtin-trace.c:1796:3: error: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'u64' [-Werror=format] cc1: all warnings being treated as errors make[1]: *** [/tmp/build/perf/builtin-trace.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [install-bin] Error 2 make: Leaving directory `/home/acme/git/linux/tools/perf' acme@linux-goap:~/git/linux> uname -a Linux linux-goap 3.7.10-1.16-desktop #1 SMP PREEMPT Fri May 31 20:21:23 UTC 2013 (97c14ba) i686 i686 i386 GNU/Linux Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stanislav Fomichev Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-843p3aqbw531eqiu2hah8o9p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b94dffc5fa8584..c4a5a7d7b2cf91 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1788,12 +1788,12 @@ static void print_location(FILE *f, struct perf_sample *sample, fprintf(f, "%s@", al->map->dso->long_name); if ((verbose || print_sym) && al->sym) - fprintf(f, "%s+0x%lx", al->sym->name, + fprintf(f, "%s+0x%" PRIx64, al->sym->name, al->addr - al->sym->start); else if (al->map) - fprintf(f, "0x%lx", al->addr); + fprintf(f, "0x%" PRIx64, al->addr); else - fprintf(f, "0x%lx", sample->addr); + fprintf(f, "0x%" PRIx64, sample->addr); } static int trace__pgfault(struct trace *trace,