2012-10-04 18:09:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/42] perf/core improvements and fixes

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 29a0fc9b2b6084e7a8810481df62a0fa496d8957:

perf tools: Convert to LIBELF_SUPPORT (2012-09-28 21:07:36 -0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo

for you to fetch changes up to 139c0815903de1a7865fe1d6beac5e995fefdf46:

perf hists: Add more helpers for hist entry stat (2012-10-04 13:36:18 -0300)

----------------------------------------------------------------
perf/core improvements and fixes

. Remove several cases of needless global variables, on most builtins.

. Look up thread using tid instead of pid in 'perf sched'.

. Move global variables into a perf_kvm struct, from David Ahern.

. Hists refactorings, preparatory for improved 'diff' command, from Jiri Olsa.

. Hists refactorings, preparatory for event group viewieng work, from Namhyung Kim.

. Remove double negation on optional feature macro definitions, from Namhyung Kim.

. Bash auto completion improvements, now we can auto complete the tools long
options, tracepoint event names, etc, from Namhyung Kim.

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

----------------------------------------------------------------
Arnaldo Carvalho de Melo (19):
perf trace: Use evsel->handler.func
perf inject: Remove unused 'input_name' static var
perf inject: Remove static variables
perf sched: Look up thread using tid instead of pid
perf stat: Don't use globals where not needed to
perf script: Don't use globals where not needed to
perf help: Don't use globals where not needed to
perf kmem: Don't use globals where not needed to
perf lock: Don't use globals where not needed to
perf timechart: Don't use globals where not needed to
perf buildid-cache: Don't use globals where not needed to
perf buildid-list: Don't use globals where not needed to
perf probe: Don't use globals where not needed to
perf top: Don't use globals where not needed to
perf evlist: Don't use globals where not needed to
perf record: Don't use globals where not needed to
perf inject: Don't use globals where not needed to
perf evlist: Introduce add_newtp method
perf evlist: Remove some unused methods

David Ahern (1):
perf kvm: Move global variables into a perf_kvm struct

Jiri Olsa (6):
perf hists: Add struct hists pointer to struct hist_entry
perf diff: Refactor diff displacement possition info
perf hists: Separate overhead and baseline columns
perf tools: Removing hists pair argument from output path
perf tool: Add hpp interface to enable/disable hpp column
perf diff: Removing the total_period argument from output code

Namhyung Kim (13):
perf tools: Convert to LIBUNWIND_SUPPORT
perf tools: Convert to LIBAUDIT_SUPPORT
perf tools: Convert to NEWT_SUPPORT
perf tools: Convert to GTK2_SUPPORT
perf tools: Convert to HAVE_STRLCPY
perf tools: Check existence of _get_comp_words_by_ref when bash completing
perf tools: Complete long option names of perf command
perf tools: Long option completion support for each subcommands
perf tools: Convert to BACKTRACE_SUPPORT
perf tools: Complete tracepoint event names
perf hists: Introduce struct he_stat
perf hists: Move he->stat.nr_events initialization to a template
perf hists: Add more helpers for hist entry stat

tools/perf/Makefile | 46 ++--
tools/perf/bash_completion | 50 +++-
tools/perf/builtin-buildid-cache.c | 58 ++---
tools/perf/builtin-buildid-list.c | 55 ++---
tools/perf/builtin-diff.c | 68 ++++--
tools/perf/builtin-evlist.c | 21 +-
tools/perf/builtin-help.c | 40 ++--
tools/perf/builtin-inject.c | 86 +++----
tools/perf/builtin-kmem.c | 66 ++----
tools/perf/builtin-kvm.c | 460 ++++++++++++++++++++----------------
tools/perf/builtin-lock.c | 90 +++----
tools/perf/builtin-probe.c | 26 +-
tools/perf/builtin-record.c | 27 ++-
tools/perf/builtin-report.c | 4 +-
tools/perf/builtin-sched.c | 2 +-
tools/perf/builtin-script.c | 90 ++++---
tools/perf/builtin-stat.c | 328 +++++++++++++------------
tools/perf/builtin-timechart.c | 100 ++++----
tools/perf/builtin-top.c | 11 +-
tools/perf/builtin-trace.c | 134 +++++++----
tools/perf/perf.c | 2 +-
tools/perf/ui/browsers/hists.c | 12 +-
tools/perf/ui/gtk/browser.c | 6 +-
tools/perf/ui/gtk/util.c | 2 +-
tools/perf/ui/helpline.h | 18 +-
tools/perf/ui/hist.c | 145 +++++++-----
tools/perf/ui/setup.c | 2 +-
tools/perf/ui/stdio/hist.c | 45 ++--
tools/perf/util/annotate.h | 8 +-
tools/perf/util/cache.h | 38 +--
tools/perf/util/debug.c | 2 +-
tools/perf/util/debug.h | 17 +-
tools/perf/util/evlist.c | 88 +------
tools/perf/util/evlist.h | 18 +-
tools/perf/util/hist.c | 66 ++++--
tools/perf/util/hist.h | 38 ++-
tools/perf/util/parse-options.c | 8 +
tools/perf/util/parse-options.h | 1 +
tools/perf/util/path.c | 2 +-
tools/perf/util/perf_regs.h | 4 +-
tools/perf/util/sort.h | 19 +-
tools/perf/util/unwind.h | 4 +-
tools/perf/util/util.c | 4 +-
43 files changed, 1172 insertions(+), 1139 deletions(-)


2012-10-04 18:09:06

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/42] perf help: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-help.c | 40 ++++++++++++++++++++--------------------
1 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 25c8b94..411ee56 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -30,23 +30,6 @@ enum help_format {
HELP_FORMAT_WEB,
};

-static bool show_all = false;
-static enum help_format help_format = HELP_FORMAT_NONE;
-static struct option builtin_help_options[] = {
- OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
- OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
- OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
- HELP_FORMAT_WEB),
- OPT_SET_UINT('i', "info", &help_format, "show info page",
- HELP_FORMAT_INFO),
- OPT_END(),
-};
-
-static const char * const builtin_help_usage[] = {
- "perf help [--all] [--man|--web|--info] [command]",
- NULL
-};
-
static enum help_format parse_help_format(const char *format)
{
if (!strcmp(format, "man"))
@@ -258,11 +241,13 @@ static int add_man_viewer_info(const char *var, const char *value)

static int perf_help_config(const char *var, const char *value, void *cb)
{
+ enum help_format *help_formatp = cb;
+
if (!strcmp(var, "help.format")) {
if (!value)
return config_error_nonbool(var);
- help_format = parse_help_format(value);
- if (help_format == HELP_FORMAT_NONE)
+ *help_formatp = parse_help_format(value);
+ if (*help_formatp == HELP_FORMAT_NONE)
return -1;
return 0;
}
@@ -428,12 +413,27 @@ static int show_html_page(const char *perf_cmd)

int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ bool show_all = false;
+ enum help_format help_format = HELP_FORMAT_NONE;
+ struct option builtin_help_options[] = {
+ OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
+ OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
+ OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
+ HELP_FORMAT_WEB),
+ OPT_SET_UINT('i', "info", &help_format, "show info page",
+ HELP_FORMAT_INFO),
+ OPT_END(),
+ };
+ const char * const builtin_help_usage[] = {
+ "perf help [--all] [--man|--web|--info] [command]",
+ NULL
+ };
const char *alias;
int rc = 0;

load_command_list("perf-", &main_cmds, &other_cmds);

- perf_config(perf_help_config, NULL);
+ perf_config(perf_help_config, &help_format);

argc = parse_options(argc, argv, builtin_help_options,
builtin_help_usage, 0);
--
1.7.1

2012-10-04 18:09:13

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 36/42] perf hists: Separate overhead and baseline columns

From: Jiri Olsa <[email protected]>

Currently the overhead and baseline columns are handled within single
function and the distinction is made by 'baseline hists' pointer passed
by 'struct perf_hpp::ptr'.

Since hists pointer is now part of each hist_entry, it's possible to
locate paired hists pointer directly from the passed struct hist_entry
pointer.

Also separating those 2 columns makes the code more obvious.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/hist.c | 74 ++++++++++++++++++++++++++++---------------
tools/perf/ui/stdio/hist.c | 11 +++++-
tools/perf/util/hist.h | 1 +
3 files changed, 58 insertions(+), 28 deletions(-)

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 55b9ca8..532a601 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -8,9 +8,7 @@
/* hist period print (hpp) functions */
static int hpp__header_overhead(struct perf_hpp *hpp)
{
- const char *fmt = hpp->ptr ? "Baseline" : "Overhead";
-
- return scnprintf(hpp->buf, hpp->size, fmt);
+ return scnprintf(hpp->buf, hpp->size, "Overhead");
}

static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
@@ -22,17 +20,6 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
{
double percent = 100.0 * he->period / hpp->total_period;

- if (hpp->ptr) {
- struct hists *old_hists = hpp->ptr;
- u64 total_period = old_hists->stats.total_period;
- u64 base_period = he->pair ? he->pair->period : 0;
-
- if (total_period)
- percent = 100.0 * base_period / total_period;
- else
- percent = 0.0;
- }
-
return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
}

@@ -41,17 +28,6 @@ static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
double percent = 100.0 * he->period / hpp->total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";

- if (hpp->ptr) {
- struct hists *old_hists = hpp->ptr;
- u64 total_period = old_hists->stats.total_period;
- u64 base_period = he->pair ? he->pair->period : 0;
-
- if (total_period)
- percent = 100.0 * base_period / total_period;
- else
- percent = 0.0;
- }
-
return scnprintf(hpp->buf, hpp->size, fmt, percent);
}

@@ -159,6 +135,47 @@ static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
return scnprintf(hpp->buf, hpp->size, fmt, percent);
}

+static int hpp__header_baseline(struct perf_hpp *hpp)
+{
+ return scnprintf(hpp->buf, hpp->size, "Baseline");
+}
+
+static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
+{
+ return 8;
+}
+
+static double baseline_percent(struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ struct hists *pair_hists = pair ? pair->hists : NULL;
+ double percent = 0.0;
+
+ if (pair) {
+ u64 total_period = pair_hists->stats.total_period;
+ u64 base_period = pair->period;
+
+ percent = 100.0 * base_period / total_period;
+ }
+
+ return percent;
+}
+
+static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ double percent = baseline_percent(he);
+
+ return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+}
+
+static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ double percent = baseline_percent(he);
+ const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
+
+ return scnprintf(hpp->buf, hpp->size, fmt, percent);
+}
+
static int hpp__header_samples(struct perf_hpp *hpp)
{
const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
@@ -269,6 +286,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
.entry = hpp__entry_ ## _name

struct perf_hpp_fmt perf_hpp__format[] = {
+ { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
{ .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
@@ -302,6 +320,8 @@ void perf_hpp__init(bool need_pair, bool show_displacement)
perf_hpp__format[PERF_HPP__PERIOD].cond = true;

if (need_pair) {
+ perf_hpp__format[PERF_HPP__OVERHEAD].cond = false;
+ perf_hpp__format[PERF_HPP__BASELINE].cond = true;
perf_hpp__format[PERF_HPP__DELTA].cond = true;

if (show_displacement)
@@ -321,6 +341,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
const char *sep = symbol_conf.field_sep;
char *start = hpp->buf;
int i, ret;
+ bool first = true;

if (symbol_conf.exclude_other && !he->parent)
return 0;
@@ -329,9 +350,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
if (!perf_hpp__format[i].cond)
continue;

- if (!sep || i > 0) {
+ if (!sep || !first) {
ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
advance_hpp(hpp, ret);
+ first = false;
}

if (color && perf_hpp__format[i].color)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index d7405f0..0aa6776 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -353,6 +353,7 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
.size = sizeof(bf),
.ptr = pair,
};
+ bool first = true;

init_rem_hits();

@@ -364,8 +365,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
if (!perf_hpp__format[idx].cond)
continue;

- if (idx)
+ if (!first)
fprintf(fp, "%s", sep ?: " ");
+ else
+ first = false;

perf_hpp__format[idx].header(&dummy_hpp);
fprintf(fp, "%s", bf);
@@ -400,6 +403,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
if (sep)
goto print_entries;

+ first = true;
+
fprintf(fp, "# ");
for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
unsigned int i;
@@ -407,8 +412,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
if (!perf_hpp__format[idx].cond)
continue;

- if (idx)
+ if (!first)
fprintf(fp, "%s", sep ?: " ");
+ else
+ first = false;

width = perf_hpp__format[idx].width(&dummy_hpp);
for (i = 0; i < width; i++)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index efb8fc8..b1a2b9d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -133,6 +133,7 @@ struct perf_hpp_fmt {
extern struct perf_hpp_fmt perf_hpp__format[];

enum {
+ PERF_HPP__BASELINE,
PERF_HPP__OVERHEAD,
PERF_HPP__OVERHEAD_SYS,
PERF_HPP__OVERHEAD_US,
--
1.7.1

2012-10-04 18:09:17

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 38/42] perf tool: Add hpp interface to enable/disable hpp column

From: Jiri Olsa <[email protected]>

Adding perf_hpp__column_enable function to enable/disable hists column
and removing diff command specific stuff 'need_pair and
show_displacement' from hpp code.

The diff command now enables/disables columns separately according to
the user arguments. This will be helpful in future patches where more
columns are added into diff output.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-diff.c | 18 +++++++++++++++++-
tools/perf/builtin-report.c | 2 +-
tools/perf/ui/browsers/hists.c | 2 +-
tools/perf/ui/gtk/browser.c | 2 +-
tools/perf/ui/hist.c | 15 ++++++---------
tools/perf/ui/setup.c | 2 +-
tools/perf/util/hist.h | 3 ++-
7 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 413c65a..a0b531c 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -256,6 +256,21 @@ static const struct option options[] = {
OPT_END()
};

+static void ui_init(void)
+{
+ perf_hpp__init();
+
+ /* No overhead column. */
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
+
+ /* Display baseline/delta/displacement columns. */
+ perf_hpp__column_enable(PERF_HPP__BASELINE, true);
+ perf_hpp__column_enable(PERF_HPP__DELTA, true);
+
+ if (show_displacement)
+ perf_hpp__column_enable(PERF_HPP__DISPL, true);
+}
+
int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
{
sort_order = diff__default_sort_order;
@@ -278,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
if (symbol__init() < 0)
return -1;

- perf_hpp__init(true, show_displacement);
+ ui_init();
+
setup_sorting(diff_usage, options);
setup_pager();

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 95e7ea8..a61725d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
setup_browser(true);
else {
use_browser = 0;
- perf_hpp__init(false, false);
+ perf_hpp__init();
}

setup_sorting(report_usage, options);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a21f40b..bbd11c2 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -584,7 +584,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)

void hist_browser__init_hpp(void)
{
- perf_hpp__init(false, false);
+ perf_hpp__init();

perf_hpp__format[PERF_HPP__OVERHEAD].color =
hist_browser__hpp_color_overhead;
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 7ff99ec..2bc08f6 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -73,7 +73,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)

void perf_gtk__init_hpp(void)
{
- perf_hpp__init(false, false);
+ perf_hpp__init();

perf_hpp__format[PERF_HPP__OVERHEAD].color =
perf_gtk__hpp_color_overhead;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 6b0138e..e8853f7 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -302,7 +302,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
#undef HPP__COLOR_PRINT_FNS
#undef HPP__PRINT_FNS

-void perf_hpp__init(bool need_pair, bool show_displacement)
+void perf_hpp__init(void)
{
if (symbol_conf.show_cpu_utilization) {
perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
@@ -319,15 +319,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement)

if (symbol_conf.show_total_period)
perf_hpp__format[PERF_HPP__PERIOD].cond = true;
+}

- if (need_pair) {
- perf_hpp__format[PERF_HPP__OVERHEAD].cond = false;
- perf_hpp__format[PERF_HPP__BASELINE].cond = true;
- perf_hpp__format[PERF_HPP__DELTA].cond = true;
-
- if (show_displacement)
- perf_hpp__format[PERF_HPP__DISPL].cond = true;
- }
+void perf_hpp__column_enable(unsigned col, bool enable)
+{
+ BUG_ON(col >= PERF_HPP__MAX_INDEX);
+ perf_hpp__format[col].cond = enable;
}

static inline void advance_hpp(struct perf_hpp *hpp, int inc)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index bd7d460..ebb4cc1 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,7 +30,7 @@ void setup_browser(bool fallback_to_pager)
if (fallback_to_pager)
setup_pager();

- perf_hpp__init(false, false);
+ perf_hpp__init();
break;
}
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index b83a226..a7f69d6 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -147,7 +147,8 @@ enum {
PERF_HPP__MAX_INDEX
};

-void perf_hpp__init(bool need_pair, bool show_displacement);
+void perf_hpp__init(void);
+void perf_hpp__column_enable(unsigned col, bool enable);
int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
bool color);

--
1.7.1

2012-10-04 18:09:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/42] perf tools: Convert to LIBELF_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without libelf, we can set NO_LIBELF=1 as a argument
of make. It then defines NO_LIBELF_SUPPORT macro for C code to do the
proper handling. However it usually used in a negative semantics -
e.g. #ifndef - so we saw double negations which can be misleading.
Convert it to a positive form to make it more readable.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 7 +++----
tools/perf/builtin-inject.c | 2 +-
tools/perf/perf.c | 2 +-
tools/perf/util/generate-cmdlist.sh | 4 ++--
tools/perf/util/map.c | 2 +-
tools/perf/util/symbol.h | 10 +++++-----
6 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9cd4913..1df0917 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -503,8 +503,6 @@ ifneq ($(OUTPUT),)
endif

ifdef NO_LIBELF
-BASIC_CFLAGS += -DNO_LIBELF_SUPPORT
-
EXTLIBS := $(filter-out -lelf,$(EXTLIBS))

# Remove ELF/DWARF dependent codes
@@ -519,9 +517,10 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
LIB_OBJS += $(OUTPUT)util/symbol-minimal.o

else # NO_LIBELF
+BASIC_CFLAGS += -DLIBELF_SUPPORT

-ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
- BASIC_CFLAGS += -DLIBELF_NO_MMAP
+ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
+ BASIC_CFLAGS += -DLIBELF_MMAP
endif

ifndef NO_DWARF
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 1eaa661..b5ab084 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -194,7 +194,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
* account this as unresolved.
*/
} else {
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
pr_warning("no symbols found in %s, maybe "
"install a debug package?\n",
al.map->dso->long_name);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index fc2f770..dacae4b 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -48,7 +48,7 @@ static struct cmd_struct commands[] = {
{ "version", cmd_version, 0 },
{ "script", cmd_script, 0 },
{ "sched", cmd_sched, 0 },
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
{ "probe", cmd_probe, 0 },
#endif
{ "kmem", cmd_kmem, 0 },
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 389590c..3ac3803 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
}' "Documentation/perf-$cmd.txt"
done

-echo "#ifndef NO_LIBELF_SUPPORT"
+echo "#ifdef LIBELF_SUPPORT"
sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
sort |
while read cmd
@@ -35,5 +35,5 @@ do
p
}' "Documentation/perf-$cmd.txt"
done
-echo "#endif /* NO_LIBELF_SUPPORT */"
+echo "#endif /* LIBELF_SUPPORT */"
echo "};"
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index ead5316..6109fa4 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -162,7 +162,7 @@ int map__load(struct map *self, symbol_filter_t filter)
pr_warning(", continuing without symbols\n");
return -1;
} else if (nr == 0) {
-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
const size_t len = strlen(name);
const size_t real_len = len - sizeof(DSO__DELETED);

diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b441b07..8b6ef7f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -12,7 +12,7 @@
#include <byteswap.h>
#include <libgen.h>

-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
#include <libelf.h>
#include <gelf.h>
#include <elf.h>
@@ -46,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
* libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
* for newer versions we can use mmap to reduce memory usage:
*/
-#ifdef LIBELF_NO_MMAP
-# define PERF_ELF_C_READ_MMAP ELF_C_READ
-#else
+#ifdef LIBELF_MMAP
# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#else
+# define PERF_ELF_C_READ_MMAP ELF_C_READ
#endif

#ifndef DMGL_PARAMS
@@ -233,7 +233,7 @@ struct symsrc {
int fd;
enum dso_binary_type type;

-#ifndef NO_LIBELF_SUPPORT
+#ifdef LIBELF_SUPPORT
Elf *elf;
GElf_Ehdr ehdr;

--
1.7.1

2012-10-04 18:09:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 21/42] perf probe: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-probe.c | 26 ++++++++++++--------------
1 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 118aa89..de38a03 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -250,19 +250,20 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
return 0;
}

-static const char * const probe_usage[] = {
- "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
- "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
- "perf probe [<options>] --del '[GROUP:]EVENT' ...",
- "perf probe --list",
+int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+ const char * const probe_usage[] = {
+ "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
+ "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
+ "perf probe [<options>] --del '[GROUP:]EVENT' ...",
+ "perf probe --list",
#ifdef DWARF_SUPPORT
- "perf probe [<options>] --line 'LINEDESC'",
- "perf probe [<options>] --vars 'PROBEPOINT'",
+ "perf probe [<options>] --line 'LINEDESC'",
+ "perf probe [<options>] --vars 'PROBEPOINT'",
#endif
- NULL
+ NULL
};
-
-static const struct option options[] = {
+ const struct option options[] = {
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show parsed arguments, etc)"),
OPT_BOOLEAN('l', "list", &params.list_events,
@@ -325,10 +326,7 @@ static const struct option options[] = {
OPT_CALLBACK('x', "exec", NULL, "executable|path",
"target executable name or path", opt_set_target),
OPT_END()
-};
-
-int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
-{
+ };
int ret;

argc = parse_options(argc, argv, options, probe_usage,
--
1.7.1

2012-10-04 18:09:47

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 40/42] perf hists: Introduce struct he_stat

From: Namhyung Kim <[email protected]>

The struct he_stat is for separating out statistics data of a hist
entry. It is required for later changes.

It's just a mechanical change and should have no functional differences.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Arun Sharma <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/browsers/hists.c | 8 +++---
tools/perf/ui/gtk/browser.c | 2 +-
tools/perf/ui/hist.c | 30 +++++++++++-----------
tools/perf/ui/stdio/hist.c | 2 +-
tools/perf/util/hist.c | 52 +++++++++++++++++++++------------------
tools/perf/util/sort.h | 16 +++++++----
6 files changed, 59 insertions(+), 51 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index d359795..0568536 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -570,7 +570,7 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \
struct hist_entry *he) \
{ \
struct hists *hists = he->hists; \
- double percent = 100.0 * he->_field / hists->stats.total_period;\
+ double percent = 100.0 * he->stat._field / hists->stats.total_period; \
*(double *)hpp->ptr = percent; \
return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \
}
@@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
folded_sign = hist_entry__folded(he);

hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
- percent = (he->period * 100.0) / browser->hists->stats.total_period;
+ percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;

if (symbol_conf.use_callchain)
printed += fprintf(fp, "%c ", folded_sign);
@@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
printed += fprintf(fp, " %5.2f%%", percent);

if (symbol_conf.show_nr_samples)
- printed += fprintf(fp, " %11u", he->nr_events);
+ printed += fprintf(fp, " %11u", he->stat.nr_events);

if (symbol_conf.show_total_period)
- printed += fprintf(fp, " %12" PRIu64, he->period);
+ printed += fprintf(fp, " %12" PRIu64, he->stat.period);

printed += fprintf(fp, "%s\n", rtrim(s));

diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 3cbb1d6..4125c62 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -50,7 +50,7 @@ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \
struct hist_entry *he) \
{ \
struct hists *hists = he->hists; \
- double percent = 100.0 * he->_field / hists->stats.total_period; \
+ double percent = 100.0 * he->stat._field / hists->stats.total_period; \
const char *markup; \
int ret = 0; \
\
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 7f04339..f5a1e4f 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -19,7 +19,7 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
}
@@ -27,7 +27,7 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -48,7 +48,7 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_sys / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
}
@@ -56,7 +56,7 @@ static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_sys / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -77,7 +77,7 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_us / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_us / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
}
@@ -85,7 +85,7 @@ static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_us / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -105,7 +105,7 @@ static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_guest_sys / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
}
@@ -114,7 +114,7 @@ static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_guest_sys / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -134,7 +134,7 @@ static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_guest_us / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
}
@@ -143,7 +143,7 @@ static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
struct hist_entry *he)
{
struct hists *hists = he->hists;
- double percent = 100.0 * he->period_guest_us / hists->stats.total_period;
+ double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -167,7 +167,7 @@ static double baseline_percent(struct hist_entry *he)

if (pair) {
u64 total_period = pair_hists->stats.total_period;
- u64 base_period = pair->period;
+ u64 base_period = pair->stat.period;

percent = 100.0 * base_period / total_period;
}
@@ -206,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
{
const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;

- return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events);
+ return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
}

static int hpp__header_period(struct perf_hpp *hpp)
@@ -225,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
{
const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;

- return scnprintf(hpp->buf, hpp->size, fmt, he->period);
+ return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
}

static int hpp__header_delta(struct perf_hpp *hpp)
@@ -253,11 +253,11 @@ static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)

old_total = pair_hists ? pair_hists->stats.total_period : 0;
if (old_total > 0 && pair)
- old_percent = 100.0 * pair->period / old_total;
+ old_percent = 100.0 * pair->stat.period / old_total;

new_total = hists->stats.total_period;
if (new_total > 0)
- new_percent = 100.0 * he->period / new_total;
+ new_percent = 100.0 * he->stat.period / new_total;

diff = new_percent - old_percent;
if (fabs(diff) >= 0.01)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 850c6d2..fbd4e32 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -271,7 +271,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
{
switch (callchain_param.mode) {
case CHAIN_GRAPH_REL:
- return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
+ return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
left_margin);
break;
case CHAIN_GRAPH_ABS:
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 040f34c..3197f3f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -135,16 +135,16 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
{
switch (cpumode) {
case PERF_RECORD_MISC_KERNEL:
- he->period_sys += period;
+ he->stat.period_sys += period;
break;
case PERF_RECORD_MISC_USER:
- he->period_us += period;
+ he->stat.period_us += period;
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
- he->period_guest_sys += period;
+ he->stat.period_guest_sys += period;
break;
case PERF_RECORD_MISC_GUEST_USER:
- he->period_guest_us += period;
+ he->stat.period_guest_us += period;
break;
default:
break;
@@ -153,13 +153,13 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,

static void hist_entry__decay(struct hist_entry *he)
{
- he->period = (he->period * 7) / 8;
- he->nr_events = (he->nr_events * 7) / 8;
+ he->stat.period = (he->stat.period * 7) / 8;
+ he->stat.nr_events = (he->stat.nr_events * 7) / 8;
}

static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
{
- u64 prev_period = he->period;
+ u64 prev_period = he->stat.period;

if (prev_period == 0)
return true;
@@ -167,9 +167,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
hist_entry__decay(he);

if (!he->filtered)
- hists->stats.total_period -= prev_period - he->period;
+ hists->stats.total_period -= prev_period - he->stat.period;

- return he->period == 0;
+ return he->stat.period == 0;
}

static void __hists__decay_entries(struct hists *hists, bool zap_user,
@@ -223,7 +223,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)

if (he != NULL) {
*he = *template;
- he->nr_events = 1;
+ he->stat.nr_events = 1;
if (he->ms.map)
he->ms.map->referenced = true;
if (symbol_conf.use_callchain)
@@ -238,7 +238,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
if (!h->filtered) {
hists__calc_col_len(hists, h);
++hists->nr_entries;
- hists->stats.total_period += h->period;
+ hists->stats.total_period += h->stat.period;
}
}

@@ -270,8 +270,8 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
cmp = hist_entry__cmp(entry, he);

if (!cmp) {
- he->period += period;
- ++he->nr_events;
+ he->stat.period += period;
+ ++he->stat.nr_events;

/* If the map of an existing hist_entry has
* become out-of-date due to an exec() or
@@ -321,7 +321,9 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
.cpu = al->cpu,
.ip = bi->to.addr,
.level = al->level,
- .period = period,
+ .stat = {
+ .period = period,
+ },
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
.branch_info = bi,
@@ -344,7 +346,9 @@ struct hist_entry *__hists__add_entry(struct hists *self,
.cpu = al->cpu,
.ip = al->addr,
.level = al->level,
- .period = period,
+ .stat = {
+ .period = period,
+ },
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
.hists = self,
@@ -412,12 +416,12 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
cmp = hist_entry__collapse(iter, he);

if (!cmp) {
- iter->period += he->period;
- iter->period_sys += he->period_sys;
- iter->period_us += he->period_us;
- iter->period_guest_sys += he->period_guest_sys;
- iter->period_guest_us += he->period_guest_us;
- iter->nr_events += he->nr_events;
+ iter->stat.period += he->stat.period;
+ iter->stat.period_sys += he->stat.period_sys;
+ iter->stat.period_us += he->stat.period_us;
+ iter->stat.period_guest_sys += he->stat.period_guest_sys;
+ iter->stat.period_guest_us += he->stat.period_guest_us;
+ iter->stat.nr_events += he->stat.nr_events;

if (symbol_conf.use_callchain) {
callchain_cursor_reset(&callchain_cursor);
@@ -520,7 +524,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node);

- if (he->period > iter->period)
+ if (he->stat.period > iter->stat.period)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -581,8 +585,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
if (h->ms.unfolded)
hists->nr_entries += h->nr_rows;
h->row_offset = 0;
- hists->stats.total_period += h->period;
- hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
+ hists->stats.total_period += h->stat.period;
+ hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;

hists__calc_col_len(hists, h);
}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index f070b52..5786f32 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
extern struct sort_entry sort_sym_to;
extern enum sort_type sort__first_dimension;

+struct he_stat {
+ u64 period;
+ u64 period_sys;
+ u64 period_us;
+ u64 period_guest_sys;
+ u64 period_guest_us;
+ u32 nr_events;
+};
+
/**
* struct hist_entry - histogram entry
*
@@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
struct hist_entry {
struct rb_node rb_node_in;
struct rb_node rb_node;
- u64 period;
- u64 period_sys;
- u64 period_us;
- u64 period_guest_sys;
- u64 period_guest_us;
+ struct he_stat stat;
struct map_symbol ms;
struct thread *thread;
u64 ip;
s32 cpu;
- u32 nr_events;

/* XXX These two should move to some tree widget lib */
u16 row_offset;
--
1.7.1

2012-10-04 18:09:59

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 41/42] perf hists: Move he->stat.nr_events initialization to a template

From: Namhyung Kim <[email protected]>

Since it is set to 1 for a new hist entry, no need to set to separately.
Move it to a template entry.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Arun Sharma <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/hist.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 3197f3f..02476cb 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -223,7 +223,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)

if (he != NULL) {
*he = *template;
- he->stat.nr_events = 1;
+
if (he->ms.map)
he->ms.map->referenced = true;
if (symbol_conf.use_callchain)
@@ -323,6 +323,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
.level = al->level,
.stat = {
.period = period,
+ .nr_events = 1,
},
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
@@ -348,6 +349,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
.level = al->level,
.stat = {
.period = period,
+ .nr_events = 1,
},
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
--
1.7.1

2012-10-04 18:10:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 42/42] perf hists: Add more helpers for hist entry stat

From: Namhyung Kim <[email protected]>

Add and use he_stat__add_{period,stat} for calculating hist entry's
stat. It will be used for accumulated stats later as well.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Arun Sharma <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/hist.c | 26 ++++++++++++++++++--------
1 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 02476cb..277947a 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -151,6 +151,22 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
}
}

+static void he_stat__add_period(struct he_stat *he_stat, u64 period)
+{
+ he_stat->period += period;
+ he_stat->nr_events += 1;
+}
+
+static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
+{
+ dest->period += src->period;
+ dest->period_sys += src->period_sys;
+ dest->period_us += src->period_us;
+ dest->period_guest_sys += src->period_guest_sys;
+ dest->period_guest_us += src->period_guest_us;
+ dest->nr_events += src->nr_events;
+}
+
static void hist_entry__decay(struct hist_entry *he)
{
he->stat.period = (he->stat.period * 7) / 8;
@@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
cmp = hist_entry__cmp(entry, he);

if (!cmp) {
- he->stat.period += period;
- ++he->stat.nr_events;
+ he_stat__add_period(&he->stat, period);

/* If the map of an existing hist_entry has
* become out-of-date due to an exec() or
@@ -418,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
cmp = hist_entry__collapse(iter, he);

if (!cmp) {
- iter->stat.period += he->stat.period;
- iter->stat.period_sys += he->stat.period_sys;
- iter->stat.period_us += he->stat.period_us;
- iter->stat.period_guest_sys += he->stat.period_guest_sys;
- iter->stat.period_guest_us += he->stat.period_guest_us;
- iter->stat.nr_events += he->stat.nr_events;
+ he_stat__add_stat(&iter->stat, &he->stat);

if (symbol_conf.use_callchain) {
callchain_cursor_reset(&callchain_cursor);
--
1.7.1

2012-10-04 18:09:45

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 28/42] perf tools: Long option completion support for each subcommands

From: Namhyung Kim <[email protected]>

Add internal --list-opts option to print all of long option names to
stdout so that it can be used for bash completion engine.

Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/bash_completion | 9 +++++++--
tools/perf/util/parse-options.c | 8 ++++++++
tools/perf/util/parse-options.h | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index bef06f0..5c355ab 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -33,8 +33,13 @@ _perf()
fi
# List possible events for -e option
elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
- cmds=$($cmd list --raw-dump)
- COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+ evts=$($cmd list --raw-dump)
+ COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
+ # List long option names
+ elif [[ $cur == --* ]]; then
+ subcmd=${COMP_WORDS[1]}
+ opts=$($cmd $subcmd --list-opts)
+ COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
# Fall down to list regular files
else
_filedir
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 443fc11..2bc9e70 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
return usage_with_options_internal(usagestr, options, 1);
if (internal_help && !strcmp(arg + 2, "help"))
return parse_options_usage(usagestr, options);
+ if (!strcmp(arg + 2, "list-opts"))
+ return PARSE_OPT_LIST;
switch (parse_long_opt(ctx, arg + 2, options)) {
case -1:
return parse_options_usage(usagestr, options);
@@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
exit(129);
case PARSE_OPT_DONE:
break;
+ case PARSE_OPT_LIST:
+ while (options->type != OPTION_END) {
+ printf("--%s ", options->long_name);
+ options++;
+ }
+ exit(130);
default: /* PARSE_OPT_UNKNOWN */
if (ctx.argv[0][1] == '-') {
error("unknown option `%s'", ctx.argv[0] + 2);
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index abc31a1..7bb5999 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
enum {
PARSE_OPT_HELP = -1,
PARSE_OPT_DONE,
+ PARSE_OPT_LIST,
PARSE_OPT_UNKNOWN,
};

--
1.7.1

2012-10-04 18:11:02

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 39/42] perf diff: Removing the total_period argument from output code

From: Jiri Olsa <[email protected]>

The total_period is available in struct hists data via the 'struct
hist_entry::hists' pointer. There's no need to carry it through the
output code path.

Removing 'struct perf_hpp::total_period' pointer, because it's no longer
needed.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/browsers/hists.c | 4 ++--
tools/perf/ui/gtk/browser.c | 4 ++--
tools/perf/ui/hist.c | 37 ++++++++++++++++++++++++++-----------
tools/perf/ui/stdio/hist.c | 15 +++++----------
tools/perf/util/hist.h | 1 -
5 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index bbd11c2..d359795 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \
struct hist_entry *he) \
{ \
- double percent = 100.0 * he->_field / hpp->total_period; \
+ struct hists *hists = he->hists; \
+ double percent = 100.0 * he->_field / hists->stats.total_period;\
*(double *)hpp->ptr = percent; \
return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \
}
@@ -624,7 +625,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
struct perf_hpp hpp = {
.buf = s,
.size = sizeof(s),
- .total_period = browser->hists->stats.total_period,
};

ui_browser__gotorc(&browser->b, row, 0);
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 2bc08f6..3cbb1d6 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent)
static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \
struct hist_entry *he) \
{ \
- double percent = 100.0 * he->_field / hpp->total_period; \
+ struct hists *hists = he->hists; \
+ double percent = 100.0 * he->_field / hists->stats.total_period; \
const char *markup; \
int ret = 0; \
\
@@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
struct perf_hpp hpp = {
.buf = s,
.size = sizeof(s),
- .total_period = hists->stats.total_period,
};

nr_cols = 0;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index e8853f7..7f04339 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -18,14 +18,16 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)

static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period / hists->stats.total_period;

return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
}

static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -45,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)

static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period_sys / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_sys / hists->stats.total_period;
+
return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
}

static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period_sys / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_sys / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -71,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)

static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period_us / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_us / hists->stats.total_period;
+
return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
}

static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
{
- double percent = 100.0 * he->period_us / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_us / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -96,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
struct hist_entry *he)
{
- double percent = 100.0 * he->period_guest_sys / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_guest_sys / hists->stats.total_period;
+
return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
}

static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
struct hist_entry *he)
{
- double percent = 100.0 * he->period_guest_sys / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_guest_sys / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -122,14 +133,17 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
struct hist_entry *he)
{
- double percent = 100.0 * he->period_guest_us / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_guest_us / hists->stats.total_period;
+
return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
}

static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
struct hist_entry *he)
{
- double percent = 100.0 * he->period_guest_us / hpp->total_period;
+ struct hists *hists = he->hists;
+ double percent = 100.0 * he->period_guest_us / hists->stats.total_period;
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";

return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -230,6 +244,7 @@ static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
{
struct hist_entry *pair = he->pair;
struct hists *pair_hists = pair ? pair->hists : NULL;
+ struct hists *hists = he->hists;
u64 old_total, new_total;
double old_percent = 0, new_percent = 0;
double diff;
@@ -240,7 +255,7 @@ static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
if (old_total > 0 && pair)
old_percent = 100.0 * pair->period / old_total;

- new_total = hpp->total_period;
+ new_total = hists->stats.total_period;
if (new_total > 0)
new_percent = 100.0 * he->period / new_total;

diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 1340c93..850c6d2 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -292,9 +292,10 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,

static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
struct hists *hists,
- u64 total_period, FILE *fp)
+ FILE *fp)
{
int left_margin = 0;
+ u64 total_period = hists->stats.total_period;

if (sort__first_dimension == SORT_COMM) {
struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
@@ -307,14 +308,13 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
}

static int hist_entry__fprintf(struct hist_entry *he, size_t size,
- struct hists *hists, u64 total_period, FILE *fp)
+ struct hists *hists, FILE *fp)
{
char bf[512];
int ret;
struct perf_hpp hpp = {
.buf = bf,
.size = size,
- .total_period = total_period,
};
bool color = !symbol_conf.field_sep;

@@ -327,8 +327,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
ret = fprintf(fp, "%s\n", bf);

if (symbol_conf.use_callchain)
- ret += hist_entry__callchain_fprintf(he, hists,
- total_period, fp);
+ ret += hist_entry__callchain_fprintf(he, hists, fp);

return ret;
}
@@ -339,7 +338,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
struct sort_entry *se;
struct rb_node *nd;
size_t ret = 0;
- u64 total_period;
unsigned int width;
const char *sep = symbol_conf.field_sep;
const char *col_width = symbol_conf.col_width_list_str;
@@ -441,16 +439,13 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
goto out;

print_entries:
- total_period = hists->stats.total_period;
-
for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

if (h->filtered)
continue;

- ret += hist_entry__fprintf(h, max_cols, hists,
- total_period, fp);
+ ret += hist_entry__fprintf(h, max_cols, hists, fp);

if (max_rows && ++nr_rows >= max_rows)
goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a7f69d6..66cb31f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -117,7 +117,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
struct perf_hpp {
char *buf;
size_t size;
- u64 total_period;
const char *sep;
void *ptr;
};
--
1.7.1

2012-10-04 18:09:42

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 22/42] perf top: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-top.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e434a16..f0c1c4f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1159,11 +1159,6 @@ setup:
return 0;
}

-static const char * const top_usage[] = {
- "perf top [<options>]",
- NULL
-};
-
int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct perf_evsel *pos;
@@ -1250,6 +1245,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
OPT_END()
};
+ const char * const top_usage[] = {
+ "perf top [<options>]",
+ NULL
+ };

top.evlist = perf_evlist__new(NULL, NULL);
if (top.evlist == NULL)
--
1.7.1

2012-10-04 18:12:08

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 35/42] perf diff: Refactor diff displacement possition info

From: Jiri Olsa <[email protected]>

Moving the position calculation into the diff command, so the position
as prepared inside struct hist_entry data and there's no need to compute
in the output display path.

Removing 'displacement' from struct perf_hpp as it is no longer needed.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-diff.c | 49 ++++++++++++++++++++++++++++---------------
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/ui/hist.c | 8 ++++--
tools/perf/ui/stdio/hist.c | 17 ++------------
tools/perf/util/hist.h | 4 +--
tools/perf/util/sort.h | 2 +-
7 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 761f419..5cb577a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -70,8 +70,8 @@ static struct perf_tool tool = {
.ordering_requires_timestamps = true,
};

-static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
- struct hist_entry *he)
+static void insert_hist_entry_by_name(struct rb_root *root,
+ struct hist_entry *he)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
@@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
}

-static void hists__resort_entries(struct hists *self)
+static void hists__name_resort(struct hists *self, bool sort)
{
unsigned long position = 1;
struct rb_root tmp = RB_ROOT;
@@ -100,12 +100,16 @@ static void hists__resort_entries(struct hists *self)
struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);

next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &self->entries);
n->position = position++;
- perf_session__insert_hist_entry_by_name(&tmp, n);
+
+ if (sort) {
+ rb_erase(&n->rb_node, &self->entries);
+ insert_hist_entry_by_name(&tmp, n);
+ }
}

- self->entries = tmp;
+ if (sort)
+ self->entries = tmp;
}

static struct hist_entry *hists__find_entry(struct hists *self,
@@ -121,7 +125,7 @@ static struct hist_entry *hists__find_entry(struct hists *self,
n = n->rb_left;
else if (cmp > 0)
n = n->rb_right;
- else
+ else
return iter;
}

@@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
return NULL;
}

+static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
+{
+ struct perf_evsel *evsel;
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ struct hists *hists = &evsel->hists;
+
+ hists__output_resort(hists);
+
+ /*
+ * The hists__name_resort only sets possition
+ * if name is false.
+ */
+ if (name || ((!name) && show_displacement))
+ hists__name_resort(hists, name);
+ }
+}
+
static int __cmd_diff(void)
{
int ret, i;
@@ -176,15 +198,8 @@ static int __cmd_diff(void)
evlist_old = older->evlist;
evlist_new = newer->evlist;

- list_for_each_entry(evsel, &evlist_new->entries, node)
- hists__output_resort(&evsel->hists);
-
- list_for_each_entry(evsel, &evlist_old->entries, node) {
- hists__output_resort(&evsel->hists);
-
- if (show_displacement)
- hists__resort_entries(&evsel->hists);
- }
+ perf_evlist__resort_hists(evlist_old, true);
+ perf_evlist__resort_hists(evlist_new, false);

list_for_each_entry(evsel, &evlist_new->entries, node) {
struct perf_evsel *evsel_old;
@@ -200,7 +215,7 @@ static int __cmd_diff(void)

hists__match(&evsel_old->hists, &evsel->hists);
hists__fprintf(&evsel->hists, &evsel_old->hists,
- show_displacement, true, 0, 0, stdout);
+ true, 0, 0, stdout);
}

out_delete:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1da243d..6748cac 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
const char *evname = perf_evsel__name(pos);

hists__fprintf_nr_sample_events(hists, evname, stdout);
- hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
+ hists__fprintf(hists, NULL, true, 0, 0, stdout);
fprintf(stdout, "\n\n");
}

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f0c1c4f..3571158 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
hists__output_recalc_col_len(&top->sym_evsel->hists,
top->winsize.ws_row - 3);
putchar('\n');
- hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
+ hists__fprintf(&top->sym_evsel->hists, NULL, false,
top->winsize.ws_row - 4 - printed, win_width, stdout);
}

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index e3f8cd4..55b9ca8 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -244,13 +244,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
}

static int hpp__entry_displ(struct perf_hpp *hpp,
- struct hist_entry *he __maybe_unused)
+ struct hist_entry *he)
{
+ struct hist_entry *pair = he->pair;
+ long displacement = pair ? pair->position - he->position : 0;
const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
char buf[32] = " ";

- if (hpp->displacement)
- scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement);
+ if (displacement)
+ scnprintf(buf, sizeof(buf), "%+4ld", displacement);

return scnprintf(hpp->buf, hpp->size, fmt, buf);
}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 882461a..d7405f0 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -308,7 +308,7 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,

static int hist_entry__fprintf(struct hist_entry *he, size_t size,
struct hists *hists, struct hists *pair_hists,
- long displacement, u64 total_period, FILE *fp)
+ u64 total_period, FILE *fp)
{
char bf[512];
int ret;
@@ -316,7 +316,6 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
.buf = bf,
.size = size,
.total_period = total_period,
- .displacement = displacement,
.ptr = pair_hists,
};
bool color = !symbol_conf.field_sep;
@@ -337,15 +336,13 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
}

size_t hists__fprintf(struct hists *hists, struct hists *pair,
- bool show_displacement, bool show_header, int max_rows,
+ bool show_header, int max_rows,
int max_cols, FILE *fp)
{
struct sort_entry *se;
struct rb_node *nd;
size_t ret = 0;
u64 total_period;
- unsigned long position = 1;
- long displacement = 0;
unsigned int width;
const char *sep = symbol_conf.field_sep;
const char *col_width = symbol_conf.col_width_list_str;
@@ -449,15 +446,7 @@ print_entries:
if (h->filtered)
continue;

- if (show_displacement) {
- if (h->pair != NULL)
- displacement = ((long)h->pair->position -
- (long)position);
- else
- displacement = 0;
- ++position;
- }
- ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
+ ret += hist_entry__fprintf(h, max_cols, hists, pair,
total_period, fp);

if (max_rows && ++nr_rows >= max_rows)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 6ca7407..efb8fc8 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -99,8 +99,7 @@ void hists__inc_nr_events(struct hists *self, u32 type);
size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);

size_t hists__fprintf(struct hists *self, struct hists *pair,
- bool show_displacement, bool show_header,
- int max_rows, int max_cols, FILE *fp);
+ bool show_header, int max_rows, int max_cols, FILE *fp);

int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -120,7 +119,6 @@ struct perf_hpp {
size_t size;
u64 total_period;
const char *sep;
- long displacement;
void *ptr;
};

diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index eb3959b..f070b52 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -73,8 +73,8 @@ struct hist_entry {
u8 filtered;
char *srcline;
struct symbol *parent;
+ unsigned long position;
union {
- unsigned long position;
struct hist_entry *pair;
struct rb_root sorted_chain;
};
--
1.7.1

2012-10-04 18:12:43

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 33/42] perf tools: Complete tracepoint event names

From: Namhyung Kim <[email protected]>

Currently tracepoint events cannot be completed because they contain a
colon (:) character. The colon is considered as a word separator when
bash completion is done - variable COMP_WORDBREAKS contains colon - so
if a word being completed contains a colon it can be a problem.

Recent versions of bash completion provide -n switch to
_get_comp_words_by_ref and __ltrim_colon_completions functions in order
to resolve this issue. Copy the latter in case not exists.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/bash_completion | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 5c355ab..56e6a12 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -6,6 +6,19 @@ function_exists()
return $?
}

+function_exists __ltrim_colon_completions ||
+__ltrim_colon_completions()
+{
+ if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
+ # Remove colon-word prefix from COMPREPLY items
+ local colon_word=${1%${1##*:}}
+ local i=${#COMPREPLY[*]}
+ while [[ $((--i)) -ge 0 ]]; do
+ COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
+ done
+ fi
+}
+
have perf &&
_perf()
{
@@ -13,9 +26,9 @@ _perf()

COMPREPLY=()
if function_exists _get_comp_words_by_ref; then
- _get_comp_words_by_ref cur prev
+ _get_comp_words_by_ref -n : cur prev
else
- cur=$(_get_cword)
+ cur=$(_get_cword :)
prev=${COMP_WORDS[COMP_CWORD-1]}
fi

@@ -35,6 +48,7 @@ _perf()
elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
evts=$($cmd list --raw-dump)
COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
+ __ltrim_colon_completions $cur
# List long option names
elif [[ $cur == --* ]]; then
subcmd=${COMP_WORDS[1]}
--
1.7.1

2012-10-04 18:12:47

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 31/42] perf evlist: Introduce add_newtp method

From: Arnaldo Carvalho de Melo <[email protected]>

To reduce the boilerplate of creating and adding a new tracepoint to an
evlist.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-trace.c | 18 +++---------------
tools/perf/util/evlist.c | 14 ++++++++++++++
tools/perf/util/evlist.h | 3 +++
3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 76b1202..dec8ced 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -200,24 +200,12 @@ static int trace__run(struct trace *trace)
goto out;
}

- evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
- if (evsel == NULL) {
- printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
+ if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
+ perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
+ printf("Couldn't read the raw_syscalls tracepoints information!\n");
goto out_delete_evlist;
}

- evsel->handler.func = trace__sys_enter;
- perf_evlist__add(evlist, evsel);
-
- evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
- if (evsel == NULL) {
- printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
- goto out_delete_evlist;
- }
-
- evsel->handler.func = trace__sys_exit;
- perf_evlist__add(evlist, evsel);
-
err = perf_evlist__create_maps(evlist, &trace->opts.target);
if (err < 0) {
printf("Problems parsing the target to trace, check your options!\n");
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ae89686..6a2809f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -285,6 +285,20 @@ out:
return err;
}

+int perf_evlist__add_newtp(struct perf_evlist *evlist,
+ const char *sys, const char *name, void *handler)
+{
+ struct perf_evsel *evsel;
+
+ evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
+ if (evsel == NULL)
+ return -1;
+
+ evsel->handler.func = handler;
+ perf_evlist__add(evlist, evsel);
+ return 0;
+}
+
void perf_evlist__disable(struct perf_evlist *evlist)
{
int cpu, thread;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 3f1fb66..ac98b01 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -72,6 +72,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))

+int perf_evlist__add_newtp(struct perf_evlist *evlist,
+ const char *sys, const char *name, void *handler);
+
int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);

struct perf_evsel *
--
1.7.1

2012-10-04 18:12:45

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 32/42] perf evlist: Remove some unused methods

From: Arnaldo Carvalho de Melo <[email protected]>

Those were introduced in a previous attempt at implementing 'trace', but
are not being used anywhere, ditch them.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/evlist.c | 86 +--------------------------------------------
tools/perf/util/evlist.h | 17 +--------
2 files changed, 3 insertions(+), 100 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6a2809f..186b877 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -154,8 +154,8 @@ error:
return -ENOMEM;
}

-int perf_evlist__add_attrs(struct perf_evlist *evlist,
- struct perf_event_attr *attrs, size_t nr_attrs)
+static int perf_evlist__add_attrs(struct perf_evlist *evlist,
+ struct perf_event_attr *attrs, size_t nr_attrs)
{
struct perf_evsel *evsel, *n;
LIST_HEAD(head);
@@ -189,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
}

-static int trace_event__id(const char *evname)
-{
- char *filename, *colon;
- int err = -1, fd;
-
- if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
- return -1;
-
- colon = strrchr(filename, ':');
- if (colon != NULL)
- *colon = '/';
-
- fd = open(filename, O_RDONLY);
- if (fd >= 0) {
- char id[16];
- if (read(fd, id, sizeof(id)) > 0)
- err = atoi(id);
- close(fd);
- }
-
- free(filename);
- return err;
-}
-
-int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
- const char *tracepoints[],
- size_t nr_tracepoints)
-{
- int err;
- size_t i;
- struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
-
- if (attrs == NULL)
- return -1;
-
- for (i = 0; i < nr_tracepoints; i++) {
- err = trace_event__id(tracepoints[i]);
-
- if (err < 0)
- goto out_free_attrs;
-
- attrs[i].type = PERF_TYPE_TRACEPOINT;
- attrs[i].config = err;
- attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
- PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
- attrs[i].sample_period = 1;
- }
-
- err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
-out_free_attrs:
- free(attrs);
- return err;
-}
-
struct perf_evsel *
perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
{
@@ -257,34 +203,6 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
return NULL;
}

-int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
- const struct perf_evsel_str_handler *assocs,
- size_t nr_assocs)
-{
- struct perf_evsel *evsel;
- int err;
- size_t i;
-
- for (i = 0; i < nr_assocs; i++) {
- err = trace_event__id(assocs[i].name);
- if (err < 0)
- goto out;
-
- evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
- if (evsel == NULL)
- continue;
-
- err = -EEXIST;
- if (evsel->handler.func != NULL)
- goto out;
- evsel->handler.func = assocs[i].handler;
- }
-
- err = 0;
-out:
- return err;
-}
-
int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index ac98b01..56003f7 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -51,27 +51,12 @@ void perf_evlist__delete(struct perf_evlist *evlist);

void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
int perf_evlist__add_default(struct perf_evlist *evlist);
-int perf_evlist__add_attrs(struct perf_evlist *evlist,
- struct perf_event_attr *attrs, size_t nr_attrs);
int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs);
-int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
- const char *tracepoints[], size_t nr_tracepoints);
-int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
- const struct perf_evsel_str_handler *assocs,
- size_t nr_assocs);
-
-#define perf_evlist__add_attrs_array(evlist, array) \
- perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
+
#define perf_evlist__add_default_attrs(evlist, array) \
__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))

-#define perf_evlist__add_tracepoints_array(evlist, array) \
- perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
-
-#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
- perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
-
int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler);

--
1.7.1

2012-10-04 18:09:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 16/42] perf kmem: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kmem.c | 66 +++++++++++++++++---------------------------
1 files changed, 26 insertions(+), 40 deletions(-)

diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bc912c6..14bf82f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -21,8 +21,6 @@
struct alloc_stat;
typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);

-static const char *input_name;
-
static int alloc_flag;
static int caller_flag;

@@ -31,8 +29,6 @@ static int caller_lines = -1;

static bool raw_ip;

-static char default_sort_order[] = "frag,hit,bytes";
-
static int *cpunode_map;
static int max_cpu_num;

@@ -481,7 +477,7 @@ static void sort_result(void)
__sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
}

-static int __cmd_kmem(void)
+static int __cmd_kmem(const char *input_name)
{
int err = -EINVAL;
struct perf_session *session;
@@ -520,11 +516,6 @@ out_delete:
return err;
}

-static const char * const kmem_usage[] = {
- "perf kmem [<options>] {record|stat}",
- NULL
-};
-
static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
{
if (l->ptr < r->ptr)
@@ -720,41 +711,17 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
return 0;
}

-static const struct option kmem_options[] = {
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
- OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
- "show per-callsite statistics",
- parse_caller_opt),
- OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
- "show per-allocation statistics",
- parse_alloc_opt),
- OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
- "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
- parse_sort_opt),
- OPT_CALLBACK('l', "line", NULL, "num",
- "show n lines",
- parse_line_opt),
- OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
- OPT_END()
-};
-
-static const char *record_args[] = {
- "record",
- "-a",
- "-R",
- "-f",
- "-c", "1",
+static int __cmd_record(int argc, const char **argv)
+{
+ const char * const record_args[] = {
+ "record", "-a", "-R", "-f", "-c", "1",
"-e", "kmem:kmalloc",
"-e", "kmem:kmalloc_node",
"-e", "kmem:kfree",
"-e", "kmem:kmem_cache_alloc",
"-e", "kmem:kmem_cache_alloc_node",
"-e", "kmem:kmem_cache_free",
-};
-
-static int __cmd_record(int argc, const char **argv)
-{
+ };
unsigned int rec_argc, i, j;
const char **rec_argv;

@@ -775,6 +742,25 @@ static int __cmd_record(int argc, const char **argv)

int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ const char * const default_sort_order = "frag,hit,bytes";
+ const char *input_name = NULL;
+ const struct option kmem_options[] = {
+ OPT_STRING('i', "input", &input_name, "file", "input file name"),
+ OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
+ "show per-callsite statistics", parse_caller_opt),
+ OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
+ "show per-allocation statistics", parse_alloc_opt),
+ OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
+ "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
+ parse_sort_opt),
+ OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
+ OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
+ OPT_END()
+ };
+ const char * const kmem_usage[] = {
+ "perf kmem [<options>] {record|stat}",
+ NULL
+ };
argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);

if (!argc)
@@ -793,7 +779,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
if (list_empty(&alloc_sort))
setup_sorting(&alloc_sort, default_sort_order);

- return __cmd_kmem();
+ return __cmd_kmem(input_name);
} else
usage_with_options(kmem_usage, kmem_options);

--
1.7.1

2012-10-04 18:14:15

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 29/42] perf tools: Convert to BACKTRACE_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without stack backtrace debug, we can set
NO_BACKTRACE=1 as a argument of make. It then defines NO_BACKTRACE
macro for C code to do the proper handling. However it usually used in
a negative semantics - e.g. #ifndef - so we saw double negations which
can be misleading. Convert it to a positive form to make it more
readable and add _SUPPORT suffix for consistency.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Irina Tirdea <[email protected]>
Cc: Irina Tirdea <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 10 +++++-----
tools/perf/util/util.c | 4 ++--
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 5216ade..f9126f8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -45,6 +45,8 @@ include config/utilities.mak
#
# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
# backtrace post unwind.
+#
+# Define NO_BACKTRACE if you do not want stack backtrace debug feature

$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -749,11 +751,9 @@ ifndef NO_STRLCPY
endif
endif

-ifdef NO_BACKTRACE
- BASIC_CFLAGS += -DNO_BACKTRACE
-else
- ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
- BASIC_CFLAGS += -DNO_BACKTRACE
+ifndef NO_BACKTRACE
+ ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
+ BASIC_CFLAGS += -DBACKTRACE_SUPPORT
endif
endif

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 2055cf3..9966459 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
#include "../perf.h"
#include "util.h"
#include <sys/mman.h>
-#ifndef NO_BACKTRACE
+#ifdef BACKTRACE_SUPPORT
#include <execinfo.h>
#endif
#include <stdio.h>
@@ -165,7 +165,7 @@ size_t hex_width(u64 v)
}

/* Obtain a backtrace and print it to stdout. */
-#ifndef NO_BACKTRACE
+#ifdef BACKTRACE_SUPPORT
void dump_stack(void)
{
void *array[16];
--
1.7.1

2012-10-04 18:14:37

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 30/42] perf kvm: Move global variables into a perf_kvm struct

From: David Ahern <[email protected]>

Cleans up the builtin-kvm code in preparation for the live mode. No
functional changes; only code movement.

Signed-off-by: David Ahern <[email protected]>
Cc: Dong Hao <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Runzhen Wang <[email protected]>
Cc: Xiao Guangrong <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kvm.c | 460 +++++++++++++++++++++++++---------------------
1 files changed, 253 insertions(+), 207 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a28c9ca..260abc5 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -32,16 +32,76 @@ struct event_key {
int info;
};

+struct kvm_event_stats {
+ u64 time;
+ struct stats stats;
+};
+
+struct kvm_event {
+ struct list_head hash_entry;
+ struct rb_node rb;
+
+ struct event_key key;
+
+ struct kvm_event_stats total;
+
+ #define DEFAULT_VCPU_NUM 8
+ int max_vcpu;
+ struct kvm_event_stats *vcpu;
+};
+
+typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
+
+struct kvm_event_key {
+ const char *name;
+ key_cmp_fun key;
+};
+
+
+struct perf_kvm;
+
struct kvm_events_ops {
bool (*is_begin_event)(struct perf_evsel *evsel,
struct perf_sample *sample,
struct event_key *key);
bool (*is_end_event)(struct perf_evsel *evsel,
struct perf_sample *sample, struct event_key *key);
- void (*decode_key)(struct event_key *key, char decode[20]);
+ void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
+ char decode[20]);
const char *name;
};

+struct exit_reasons_table {
+ unsigned long exit_code;
+ const char *reason;
+};
+
+#define EVENTS_BITS 12
+#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
+
+struct perf_kvm {
+ struct perf_tool tool;
+ struct perf_session *session;
+
+ const char *file_name;
+ const char *report_event;
+ const char *sort_key;
+ int trace_vcpu;
+
+ struct exit_reasons_table *exit_reasons;
+ int exit_reasons_size;
+ const char *exit_reasons_isa;
+
+ struct kvm_events_ops *events_ops;
+ key_cmp_fun compare;
+ struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
+ u64 total_time;
+ u64 total_count;
+
+ struct rb_root result;
+};
+
+
static void exit_event_get_key(struct perf_evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
@@ -78,45 +138,35 @@ static bool exit_event_end(struct perf_evsel *evsel,
return kvm_entry_event(evsel);
}

-struct exit_reasons_table {
- unsigned long exit_code;
- const char *reason;
-};
-
-struct exit_reasons_table vmx_exit_reasons[] = {
+static struct exit_reasons_table vmx_exit_reasons[] = {
VMX_EXIT_REASONS
};

-struct exit_reasons_table svm_exit_reasons[] = {
+static struct exit_reasons_table svm_exit_reasons[] = {
SVM_EXIT_REASONS
};

-static int cpu_isa;
-
-static const char *get_exit_reason(u64 exit_code)
+static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
{
- int table_size = ARRAY_SIZE(svm_exit_reasons);
- struct exit_reasons_table *table = svm_exit_reasons;
-
- if (cpu_isa == 1) {
- table = vmx_exit_reasons;
- table_size = ARRAY_SIZE(vmx_exit_reasons);
- }
+ int i = kvm->exit_reasons_size;
+ struct exit_reasons_table *tbl = kvm->exit_reasons;

- while (table_size--) {
- if (table->exit_code == exit_code)
- return table->reason;
- table++;
+ while (i--) {
+ if (tbl->exit_code == exit_code)
+ return tbl->reason;
+ tbl++;
}

pr_err("unknown kvm exit code:%lld on %s\n",
- (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM");
+ (unsigned long long)exit_code, kvm->exit_reasons_isa);
return "UNKNOWN";
}

-static void exit_event_decode_key(struct event_key *key, char decode[20])
+static void exit_event_decode_key(struct perf_kvm *kvm,
+ struct event_key *key,
+ char decode[20])
{
- const char *exit_reason = get_exit_reason(key->key);
+ const char *exit_reason = get_exit_reason(kvm, key->key);

scnprintf(decode, 20, "%s", exit_reason);
}
@@ -128,11 +178,11 @@ static struct kvm_events_ops exit_events = {
.name = "VM-EXIT"
};

- /*
- * For the mmio events, we treat:
- * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
- * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
- */
+/*
+ * For the mmio events, we treat:
+ * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
+ * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
+ */
static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
struct event_key *key)
{
@@ -178,7 +228,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
return false;
}

-static void mmio_event_decode_key(struct event_key *key, char decode[20])
+static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+ struct event_key *key,
+ char decode[20])
{
scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
@@ -219,7 +271,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,
return kvm_entry_event(evsel);
}

-static void ioport_event_decode_key(struct event_key *key, char decode[20])
+static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+ struct event_key *key,
+ char decode[20])
{
scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
key->info ? "POUT" : "PIN");
@@ -232,64 +286,37 @@ static struct kvm_events_ops ioport_events = {
.name = "IO Port Access"
};

-static const char *report_event = "vmexit";
-struct kvm_events_ops *events_ops;
-
-static bool register_kvm_events_ops(void)
+static bool register_kvm_events_ops(struct perf_kvm *kvm)
{
bool ret = true;

- if (!strcmp(report_event, "vmexit"))
- events_ops = &exit_events;
- else if (!strcmp(report_event, "mmio"))
- events_ops = &mmio_events;
- else if (!strcmp(report_event, "ioport"))
- events_ops = &ioport_events;
+ if (!strcmp(kvm->report_event, "vmexit"))
+ kvm->events_ops = &exit_events;
+ else if (!strcmp(kvm->report_event, "mmio"))
+ kvm->events_ops = &mmio_events;
+ else if (!strcmp(kvm->report_event, "ioport"))
+ kvm->events_ops = &ioport_events;
else {
- pr_err("Unknown report event:%s\n", report_event);
+ pr_err("Unknown report event:%s\n", kvm->report_event);
ret = false;
}

return ret;
}

-struct kvm_event_stats {
- u64 time;
- struct stats stats;
-};
-
-struct kvm_event {
- struct list_head hash_entry;
- struct rb_node rb;
-
- struct event_key key;
-
- struct kvm_event_stats total;
-
- #define DEFAULT_VCPU_NUM 8
- int max_vcpu;
- struct kvm_event_stats *vcpu;
-};
-
struct vcpu_event_record {
int vcpu_id;
u64 start_time;
struct kvm_event *last_event;
};

-#define EVENTS_BITS 12
-#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
-
-static u64 total_time;
-static u64 total_count;
-static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];

-static void init_kvm_event_record(void)
+static void init_kvm_event_record(struct perf_kvm *kvm)
{
int i;

for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
- INIT_LIST_HEAD(&kvm_events_cache[i]);
+ INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
}

static int kvm_events_hash_fn(u64 key)
@@ -333,14 +360,15 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
return event;
}

-static struct kvm_event *find_create_kvm_event(struct event_key *key)
+static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
+ struct event_key *key)
{
struct kvm_event *event;
struct list_head *head;

BUG_ON(key->key == INVALID_KEY);

- head = &kvm_events_cache[kvm_events_hash_fn(key->key)];
+ head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
list_for_each_entry(event, head, hash_entry)
if (event->key.key == key->key && event->key.info == key->info)
return event;
@@ -353,13 +381,14 @@ static struct kvm_event *find_create_kvm_event(struct event_key *key)
return event;
}

-static bool handle_begin_event(struct vcpu_event_record *vcpu_record,
+static bool handle_begin_event(struct perf_kvm *kvm,
+ struct vcpu_event_record *vcpu_record,
struct event_key *key, u64 timestamp)
{
struct kvm_event *event = NULL;

if (key->key != INVALID_KEY)
- event = find_create_kvm_event(key);
+ event = find_create_kvm_event(kvm, key);

vcpu_record->last_event = event;
vcpu_record->start_time = timestamp;
@@ -396,8 +425,10 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
return true;
}

-static bool handle_end_event(struct vcpu_event_record *vcpu_record,
- struct event_key *key, u64 timestamp)
+static bool handle_end_event(struct perf_kvm *kvm,
+ struct vcpu_event_record *vcpu_record,
+ struct event_key *key,
+ u64 timestamp)
{
struct kvm_event *event;
u64 time_begin, time_diff;
@@ -419,7 +450,7 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
return true;

if (!event)
- event = find_create_kvm_event(key);
+ event = find_create_kvm_event(kvm, key);

if (!event)
return false;
@@ -455,7 +486,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
return thread->priv;
}

-static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
+static bool handle_kvm_event(struct perf_kvm *kvm,
+ struct thread *thread,
+ struct perf_evsel *evsel,
struct perf_sample *sample)
{
struct vcpu_event_record *vcpu_record;
@@ -465,22 +498,15 @@ static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
if (!vcpu_record)
return true;

- if (events_ops->is_begin_event(evsel, sample, &key))
- return handle_begin_event(vcpu_record, &key, sample->time);
+ if (kvm->events_ops->is_begin_event(evsel, sample, &key))
+ return handle_begin_event(kvm, vcpu_record, &key, sample->time);

- if (events_ops->is_end_event(evsel, sample, &key))
- return handle_end_event(vcpu_record, &key, sample->time);
+ if (kvm->events_ops->is_end_event(evsel, sample, &key))
+ return handle_end_event(kvm, vcpu_record, &key, sample->time);

return true;
}

-typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
-struct kvm_event_key {
- const char *name;
- key_cmp_fun key;
-};
-
-static int trace_vcpu = -1;
#define GET_EVENT_KEY(func, field) \
static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
{ \
@@ -515,29 +541,25 @@ static struct kvm_event_key keys[] = {
{ NULL, NULL }
};

-static const char *sort_key = "sample";
-static key_cmp_fun compare;
-
-static bool select_key(void)
+static bool select_key(struct perf_kvm *kvm)
{
int i;

for (i = 0; keys[i].name; i++) {
- if (!strcmp(keys[i].name, sort_key)) {
- compare = keys[i].key;
+ if (!strcmp(keys[i].name, kvm->sort_key)) {
+ kvm->compare = keys[i].key;
return true;
}
}

- pr_err("Unknown compare key:%s\n", sort_key);
+ pr_err("Unknown compare key:%s\n", kvm->sort_key);
return false;
}

-static struct rb_root result;
-static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
- int vcpu)
+static void insert_to_result(struct rb_root *result, struct kvm_event *event,
+ key_cmp_fun bigger, int vcpu)
{
- struct rb_node **rb = &result.rb_node;
+ struct rb_node **rb = &result->rb_node;
struct rb_node *parent = NULL;
struct kvm_event *p;

@@ -552,13 +574,15 @@ static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
}

rb_link_node(&event->rb, parent, rb);
- rb_insert_color(&event->rb, &result);
+ rb_insert_color(&event->rb, result);
}

-static void update_total_count(struct kvm_event *event, int vcpu)
+static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
{
- total_count += get_event_count(event, vcpu);
- total_time += get_event_time(event, vcpu);
+ int vcpu = kvm->trace_vcpu;
+
+ kvm->total_count += get_event_count(event, vcpu);
+ kvm->total_time += get_event_time(event, vcpu);
}

static bool event_is_valid(struct kvm_event *event, int vcpu)
@@ -566,28 +590,30 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
return !!get_event_count(event, vcpu);
}

-static void sort_result(int vcpu)
+static void sort_result(struct perf_kvm *kvm)
{
unsigned int i;
+ int vcpu = kvm->trace_vcpu;
struct kvm_event *event;

for (i = 0; i < EVENTS_CACHE_SIZE; i++)
- list_for_each_entry(event, &kvm_events_cache[i], hash_entry)
+ list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
if (event_is_valid(event, vcpu)) {
- update_total_count(event, vcpu);
- insert_to_result(event, compare, vcpu);
+ update_total_count(kvm, event);
+ insert_to_result(&kvm->result, event,
+ kvm->compare, vcpu);
}
}

/* returns left most element of result, and erase it */
-static struct kvm_event *pop_from_result(void)
+static struct kvm_event *pop_from_result(struct rb_root *result)
{
- struct rb_node *node = rb_first(&result);
+ struct rb_node *node = rb_first(result);

if (!node)
return NULL;

- rb_erase(node, &result);
+ rb_erase(node, result);
return container_of(node, struct kvm_event, rb);
}

@@ -601,14 +627,15 @@ static void print_vcpu_info(int vcpu)
pr_info("VCPU %d:\n\n", vcpu);
}

-static void print_result(int vcpu)
+static void print_result(struct perf_kvm *kvm)
{
char decode[20];
struct kvm_event *event;
+ int vcpu = kvm->trace_vcpu;

pr_info("\n\n");
print_vcpu_info(vcpu);
- pr_info("%20s ", events_ops->name);
+ pr_info("%20s ", kvm->events_ops->name);
pr_info("%10s ", "Samples");
pr_info("%9s ", "Samples%");

@@ -616,33 +643,34 @@ static void print_result(int vcpu)
pr_info("%16s ", "Avg time");
pr_info("\n\n");

- while ((event = pop_from_result())) {
+ while ((event = pop_from_result(&kvm->result))) {
u64 ecount, etime;

ecount = get_event_count(event, vcpu);
etime = get_event_time(event, vcpu);

- events_ops->decode_key(&event->key, decode);
+ kvm->events_ops->decode_key(kvm, &event->key, decode);
pr_info("%20s ", decode);
pr_info("%10llu ", (unsigned long long)ecount);
- pr_info("%8.2f%% ", (double)ecount / total_count * 100);
- pr_info("%8.2f%% ", (double)etime / total_time * 100);
+ pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
+ pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
kvm_event_rel_stddev(vcpu, event));
pr_info("\n");
}

pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
- (unsigned long long)total_count, total_time / 1e3);
+ (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
}

-static int process_sample_event(struct perf_tool *tool __maybe_unused,
+static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, sample->tid);
+ struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);

if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
@@ -650,18 +678,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}

- if (!handle_kvm_event(thread, evsel, sample))
+ if (!handle_kvm_event(kvm, thread, evsel, sample))
return -1;

return 0;
}

-static struct perf_tool eops = {
- .sample = process_sample_event,
- .comm = perf_event__process_comm,
- .ordered_samples = true,
-};
-
static int get_cpu_isa(struct perf_session *session)
{
char *cpuid = session->header.env.cpuid;
@@ -679,34 +701,43 @@ static int get_cpu_isa(struct perf_session *session)
return isa;
}

-static const char *file_name;
-
-static int read_events(void)
+static int read_events(struct perf_kvm *kvm)
{
- struct perf_session *kvm_session;
int ret;

- kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops);
- if (!kvm_session) {
+ struct perf_tool eops = {
+ .sample = process_sample_event,
+ .comm = perf_event__process_comm,
+ .ordered_samples = true,
+ };
+
+ kvm->tool = eops;
+ kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
+ &kvm->tool);
+ if (!kvm->session) {
pr_err("Initializing perf session failed\n");
return -EINVAL;
}

- if (!perf_session__has_traces(kvm_session, "kvm record"))
+ if (!perf_session__has_traces(kvm->session, "kvm record"))
return -EINVAL;

/*
* Do not use 'isa' recorded in kvm_exit tracepoint since it is not
* traced in the old kernel.
*/
- ret = get_cpu_isa(kvm_session);
+ ret = get_cpu_isa(kvm->session);

if (ret < 0)
return ret;

- cpu_isa = ret;
+ if (ret == 1) {
+ kvm->exit_reasons = vmx_exit_reasons;
+ kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
+ kvm->exit_reasons_isa = "VMX";
+ }

- return perf_session__process_events(kvm_session, &eops);
+ return perf_session__process_events(kvm->session, &kvm->tool);
}

static bool verify_vcpu(int vcpu)
@@ -719,28 +750,30 @@ static bool verify_vcpu(int vcpu)
return true;
}

-static int kvm_events_report_vcpu(int vcpu)
+static int kvm_events_report_vcpu(struct perf_kvm *kvm)
{
int ret = -EINVAL;
+ int vcpu = kvm->trace_vcpu;

if (!verify_vcpu(vcpu))
goto exit;

- if (!select_key())
+ if (!select_key(kvm))
goto exit;

- if (!register_kvm_events_ops())
+ if (!register_kvm_events_ops(kvm))
goto exit;

- init_kvm_event_record();
+ init_kvm_event_record(kvm);
setup_pager();

- ret = read_events();
+ ret = read_events(kvm);
if (ret)
goto exit;

- sort_result(vcpu);
- print_result(vcpu);
+ sort_result(kvm);
+ print_result(kvm);
+
exit:
return ret;
}
@@ -765,7 +798,7 @@ static const char * const record_args[] = {
_p; \
})

-static int kvm_events_record(int argc, const char **argv)
+static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
{
unsigned int rec_argc, i, j;
const char **rec_argv;
@@ -780,7 +813,7 @@ static int kvm_events_record(int argc, const char **argv)
rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);

rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
- rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
+ rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);

for (j = 1; j < (unsigned int)argc; j++, i++)
rec_argv[i] = argv[j];
@@ -788,24 +821,24 @@ static int kvm_events_record(int argc, const char **argv)
return cmd_record(i, rec_argv, NULL);
}

-static const char * const kvm_events_report_usage[] = {
- "perf kvm stat report [<options>]",
- NULL
-};
+static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
+{
+ const struct option kvm_events_report_options[] = {
+ OPT_STRING(0, "event", &kvm->report_event, "report event",
+ "event for reporting: vmexit, mmio, ioport"),
+ OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
+ "vcpu id to report"),
+ OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
+ "key for sorting: sample(sort by samples number)"
+ " time (sort by avg time)"),
+ OPT_END()
+ };

-static const struct option kvm_events_report_options[] = {
- OPT_STRING(0, "event", &report_event, "report event",
- "event for reporting: vmexit, mmio, ioport"),
- OPT_INTEGER(0, "vcpu", &trace_vcpu,
- "vcpu id to report"),
- OPT_STRING('k', "key", &sort_key, "sort-key",
- "key for sorting: sample(sort by samples number)"
- " time (sort by avg time)"),
- OPT_END()
-};
+ const char * const kvm_events_report_usage[] = {
+ "perf kvm stat report [<options>]",
+ NULL
+ };

-static int kvm_events_report(int argc, const char **argv)
-{
symbol__init();

if (argc) {
@@ -817,7 +850,7 @@ static int kvm_events_report(int argc, const char **argv)
kvm_events_report_options);
}

- return kvm_events_report_vcpu(trace_vcpu);
+ return kvm_events_report_vcpu(kvm);
}

static void print_kvm_stat_usage(void)
@@ -831,7 +864,7 @@ static void print_kvm_stat_usage(void)
printf("\nOtherwise, it is the alias of 'perf stat':\n");
}

-static int kvm_cmd_stat(int argc, const char **argv)
+static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
{
if (argc == 1) {
print_kvm_stat_usage();
@@ -839,44 +872,16 @@ static int kvm_cmd_stat(int argc, const char **argv)
}

if (!strncmp(argv[1], "rec", 3))
- return kvm_events_record(argc - 1, argv + 1);
+ return kvm_events_record(kvm, argc - 1, argv + 1);

if (!strncmp(argv[1], "rep", 3))
- return kvm_events_report(argc - 1 , argv + 1);
+ return kvm_events_report(kvm, argc - 1 , argv + 1);

perf_stat:
return cmd_stat(argc, argv, NULL);
}

-static char name_buffer[256];
-
-static const char * const kvm_usage[] = {
- "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
- NULL
-};
-
-static const struct option kvm_options[] = {
- OPT_STRING('i', "input", &file_name, "file",
- "Input file name"),
- OPT_STRING('o', "output", &file_name, "file",
- "Output file name"),
- OPT_BOOLEAN(0, "guest", &perf_guest,
- "Collect guest os data"),
- OPT_BOOLEAN(0, "host", &perf_host,
- "Collect host os data"),
- OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
- "guest mount directory under which every guest os"
- " instance has a subdir"),
- OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
- "file", "file saving guest os vmlinux"),
- OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
- "file", "file saving guest os /proc/kallsyms"),
- OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
- "file", "file saving guest os /proc/modules"),
- OPT_END()
-};
-
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -885,7 +890,7 @@ static int __cmd_record(int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("record");
rec_argv[i++] = strdup("-o");
- rec_argv[i++] = strdup(file_name);
+ rec_argv[i++] = strdup(kvm->file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];

@@ -894,7 +899,7 @@ static int __cmd_record(int argc, const char **argv)
return cmd_record(i, rec_argv, NULL);
}

-static int __cmd_report(int argc, const char **argv)
+static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -903,7 +908,7 @@ static int __cmd_report(int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("report");
rec_argv[i++] = strdup("-i");
- rec_argv[i++] = strdup(file_name);
+ rec_argv[i++] = strdup(kvm->file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];

@@ -912,7 +917,7 @@ static int __cmd_report(int argc, const char **argv)
return cmd_report(i, rec_argv, NULL);
}

-static int __cmd_buildid_list(int argc, const char **argv)
+static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -921,7 +926,7 @@ static int __cmd_buildid_list(int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("buildid-list");
rec_argv[i++] = strdup("-i");
- rec_argv[i++] = strdup(file_name);
+ rec_argv[i++] = strdup(kvm->file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];

@@ -932,6 +937,43 @@ static int __cmd_buildid_list(int argc, const char **argv)

int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ struct perf_kvm kvm = {
+ .trace_vcpu = -1,
+ .report_event = "vmexit",
+ .sort_key = "sample",
+
+ .exit_reasons = svm_exit_reasons,
+ .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
+ .exit_reasons_isa = "SVM",
+ };
+
+ const struct option kvm_options[] = {
+ OPT_STRING('i', "input", &kvm.file_name, "file",
+ "Input file name"),
+ OPT_STRING('o', "output", &kvm.file_name, "file",
+ "Output file name"),
+ OPT_BOOLEAN(0, "guest", &perf_guest,
+ "Collect guest os data"),
+ OPT_BOOLEAN(0, "host", &perf_host,
+ "Collect host os data"),
+ OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
+ "guest mount directory under which every guest os"
+ " instance has a subdir"),
+ OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
+ "file", "file saving guest os vmlinux"),
+ OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
+ "file", "file saving guest os /proc/kallsyms"),
+ OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
+ "file", "file saving guest os /proc/modules"),
+ OPT_END()
+ };
+
+
+ const char * const kvm_usage[] = {
+ "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
+ NULL
+ };
+
perf_host = 0;
perf_guest = 1;

@@ -943,28 +985,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
if (!perf_host)
perf_guest = 1;

- if (!file_name) {
+ if (!kvm.file_name) {
if (perf_host && !perf_guest)
- sprintf(name_buffer, "perf.data.host");
+ kvm.file_name = strdup("perf.data.host");
else if (!perf_host && perf_guest)
- sprintf(name_buffer, "perf.data.guest");
+ kvm.file_name = strdup("perf.data.guest");
else
- sprintf(name_buffer, "perf.data.kvm");
- file_name = name_buffer;
+ kvm.file_name = strdup("perf.data.kvm");
+
+ if (!kvm.file_name) {
+ pr_err("Failed to allocate memory for filename\n");
+ return -ENOMEM;
+ }
}

if (!strncmp(argv[0], "rec", 3))
- return __cmd_record(argc, argv);
+ return __cmd_record(&kvm, argc, argv);
else if (!strncmp(argv[0], "rep", 3))
- return __cmd_report(argc, argv);
+ return __cmd_report(&kvm, argc, argv);
else if (!strncmp(argv[0], "diff", 4))
return cmd_diff(argc, argv, NULL);
else if (!strncmp(argv[0], "top", 3))
return cmd_top(argc, argv, NULL);
else if (!strncmp(argv[0], "buildid-list", 12))
- return __cmd_buildid_list(argc, argv);
+ return __cmd_buildid_list(&kvm, argc, argv);
else if (!strncmp(argv[0], "stat", 4))
- return kvm_cmd_stat(argc, argv);
+ return kvm_cmd_stat(&kvm, argc, argv);
else
usage_with_options(kvm_usage, kvm_options);

--
1.7.1

2012-10-04 18:14:58

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 26/42] perf tools: Check existence of _get_comp_words_by_ref when bash completing

From: Namhyung Kim <[email protected]>

The '_get_comp_words_by_ref' function is available from the bash
completion v1.2 so that earlier version emits following warning:

$ perf re<TAB>_get_comp_words_by_ref: command not found

Use older '_get_cword' method when the above function doesn't exist.

Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/bash_completion | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 1958fa5..3d48cee 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,12 +1,23 @@
# perf completion

+function_exists()
+{
+ declare -F $1 > /dev/null
+ return $?
+}
+
have perf &&
_perf()
{
- local cur cmd
+ local cur prev cmd

COMPREPLY=()
- _get_comp_words_by_ref cur prev
+ if function_exists _get_comp_words_by_ref; then
+ _get_comp_words_by_ref cur prev
+ else
+ cur=$(_get_cword)
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+ fi

cmd=${COMP_WORDS[0]}

--
1.7.1

2012-10-04 18:09:29

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/42] perf inject: Remove static variables

From: Arnaldo Carvalho de Melo <[email protected]>

We want to reduce the impact that each of the builtins has on perf as a
whole, so use the superclassing of perf_tool mechanizm to move its
config knobs to the stack, so that only if we use that tool, its impact
will be felt.

In this case is more about consistency, as the impact of this tool is
minimal.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-inject.c | 72 ++++++++++++++++++++++--------------------
1 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index e249f24..3c9ab55 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,7 +14,10 @@

#include "util/parse-options.h"

-static bool inject_build_ids;
+struct perf_inject {
+ struct perf_tool tool;
+ bool build_ids;
+};

static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
union perf_event *event,
@@ -207,22 +210,6 @@ repipe:
return 0;
}

-struct perf_tool perf_inject = {
- .sample = perf_event__repipe_sample,
- .mmap = perf_event__repipe,
- .comm = perf_event__repipe,
- .fork = perf_event__repipe,
- .exit = perf_event__repipe,
- .lost = perf_event__repipe,
- .read = perf_event__repipe_sample,
- .throttle = perf_event__repipe,
- .unthrottle = perf_event__repipe,
- .attr = perf_event__repipe_attr,
- .event_type = perf_event__repipe_event_type_synth,
- .tracing_data = perf_event__repipe_tracing_data_synth,
- .build_id = perf_event__repipe_op2_synth,
-};
-
extern volatile int session_done;

static void sig_handler(int sig __maybe_unused)
@@ -230,25 +217,25 @@ static void sig_handler(int sig __maybe_unused)
session_done = 1;
}

-static int __cmd_inject(void)
+static int __cmd_inject(struct perf_inject *inject)
{
struct perf_session *session;
int ret = -EINVAL;

signal(SIGINT, sig_handler);

- if (inject_build_ids) {
- perf_inject.sample = perf_event__inject_buildid;
- perf_inject.mmap = perf_event__repipe_mmap;
- perf_inject.fork = perf_event__repipe_task;
- perf_inject.tracing_data = perf_event__repipe_tracing_data;
+ if (inject->build_ids) {
+ inject->tool.sample = perf_event__inject_buildid;
+ inject->tool.mmap = perf_event__repipe_mmap;
+ inject->tool.fork = perf_event__repipe_task;
+ inject->tool.tracing_data = perf_event__repipe_tracing_data;
}

- session = perf_session__new("-", O_RDONLY, false, true, &perf_inject);
+ session = perf_session__new("-", O_RDONLY, false, true, &inject->tool);
if (session == NULL)
return -ENOMEM;

- ret = perf_session__process_events(session, &perf_inject);
+ ret = perf_session__process_events(session, &inject->tool);

perf_session__delete(session);

@@ -260,16 +247,33 @@ static const char * const report_usage[] = {
NULL
};

-static const struct option options[] = {
- OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
- "Inject build-ids into the output stream"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show build ids, etc)"),
- OPT_END()
-};
-
int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ struct perf_inject inject = {
+ .tool = {
+ .sample = perf_event__repipe_sample,
+ .mmap = perf_event__repipe,
+ .comm = perf_event__repipe,
+ .fork = perf_event__repipe,
+ .exit = perf_event__repipe,
+ .lost = perf_event__repipe,
+ .read = perf_event__repipe_sample,
+ .throttle = perf_event__repipe,
+ .unthrottle = perf_event__repipe,
+ .attr = perf_event__repipe_attr,
+ .event_type = perf_event__repipe_event_type_synth,
+ .tracing_data = perf_event__repipe_tracing_data_synth,
+ .build_id = perf_event__repipe_op2_synth,
+ },
+ };
+ const struct option options[] = {
+ OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
+ "Inject build-ids into the output stream"),
+ OPT_INCR('v', "verbose", &verbose,
+ "be more verbose (show build ids, etc)"),
+ OPT_END()
+ };
+
argc = parse_options(argc, argv, options, report_usage, 0);

/*
@@ -281,5 +285,5 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
if (symbol__init() < 0)
return -1;

- return __cmd_inject();
+ return __cmd_inject(&inject);
}
--
1.7.1

2012-10-04 18:19:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 19/42] perf buildid-cache: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-buildid-cache.c | 58 ++++++++++++++++--------------------
1 files changed, 26 insertions(+), 32 deletions(-)

diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 8365455..d37e077 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -15,22 +15,6 @@
#include "util/strlist.h"
#include "util/symbol.h"

-static char const *add_name_list_str, *remove_name_list_str;
-
-static const char * const buildid_cache_usage[] = {
- "perf buildid-cache [<options>]",
- NULL
-};
-
-static const struct option buildid_cache_options[] = {
- OPT_STRING('a', "add", &add_name_list_str,
- "file list", "file(s) to add"),
- OPT_STRING('r', "remove", &remove_name_list_str, "file list",
- "file(s) to remove"),
- OPT_INCR('v', "verbose", &verbose, "be more verbose"),
- OPT_END()
-};
-
static int build_id_cache__add_file(const char *filename, const char *debugdir)
{
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -51,8 +35,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
return err;
}

-static int build_id_cache__remove_file(const char *filename __maybe_unused,
- const char *debugdir __maybe_unused)
+static int build_id_cache__remove_file(const char *filename,
+ const char *debugdir)
{
u8 build_id[BUILD_ID_SIZE];
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -73,11 +57,34 @@ static int build_id_cache__remove_file(const char *filename __maybe_unused,
return err;
}

-static int __cmd_buildid_cache(void)
+int cmd_buildid_cache(int argc, const char **argv,
+ const char *prefix __maybe_unused)
{
struct strlist *list;
struct str_node *pos;
char debugdir[PATH_MAX];
+ char const *add_name_list_str = NULL,
+ *remove_name_list_str = NULL;
+ const struct option buildid_cache_options[] = {
+ OPT_STRING('a', "add", &add_name_list_str,
+ "file list", "file(s) to add"),
+ OPT_STRING('r', "remove", &remove_name_list_str, "file list",
+ "file(s) to remove"),
+ OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+ OPT_END()
+ };
+ const char * const buildid_cache_usage[] = {
+ "perf buildid-cache [<options>]",
+ NULL
+ };
+
+ argc = parse_options(argc, argv, buildid_cache_options,
+ buildid_cache_usage, 0);
+
+ if (symbol__init() < 0)
+ return -1;
+
+ setup_pager();

snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);

@@ -119,16 +126,3 @@ static int __cmd_buildid_cache(void)

return 0;
}
-
-int cmd_buildid_cache(int argc, const char **argv,
- const char *prefix __maybe_unused)
-{
- argc = parse_options(argc, argv, buildid_cache_options,
- buildid_cache_usage, 0);
-
- if (symbol__init() < 0)
- return -1;
-
- setup_pager();
- return __cmd_buildid_cache();
-}
--
1.7.1

2012-10-04 18:19:29

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 18/42] perf timechart: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-timechart.c | 100 ++++++++++++++++-----------------------
1 files changed, 41 insertions(+), 59 deletions(-)

diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index b1a8a3b..f251b61 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -38,9 +38,6 @@
#define PWR_EVENT_EXIT -1


-static const char *input_name;
-static const char *output_name = "output.svg";
-
static unsigned int numcpus;
static u64 min_freq; /* Lowest CPU frequency seen */
static u64 max_freq; /* Highest CPU frequency seen */
@@ -968,16 +965,15 @@ static void write_svg_file(const char *filename)
svg_close();
}

-static struct perf_tool perf_timechart = {
- .comm = process_comm_event,
- .fork = process_fork_event,
- .exit = process_exit_event,
- .sample = process_sample_event,
- .ordered_samples = true,
-};
-
-static int __cmd_timechart(void)
+static int __cmd_timechart(const char *input_name, const char *output_name)
{
+ struct perf_tool perf_timechart = {
+ .comm = process_comm_event,
+ .fork = process_fork_event,
+ .exit = process_exit_event,
+ .sample = process_sample_event,
+ .ordered_samples = true,
+ };
struct perf_session *session = perf_session__new(input_name, O_RDONLY,
0, false, &perf_timechart);
int ret = -EINVAL;
@@ -1005,40 +1001,25 @@ out_delete:
return ret;
}

-static const char * const timechart_usage[] = {
- "perf timechart [<options>] {record}",
- NULL
-};
-
-#ifdef SUPPORT_OLD_POWER_EVENTS
-static const char * const record_old_args[] = {
- "record",
- "-a",
- "-R",
- "-f",
- "-c", "1",
- "-e", "power:power_start",
- "-e", "power:power_end",
- "-e", "power:power_frequency",
- "-e", "sched:sched_wakeup",
- "-e", "sched:sched_switch",
-};
-#endif
-
-static const char * const record_new_args[] = {
- "record",
- "-a",
- "-R",
- "-f",
- "-c", "1",
- "-e", "power:cpu_frequency",
- "-e", "power:cpu_idle",
- "-e", "sched:sched_wakeup",
- "-e", "sched:sched_switch",
-};
-
static int __cmd_record(int argc, const char **argv)
{
+#ifdef SUPPORT_OLD_POWER_EVENTS
+ const char * const record_old_args[] = {
+ "record", "-a", "-R", "-f", "-c", "1",
+ "-e", "power:power_start",
+ "-e", "power:power_end",
+ "-e", "power:power_frequency",
+ "-e", "sched:sched_wakeup",
+ "-e", "sched:sched_switch",
+ };
+#endif
+ const char * const record_new_args[] = {
+ "record", "-a", "-R", "-f", "-c", "1",
+ "-e", "power:cpu_frequency",
+ "-e", "power:cpu_idle",
+ "-e", "sched:sched_wakeup",
+ "-e", "sched:sched_switch",
+ };
unsigned int rec_argc, i, j;
const char **rec_argv;
const char * const *record_args = record_new_args;
@@ -1077,27 +1058,28 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
return 0;
}

-static const struct option options[] = {
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
- OPT_STRING('o', "output", &output_name, "file",
- "output file name"),
- OPT_INTEGER('w', "width", &svg_page_width,
- "page width"),
- OPT_BOOLEAN('P', "power-only", &power_only,
- "output power data only"),
+int cmd_timechart(int argc, const char **argv,
+ const char *prefix __maybe_unused)
+{
+ const char *input_name;
+ const char *output_name = "output.svg";
+ const struct option options[] = {
+ OPT_STRING('i', "input", &input_name, "file", "input file name"),
+ OPT_STRING('o', "output", &output_name, "file", "output file name"),
+ OPT_INTEGER('w', "width", &svg_page_width, "page width"),
+ OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
OPT_CALLBACK('p', "process", NULL, "process",
"process selector. Pass a pid or process name.",
parse_process),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_END()
-};
-
+ };
+ const char * const timechart_usage[] = {
+ "perf timechart [<options>] {record}",
+ NULL
+ };

-int cmd_timechart(int argc, const char **argv,
- const char *prefix __maybe_unused)
-{
argc = parse_options(argc, argv, options, timechart_usage,
PARSE_OPT_STOP_AT_NON_OPTION);

@@ -1110,5 +1092,5 @@ int cmd_timechart(int argc, const char **argv,

setup_pager();

- return __cmd_timechart();
+ return __cmd_timechart(input_name, output_name);
}
--
1.7.1

2012-10-04 18:19:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/42] perf script: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-script.c | 90 ++++++++++++++++++++-----------------------
1 files changed, 42 insertions(+), 48 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1be843a..fb96250 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -24,7 +24,6 @@ static u64 last_timestamp;
static u64 nr_unordered;
extern const struct option record_options[];
static bool no_callchain;
-static bool show_full_info;
static bool system_wide;
static const char *cpu_list;
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -473,8 +472,6 @@ static int cleanup_scripting(void)
return scripting_ops->stop_script();
}

-static const char *input_name;
-
static int process_sample_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
@@ -1156,20 +1153,40 @@ out:
return n_args;
}

-static const char * const script_usage[] = {
- "perf script [<options>]",
- "perf script [<options>] record <script> [<record-options>] <command>",
- "perf script [<options>] report <script> [script-args]",
- "perf script [<options>] <script> [<record-options>] <command>",
- "perf script [<options>] <top-script> [script-args]",
- NULL
-};
+static int have_cmd(int argc, const char **argv)
+{
+ char **__argv = malloc(sizeof(const char *) * argc);
+
+ if (!__argv) {
+ pr_err("malloc failed\n");
+ return -1;
+ }
+
+ memcpy(__argv, argv, sizeof(const char *) * argc);
+ argc = parse_options(argc, (const char **)__argv, record_options,
+ NULL, PARSE_OPT_STOP_AT_NON_OPTION);
+ free(__argv);

-static const struct option options[] = {
+ system_wide = (argc == 0);
+
+ return 0;
+}
+
+int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+ bool show_full_info = false;
+ const char *input_name = NULL;
+ char *rec_script_path = NULL;
+ char *rep_script_path = NULL;
+ struct perf_session *session;
+ char *script_path = NULL;
+ const char **__argv;
+ int i, j, err;
+ const struct option options[] = {
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show symbol address, etc)"),
+ "be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('L', "Latency", &latency_format,
"show latency attributes (irqs/preemption disabled, etc)"),
OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
@@ -1179,8 +1196,7 @@ static const struct option options[] = {
parse_scriptname),
OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
"generate perf-script.xx script in specified language"),
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
+ OPT_STRING('i', "input", &input_name, "file", "input file name"),
OPT_BOOLEAN('d', "debug-mode", &debug_mode,
"do various checks like samples ordering and lost events"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -1195,10 +1211,9 @@ static const struct option options[] = {
"comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
- "addr,symoff",
- parse_output_fields),
+ "addr,symoff", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
- "system-wide collection from all CPUs"),
+ "system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
"only consider these symbols"),
OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -1208,37 +1223,16 @@ static const struct option options[] = {
"display extended information from perf.data file"),
OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
"Show the path of [kernel.kallsyms]"),
-
OPT_END()
-};
-
-static int have_cmd(int argc, const char **argv)
-{
- char **__argv = malloc(sizeof(const char *) * argc);
-
- if (!__argv) {
- pr_err("malloc failed\n");
- return -1;
- }
-
- memcpy(__argv, argv, sizeof(const char *) * argc);
- argc = parse_options(argc, (const char **)__argv, record_options,
- NULL, PARSE_OPT_STOP_AT_NON_OPTION);
- free(__argv);
-
- system_wide = (argc == 0);
-
- return 0;
-}
-
-int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
-{
- char *rec_script_path = NULL;
- char *rep_script_path = NULL;
- struct perf_session *session;
- char *script_path = NULL;
- const char **__argv;
- int i, j, err;
+ };
+ const char * const script_usage[] = {
+ "perf script [<options>]",
+ "perf script [<options>] record <script> [<record-options>] <command>",
+ "perf script [<options>] report <script> [script-args]",
+ "perf script [<options>] <script> [<record-options>] <command>",
+ "perf script [<options>] <top-script> [script-args]",
+ NULL
+ };

setup_scripting();

--
1.7.1

2012-10-04 18:20:42

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/42] perf sched: Look up thread using tid instead of pid

From: Arnaldo Carvalho de Melo <[email protected]>

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-sched.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 9b9e32e..3488ead 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1426,7 +1426,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
struct perf_evsel *evsel,
struct machine *machine)
{
- struct thread *thread = machine__findnew_thread(machine, sample->pid);
+ struct thread *thread = machine__findnew_thread(machine, sample->tid);
int err = 0;

if (thread == NULL) {
--
1.7.1

2012-10-04 18:20:58

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/42] perf tools: Convert to HAVE_STRLCPY

From: Namhyung Kim <[email protected]>

For similar reason of previous patches, convert NO_STRLCPY to positive
HAVE_STRLCPY.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 8 +++-----
tools/perf/util/cache.h | 2 +-
tools/perf/util/path.c | 2 +-
3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 31a07f9..5216ade 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -743,11 +743,9 @@ ifeq ($(NO_PERF_REGS),0)
BASIC_CFLAGS += -DHAVE_PERF_REGS
endif

-ifdef NO_STRLCPY
- BASIC_CFLAGS += -DNO_STRLCPY
-else
- ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
- BASIC_CFLAGS += -DNO_STRLCPY
+ifndef NO_STRLCPY
+ ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y)
+ BASIC_CFLAGS += -DHAVE_STRLCPY
endif
endif

diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 07aec06..2bd5137 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -107,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
extern char *perf_pathdup(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));

-#ifdef NO_STRLCPY
+#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *dest, const char *src, size_t size);
#endif

diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index bd74977..a8c4954 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
return ".";
}

-#ifdef NO_STRLCPY
+#ifndef HAVE_STRLCPY
size_t strlcpy(char *dest, const char *src, size_t size)
{
size_t ret = strlen(src);
--
1.7.1

2012-10-04 18:09:10

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 34/42] perf hists: Add struct hists pointer to struct hist_entry

From: Jiri Olsa <[email protected]>

Adding pointer back to the parent struct hists for struct hists_entry.

This will be useful in future for any hist_entry's data computation,
that depends on total data of its parent hists.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/hist.c | 2 ++
tools/perf/util/sort.h | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 236bc9d..040f34c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -325,6 +325,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
.branch_info = bi,
+ .hists = self,
};

return add_hist_entry(self, &entry, al, period);
@@ -346,6 +347,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
.period = period,
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
+ .hists = self,
};

return add_hist_entry(self, &entry, al, period);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 12d6347..eb3959b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -79,6 +79,7 @@ struct hist_entry {
struct rb_root sorted_chain;
};
struct branch_info *branch_info;
+ struct hists *hists;
struct callchain_root callchain[0];
};

--
1.7.1

2012-10-04 18:21:46

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 37/42] perf tools: Removing hists pair argument from output path

From: Jiri Olsa <[email protected]>

The hists pointer is now part of the 'struct hist_entry'.

And since the overhead and baseline columns are split now, there's no
reason to pass it through the output path.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-diff.c | 3 +--
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/ui/hist.c | 9 +++++----
tools/perf/ui/stdio/hist.c | 10 +++-------
tools/perf/util/hist.h | 4 ++--
6 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 5cb577a..413c65a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -214,8 +214,7 @@ static int __cmd_diff(void)
first = false;

hists__match(&evsel_old->hists, &evsel->hists);
- hists__fprintf(&evsel->hists, &evsel_old->hists,
- true, 0, 0, stdout);
+ hists__fprintf(&evsel->hists, true, 0, 0, stdout);
}

out_delete:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 6748cac..95e7ea8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
const char *evname = perf_evsel__name(pos);

hists__fprintf_nr_sample_events(hists, evname, stdout);
- hists__fprintf(hists, NULL, true, 0, 0, stdout);
+ hists__fprintf(hists, true, 0, 0, stdout);
fprintf(stdout, "\n\n");
}

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 3571158..ff6db80 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
hists__output_recalc_col_len(&top->sym_evsel->hists,
top->winsize.ws_row - 3);
putchar('\n');
- hists__fprintf(&top->sym_evsel->hists, NULL, false,
+ hists__fprintf(&top->sym_evsel->hists, false,
top->winsize.ws_row - 4 - printed, win_width, stdout);
}

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 532a601..6b0138e 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -228,16 +228,17 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
{
- struct hists *pair_hists = hpp->ptr;
+ struct hist_entry *pair = he->pair;
+ struct hists *pair_hists = pair ? pair->hists : NULL;
u64 old_total, new_total;
double old_percent = 0, new_percent = 0;
double diff;
const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
char buf[32] = " ";

- old_total = pair_hists->stats.total_period;
- if (old_total > 0 && he->pair)
- old_percent = 100.0 * he->pair->period / old_total;
+ old_total = pair_hists ? pair_hists->stats.total_period : 0;
+ if (old_total > 0 && pair)
+ old_percent = 100.0 * pair->period / old_total;

new_total = hpp->total_period;
if (new_total > 0)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 0aa6776..1340c93 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -307,8 +307,7 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
}

static int hist_entry__fprintf(struct hist_entry *he, size_t size,
- struct hists *hists, struct hists *pair_hists,
- u64 total_period, FILE *fp)
+ struct hists *hists, u64 total_period, FILE *fp)
{
char bf[512];
int ret;
@@ -316,7 +315,6 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
.buf = bf,
.size = size,
.total_period = total_period,
- .ptr = pair_hists,
};
bool color = !symbol_conf.field_sep;

@@ -335,8 +333,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
return ret;
}

-size_t hists__fprintf(struct hists *hists, struct hists *pair,
- bool show_header, int max_rows,
+size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
int max_cols, FILE *fp)
{
struct sort_entry *se;
@@ -351,7 +348,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
struct perf_hpp dummy_hpp = {
.buf = bf,
.size = sizeof(bf),
- .ptr = pair,
};
bool first = true;

@@ -453,7 +449,7 @@ print_entries:
if (h->filtered)
continue;

- ret += hist_entry__fprintf(h, max_cols, hists, pair,
+ ret += hist_entry__fprintf(h, max_cols, hists,
total_period, fp);

if (max_rows && ++nr_rows >= max_rows)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index b1a2b9d..b83a226 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -98,8 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
void hists__inc_nr_events(struct hists *self, u32 type);
size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);

-size_t hists__fprintf(struct hists *self, struct hists *pair,
- bool show_header, int max_rows, int max_cols, FILE *fp);
+size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
+ int max_cols, FILE *fp);

int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
int hist_entry__annotate(struct hist_entry *self, size_t privsize);
--
1.7.1

2012-10-04 18:22:25

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 23/42] perf evlist: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-evlist.c | 21 +++++++++------------
1 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 1fb1641..997afb8 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -108,23 +108,20 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
return 0;
}

-static const char * const evlist_usage[] = {
- "perf evlist [<options>]",
- NULL
-};
-
int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct perf_attr_details details = { .verbose = false, };
const char *input_name = NULL;
const struct option options[] = {
- OPT_STRING('i', "input", &input_name, "file",
- "Input file name"),
- OPT_BOOLEAN('F', "freq", &details.freq,
- "Show the sample frequency"),
- OPT_BOOLEAN('v', "verbose", &details.verbose,
- "Show all event attr details"),
- OPT_END()
+ OPT_STRING('i', "input", &input_name, "file", "Input file name"),
+ OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
+ OPT_BOOLEAN('v', "verbose", &details.verbose,
+ "Show all event attr details"),
+ OPT_END()
+ };
+ const char * const evlist_usage[] = {
+ "perf evlist [<options>]",
+ NULL
};

argc = parse_options(argc, argv, options, evlist_usage, 0);
--
1.7.1

2012-10-04 18:22:43

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 24/42] perf record: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8c029fe..e923165 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,15 +31,6 @@
#include <sched.h>
#include <sys/mman.h>

-#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
-
-#ifdef LIBUNWIND_SUPPORT
-static unsigned long default_stack_dump_size = 8192;
-static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
-#else
-static char callchain_help[] = CALLCHAIN_HELP "[fp]";
-#endif
-
enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
@@ -868,6 +859,8 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
#ifdef LIBUNWIND_SUPPORT
/* Dwarf style */
} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
+ const unsigned long default_stack_dump_size = 8192;
+
ret = 0;
rec->opts.call_graph = CALLCHAIN_DWARF;
rec->opts.stack_dump_size = default_stack_dump_size;
@@ -930,6 +923,14 @@ static struct perf_record record = {
.file_new = true,
};

+#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
+
+#ifdef LIBUNWIND_SUPPORT
+static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+#else
+static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
+#endif
+
/*
* XXX Will stay a global variable till we fix builtin-script.c to stop messing
* with it and switch to use the library functions in perf_evlist that came
--
1.7.1

2012-10-04 18:22:41

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 25/42] perf inject: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Leftover from patch at the beggining of this series.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-inject.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 3c9ab55..4688bea 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -242,11 +242,6 @@ static int __cmd_inject(struct perf_inject *inject)
return ret;
}

-static const char * const report_usage[] = {
- "perf inject [<options>]",
- NULL
-};
-
int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct perf_inject inject = {
@@ -273,14 +268,18 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
"be more verbose (show build ids, etc)"),
OPT_END()
};
+ const char * const inject_usage[] = {
+ "perf inject [<options>]",
+ NULL
+ };

- argc = parse_options(argc, argv, options, report_usage, 0);
+ argc = parse_options(argc, argv, options, inject_usage, 0);

/*
* Any (unrecognized) arguments left?
*/
if (argc)
- usage_with_options(report_usage, options);
+ usage_with_options(inject_usage, options);

if (symbol__init() < 0)
return -1;
--
1.7.1

2012-10-04 18:09:02

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 27/42] perf tools: Complete long option names of perf command

From: Namhyung Kim <[email protected]>

The main perf binary can receive a number of options that configure
working environment. Add them to the completion script.

Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/bash_completion | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 3d48cee..bef06f0 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -21,10 +21,16 @@ _perf()

cmd=${COMP_WORDS[0]}

- # List perf subcommands
+ # List perf subcommands or long options
if [ $COMP_CWORD -eq 1 ]; then
- cmds=$($cmd --list-cmds)
- COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+ if [[ $cur == --* ]]; then
+ COMPREPLY=( $( compgen -W '--help --version \
+ --exec-path --html-path --paginate --no-pager \
+ --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
+ else
+ cmds=$($cmd --list-cmds)
+ COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+ fi
# List possible events for -e option
elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
cmds=$($cmd list --raw-dump)
--
1.7.1

2012-10-04 18:09:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/42] perf tools: Move libdw availability check before arch Makefile

From: Namhyung Kim <[email protected]>

Since NO_DWARF is used in arch/$(ARCH)/Makefiles, it should be checked
before including those files. It was moved by mistake during libelf
dependency removal work by me, sorry.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e5e71e7..834f09f 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -486,7 +486,13 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
NO_DWARF := 1
NO_DEMANGLE := 1
endif
-endif
+else
+ FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
+ ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
+ msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
+ NO_DWARF := 1
+ endif # Dwarf support
+endif # SOURCE_LIBELF
endif # NO_LIBELF

ifndef NO_LIBUNWIND
@@ -532,12 +538,6 @@ ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
BASIC_CFLAGS += -DLIBELF_NO_MMAP
endif

-FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
-ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
- msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
- NO_DWARF := 1
-endif # Dwarf support
-
ifndef NO_DWARF
ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
--
1.7.1

2012-10-04 18:23:38

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 20/42] perf buildid-list: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-buildid-list.c | 55 ++++++++++++++++---------------------
1 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 1159fee..a0e94ff 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -16,27 +16,6 @@
#include "util/session.h"
#include "util/symbol.h"

-static const char *input_name;
-static bool force;
-static bool show_kernel;
-static bool with_hits;
-
-static const char * const buildid_list_usage[] = {
- "perf buildid-list [<options>]",
- NULL
-};
-
-static const struct option options[] = {
- OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
- OPT_STRING('i', "input", &input_name, "file",
- "input file name"),
- OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
- OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose"),
- OPT_END()
-};
-
static int sysfs__fprintf_build_id(FILE *fp)
{
u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -65,7 +44,8 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
return fprintf(fp, "%s\n", sbuild_id);
}

-static int perf_session__list_build_ids(void)
+static int perf_session__list_build_ids(const char *input_name,
+ bool force, bool with_hits)
{
struct perf_session *session;

@@ -95,18 +75,31 @@ out:
return 0;
}

-static int __cmd_buildid_list(void)
-{
- if (show_kernel)
- return sysfs__fprintf_build_id(stdout);
-
- return perf_session__list_build_ids();
-}
-
int cmd_buildid_list(int argc, const char **argv,
const char *prefix __maybe_unused)
{
+ bool show_kernel = false;
+ bool with_hits = false;
+ bool force = false;
+ const char *input_name = NULL;
+ const struct option options[] = {
+ OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
+ OPT_STRING('i', "input", &input_name, "file", "input file name"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+ OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
+ OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+ OPT_END()
+ };
+ const char * const buildid_list_usage[] = {
+ "perf buildid-list [<options>]",
+ NULL
+ };
+
argc = parse_options(argc, argv, options, buildid_list_usage, 0);
setup_pager();
- return __cmd_buildid_list();
+
+ if (show_kernel)
+ return sysfs__fprintf_build_id(stdout);
+
+ return perf_session__list_build_ids(input_name, force, with_hits);
}
--
1.7.1

2012-10-04 18:23:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/42] perf stat: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-stat.c | 328 ++++++++++++++++++++++-----------------------
1 files changed, 159 insertions(+), 169 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e8cd4d8..93b9011 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,122 +64,12 @@
#define CNTR_NOT_SUPPORTED "<not supported>"
#define CNTR_NOT_COUNTED "<not counted>"

-static struct perf_event_attr default_attrs[] = {
-
- { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
- { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
- { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
- { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
-
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
- { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
-
-};
-
-/*
- * Detailed stats (-d), covering the L1 and last level data caches:
- */
-static struct perf_event_attr detailed_attrs[] = {
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1D << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1D << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_LL << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_LL << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-};
-
-/*
- * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
- */
-static struct perf_event_attr very_detailed_attrs[] = {
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1I << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1I << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_DTLB << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_DTLB << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_ITLB << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_ITLB << 0 |
- (PERF_COUNT_HW_CACHE_OP_READ << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-
-};
-
-/*
- * Very, very detailed stats (-d -d -d), adding prefetch events:
- */
-static struct perf_event_attr very_very_detailed_attrs[] = {
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1D << 0 |
- (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
-
- { .type = PERF_TYPE_HW_CACHE,
- .config =
- PERF_COUNT_HW_CACHE_L1D << 0 |
- (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
- (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
-};
-
-
-
static struct perf_evlist *evsel_list;

static struct perf_target target = {
.uid = UINT_MAX,
};

-static int run_idx = 0;
static int run_count = 1;
static bool no_inherit = false;
static bool scale = true;
@@ -187,15 +77,12 @@ static bool no_aggr = false;
static pid_t child_pid = -1;
static bool null_run = false;
static int detailed_run = 0;
-static bool sync_run = false;
static bool big_num = true;
static int big_num_opt = -1;
static const char *csv_sep = NULL;
static bool csv_output = false;
static bool group = false;
-static const char *output_name = NULL;
static FILE *output = NULL;
-static int output_fd;

static volatile int done = 0;

@@ -1028,11 +915,6 @@ static void sig_atexit(void)
kill(getpid(), signr);
}

-static const char * const stat_usage[] = {
- "perf stat [<options>] [<command>]",
- NULL
-};
-
static int stat__set_big_num(const struct option *opt __maybe_unused,
const char *s __maybe_unused, int unset)
{
@@ -1040,62 +922,119 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
return 0;
}

-static bool append_file;
-
-static const struct option options[] = {
- OPT_CALLBACK('e', "event", &evsel_list, "event",
- "event selector. use 'perf list' to list available events",
- parse_events_option),
- OPT_CALLBACK(0, "filter", &evsel_list, "filter",
- "event filter", parse_filter),
- OPT_BOOLEAN('i', "no-inherit", &no_inherit,
- "child tasks do not inherit counters"),
- OPT_STRING('p', "pid", &target.pid, "pid",
- "stat events on existing process id"),
- OPT_STRING('t', "tid", &target.tid, "tid",
- "stat events on existing thread id"),
- OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
- "system-wide collection from all CPUs"),
- OPT_BOOLEAN('g', "group", &group,
- "put the counters into a counter group"),
- OPT_BOOLEAN('c', "scale", &scale,
- "scale/normalize counters"),
- OPT_INCR('v', "verbose", &verbose,
- "be more verbose (show counter open errors, etc)"),
- OPT_INTEGER('r', "repeat", &run_count,
- "repeat command and print average + stddev (max: 100)"),
- OPT_BOOLEAN('n', "null", &null_run,
- "null run - dont start any counters"),
- OPT_INCR('d', "detailed", &detailed_run,
- "detailed run - start a lot of events"),
- OPT_BOOLEAN('S', "sync", &sync_run,
- "call sync() before starting a run"),
- OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
- "print large numbers with thousands\' separators",
- stat__set_big_num),
- OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
- "list of cpus to monitor in system-wide"),
- OPT_BOOLEAN('A', "no-aggr", &no_aggr,
- "disable CPU count aggregation"),
- OPT_STRING('x', "field-separator", &csv_sep, "separator",
- "print counts with custom separator"),
- OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
- "monitor event in cgroup name only",
- parse_cgroups),
- OPT_STRING('o', "output", &output_name, "file",
- "output file name"),
- OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
- OPT_INTEGER(0, "log-fd", &output_fd,
- "log output to fd, instead of stderr"),
- OPT_END()
-};
-
/*
* Add default attributes, if there were no attributes specified or
* if -d/--detailed, -d -d or -d -d -d is used:
*/
static int add_default_attributes(void)
{
+ struct perf_event_attr default_attrs[] = {
+
+ { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
+ { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
+ { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
+ { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
+
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
+ { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
+
+};
+
+/*
+ * Detailed stats (-d), covering the L1 and last level data caches:
+ */
+ struct perf_event_attr detailed_attrs[] = {
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_LL << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_LL << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+};
+
+/*
+ * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
+ */
+ struct perf_event_attr very_detailed_attrs[] = {
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1I << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1I << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_DTLB << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_DTLB << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_ITLB << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_ITLB << 0 |
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+
+};
+
+/*
+ * Very, very detailed stats (-d -d -d), adding prefetch events:
+ */
+ struct perf_event_attr very_very_detailed_attrs[] = {
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D << 0 |
+ (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
+
+ { .type = PERF_TYPE_HW_CACHE,
+ .config =
+ PERF_COUNT_HW_CACHE_L1D << 0 |
+ (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
+};
+
/* Set attrs if no event is selected and !null_run: */
if (null_run)
return 0;
@@ -1130,8 +1069,59 @@ static int add_default_attributes(void)

int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ bool append_file = false,
+ sync_run = false;
+ int output_fd = 0;
+ const char *output_name = NULL;
+ const struct option options[] = {
+ OPT_CALLBACK('e', "event", &evsel_list, "event",
+ "event selector. use 'perf list' to list available events",
+ parse_events_option),
+ OPT_CALLBACK(0, "filter", &evsel_list, "filter",
+ "event filter", parse_filter),
+ OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+ "child tasks do not inherit counters"),
+ OPT_STRING('p', "pid", &target.pid, "pid",
+ "stat events on existing process id"),
+ OPT_STRING('t', "tid", &target.tid, "tid",
+ "stat events on existing thread id"),
+ OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
+ "system-wide collection from all CPUs"),
+ OPT_BOOLEAN('g', "group", &group,
+ "put the counters into a counter group"),
+ OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
+ OPT_INCR('v', "verbose", &verbose,
+ "be more verbose (show counter open errors, etc)"),
+ OPT_INTEGER('r', "repeat", &run_count,
+ "repeat command and print average + stddev (max: 100)"),
+ OPT_BOOLEAN('n', "null", &null_run,
+ "null run - dont start any counters"),
+ OPT_INCR('d', "detailed", &detailed_run,
+ "detailed run - start a lot of events"),
+ OPT_BOOLEAN('S', "sync", &sync_run,
+ "call sync() before starting a run"),
+ OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
+ "print large numbers with thousands\' separators",
+ stat__set_big_num),
+ OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
+ "list of cpus to monitor in system-wide"),
+ OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
+ OPT_STRING('x', "field-separator", &csv_sep, "separator",
+ "print counts with custom separator"),
+ OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+ "monitor event in cgroup name only", parse_cgroups),
+ OPT_STRING('o', "output", &output_name, "file", "output file name"),
+ OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
+ OPT_INTEGER(0, "log-fd", &output_fd,
+ "log output to fd, instead of stderr"),
+ OPT_END()
+ };
+ const char * const stat_usage[] = {
+ "perf stat [<options>] [<command>]",
+ NULL
+ };
struct perf_evsel *pos;
- int status = -ENOMEM;
+ int status = -ENOMEM, run_idx;
const char *mode;

setlocale(LC_ALL, "");
--
1.7.1

2012-10-04 18:23:32

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 17/42] perf lock: Don't use globals where not needed to

From: Arnaldo Carvalho de Melo <[email protected]>

Some variables were global but used in just one function, so move it to
where it belongs.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-lock.c | 90 +++++++++++++++++++-------------------------
1 files changed, 39 insertions(+), 51 deletions(-)

diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 7d6e099..6f5f328 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -823,12 +823,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
return 0;
}

-static struct perf_tool eops = {
- .sample = process_sample_event,
- .comm = perf_event__process_comm,
- .ordered_samples = true,
-};
-
static const struct perf_evsel_str_handler lock_tracepoints[] = {
{ "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
{ "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -838,6 +832,11 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {

static int read_events(void)
{
+ struct perf_tool eops = {
+ .sample = process_sample_event,
+ .comm = perf_event__process_comm,
+ .ordered_samples = true,
+ };
session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
if (!session) {
pr_err("Initializing perf session failed\n");
@@ -878,53 +877,11 @@ static int __cmd_report(void)
return 0;
}

-static const char * const report_usage[] = {
- "perf lock report [<options>]",
- NULL
-};
-
-static const struct option report_options[] = {
- OPT_STRING('k', "key", &sort_key, "acquired",
- "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
- /* TODO: type */
- OPT_END()
-};
-
-static const char * const info_usage[] = {
- "perf lock info [<options>]",
- NULL
-};
-
-static const struct option info_options[] = {
- OPT_BOOLEAN('t', "threads", &info_threads,
- "dump thread list in perf.data"),
- OPT_BOOLEAN('m', "map", &info_map,
- "map of lock instances (address:name table)"),
- OPT_END()
-};
-
-static const char * const lock_usage[] = {
- "perf lock [<options>] {record|report|script|info}",
- NULL
-};
-
-static const struct option lock_options[] = {
- OPT_STRING('i', "input", &input_name, "file", "input file name"),
- OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
- OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
- OPT_END()
-};
-
-static const char *record_args[] = {
- "record",
- "-R",
- "-f",
- "-m", "1024",
- "-c", "1",
-};
-
static int __cmd_record(int argc, const char **argv)
{
+ const char *record_args[] = {
+ "record", "-R", "-f", "-m", "1024", "-c", "1",
+ };
unsigned int rec_argc, i, j;
const char **rec_argv;

@@ -963,6 +920,37 @@ static int __cmd_record(int argc, const char **argv)

int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ const struct option info_options[] = {
+ OPT_BOOLEAN('t', "threads", &info_threads,
+ "dump thread list in perf.data"),
+ OPT_BOOLEAN('m', "map", &info_map,
+ "map of lock instances (address:name table)"),
+ OPT_END()
+ };
+ const struct option lock_options[] = {
+ OPT_STRING('i', "input", &input_name, "file", "input file name"),
+ OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
+ OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
+ OPT_END()
+ };
+ const struct option report_options[] = {
+ OPT_STRING('k', "key", &sort_key, "acquired",
+ "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
+ /* TODO: type */
+ OPT_END()
+ };
+ const char * const info_usage[] = {
+ "perf lock info [<options>]",
+ NULL
+ };
+ const char * const lock_usage[] = {
+ "perf lock [<options>] {record|report|script|info}",
+ NULL
+ };
+ const char * const report_usage[] = {
+ "perf lock report [<options>]",
+ NULL
+ };
unsigned int i;
int rc = 0;

--
1.7.1

2012-10-04 18:24:41

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/42] perf tools: Convert to GTK2_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without gtk+2, we can set NO_GTK2=1 as a argument of
make. It then defines NO_GTK2_SUPPORT macro for C code to do the
proper handling. However it usually used in a negative semantics -
e.g. #ifndef - so we saw double negations which can be misleading.
Convert it to a positive form to make it more readable.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 ++----
tools/perf/ui/helpline.h | 8 ++++----
tools/perf/util/cache.h | 28 +++++++++++++++-------------
tools/perf/util/debug.c | 2 +-
tools/perf/util/debug.h | 17 +++++++++--------
tools/perf/util/hist.h | 11 +++++------
6 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 3d2181c..31a07f9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -583,17 +583,15 @@ ifndef NO_NEWT
endif
endif

-ifdef NO_GTK2
- BASIC_CFLAGS += -DNO_GTK2_SUPPORT
-else
+ifndef NO_GTK2
FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
- BASIC_CFLAGS += -DNO_GTK2_SUPPORT
else
ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
endif
+ BASIC_CFLAGS += -DGTK2_SUPPORT
BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index e1f126b..baa28a4 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -34,14 +34,14 @@ static inline int ui_helpline__show_help(const char *format __maybe_unused,
}
#endif /* NEWT_SUPPORT */

-#ifdef NO_GTK2_SUPPORT
+#ifdef GTK2_SUPPORT
+int perf_gtk__show_helpline(const char *format, va_list ap);
+#else
static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
va_list ap __maybe_unused)
{
return 0;
}
-#else
-int perf_gtk__show_helpline(const char *format, va_list ap);
-#endif /* NO_GTK2_SUPPORT */
+#endif /* GTK2_SUPPORT */

#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 70f318d..07aec06 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,14 +33,7 @@ extern int pager_use_color;

extern int use_browser;

-#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
-static inline void setup_browser(bool fallback_to_pager)
-{
- if (fallback_to_pager)
- setup_pager();
-}
-static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
-#else
+#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
void setup_browser(bool fallback_to_pager);
void exit_browser(bool wait_for_ok);

@@ -55,17 +48,26 @@ static inline int ui__init(void)
static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
#endif

-#ifdef NO_GTK2_SUPPORT
+#ifdef GTK2_SUPPORT
+int perf_gtk__init(void);
+void perf_gtk__exit(bool wait_for_ok);
+#else
static inline int perf_gtk__init(void)
{
return -1;
}
static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
-#else
-int perf_gtk__init(void);
-void perf_gtk__exit(bool wait_for_ok);
#endif
-#endif /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */
+
+#else /* NEWT_SUPPORT || GTK2_SUPPORT */
+
+static inline void setup_browser(bool fallback_to_pager)
+{
+ if (fallback_to_pager)
+ setup_pager();
+}
+static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
+#endif /* NEWT_SUPPORT || GTK2_SUPPORT */

char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 0f6ad70..03f830b 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
return ret;
}

-#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
int ui__warning(const char *format, ...)
{
va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 3fe9ade..dec9875 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -15,7 +15,14 @@ void trace_event(union perf_event *event);
struct ui_progress;
struct perf_error_ops;

-#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
+
+#include "../ui/progress.h"
+int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
+#include "../ui/util.h"
+
+#else
+
static inline void ui_progress__update(u64 curr __maybe_unused,
u64 total __maybe_unused,
const char *title __maybe_unused) {}
@@ -34,13 +41,7 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
return 0;
}

-#else /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */
-
-#include "../ui/progress.h"
-int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#include "../ui/util.h"
-
-#endif /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */
+#endif /* NEWT_SUPPORT || GTK2_SUPPORT */

int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
int ui__error_paranoid(void);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 843638d..6ca7407 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -187,7 +187,11 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
#define K_RIGHT -2
#endif

-#ifdef NO_GTK2_SUPPORT
+#ifdef GTK2_SUPPORT
+int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
+ void(*timer)(void *arg), void *arg,
+ int refresh);
+#else
static inline
int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
const char *help __maybe_unused,
@@ -197,11 +201,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
{
return 0;
}
-
-#else
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
- void(*timer)(void *arg), void *arg,
- int refresh);
#endif

unsigned int hists__sort_list_width(struct hists *self);
--
1.7.1

2012-10-04 18:24:42

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/42] perf tools: Convert to LIBUNWIND_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without libunwind, we can set NO_LIBUNWIND=1 as a
argument of make. It then defines NO_LIBUNWIND_SUPPORT macro for C code
to do the proper handling. However it usually used in a negative
semantics - e.g. #ifndef - so we saw double negations which can be
misleading. Convert it to a positive form to make it more readable.

Also change NO_PERF_REGS macro to HAVE_PERF_REGS for the same reason.

Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Jiri Olsa <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 8 +++-----
tools/perf/builtin-record.c | 14 +++++++-------
tools/perf/util/perf_regs.h | 4 ++--
tools/perf/util/unwind.h | 4 ++--
4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 1df0917..6763024 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -535,9 +535,8 @@ endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF
endif # NO_LIBELF

-ifdef NO_LIBUNWIND
- BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT
-else
+ifndef NO_LIBUNWIND
+ BASIC_CFLAGS += -DLIBUNWIND_SUPPORT
EXTLIBS += $(LIBUNWIND_LIBS)
BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
@@ -747,8 +746,7 @@ ifeq ($(NO_PERF_REGS),0)
ifeq ($(ARCH),x86)
LIB_H += arch/x86/include/perf_regs.h
endif
-else
- BASIC_CFLAGS += -DNO_PERF_REGS
+ BASIC_CFLAGS += -DHAVE_PERF_REGS
endif

ifdef NO_STRLCPY
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f14cb5f..8c029fe 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -33,11 +33,11 @@

#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "

-#ifdef NO_LIBUNWIND_SUPPORT
-static char callchain_help[] = CALLCHAIN_HELP "[fp]";
-#else
+#ifdef LIBUNWIND_SUPPORT
static unsigned long default_stack_dump_size = 8192;
static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+#else
+static char callchain_help[] = CALLCHAIN_HELP "[fp]";
#endif

enum write_mode_t {
@@ -800,7 +800,7 @@ error:
return ret;
}

-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
static int get_stack_size(char *str, unsigned long *_size)
{
char *endptr;
@@ -826,7 +826,7 @@ static int get_stack_size(char *str, unsigned long *_size)
max_size, str);
return -1;
}
-#endif /* !NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */

static int
parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
@@ -865,7 +865,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
"needed for -g fp\n");
break;

-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
/* Dwarf style */
} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
ret = 0;
@@ -883,7 +883,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
if (!ret)
pr_debug("callchain: stack dump size %d\n",
rec->opts.stack_dump_size);
-#endif /* !NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */
} else {
pr_err("callchain: Unknown -g option "
"value: %s\n", arg);
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 316dbe7..5a4f2b6 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
#ifndef __PERF_REGS_H
#define __PERF_REGS_H

-#ifndef NO_PERF_REGS
+#ifdef HAVE_PERF_REGS
#include <perf_regs.h>
#else
#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
{
return NULL;
}
-#endif /* NO_PERF_REGS */
+#endif /* HAVE_PERF_REGS */
#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index a78c8b3..cb6bc50 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {

typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);

-#ifndef NO_LIBUNWIND_SUPPORT
+#ifdef LIBUNWIND_SUPPORT
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct machine *machine,
struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
{
return 0;
}
-#endif /* NO_LIBUNWIND_SUPPORT */
+#endif /* LIBUNWIND_SUPPORT */
#endif /* __UNWIND_H */
--
1.7.1

2012-10-04 18:24:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/42] perf trace: Use evsel->handler.func

From: Arnaldo Carvalho de Melo <[email protected]>

I.e. we don't need to resolve the evsel via the id and then check if it
is this or that event, just stash the right handler at evsel creation
time, then use evsel->handler.func() straight away.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-trace.c | 132 +++++++++++++++++++++++++++++---------------
1 files changed, 87 insertions(+), 45 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8f113da..76b1202 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
return printed;
}

+typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
+ struct perf_sample *sample);
+
+static struct syscall *trace__syscall_info(struct trace *trace,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample)
+{
+ int id = perf_evsel__intval(evsel, sample, "id");
+
+ if (id < 0) {
+ printf("Invalid syscall %d id, skipping...\n", id);
+ return NULL;
+ }
+
+ if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
+ trace__read_syscall_info(trace, id))
+ goto out_cant_read;
+
+ if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
+ goto out_cant_read;
+
+ return &trace->syscalls.table[id];
+
+out_cant_read:
+ printf("Problems reading syscall %d information\n", id);
+ return NULL;
+}
+
+static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
+ struct perf_sample *sample)
+{
+ void *args;
+ struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+ if (sc == NULL)
+ return -1;
+
+ args = perf_evsel__rawptr(evsel, sample, "args");
+ if (args == NULL) {
+ printf("Problems reading syscall arguments\n");
+ return -1;
+ }
+
+ printf("%s(", sc->name);
+ syscall__fprintf_args(sc, args, stdout);
+
+ return 0;
+}
+
+static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
+ struct perf_sample *sample)
+{
+ int ret;
+ struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+ if (sc == NULL)
+ return -1;
+
+ ret = perf_evsel__intval(evsel, sample, "ret");
+
+ if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
+ char bf[256];
+ const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
+ *e = audit_errno_to_name(-ret);
+
+ printf(") = -1 %s %s", e, emsg);
+ } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
+ printf(") = 0 Timeout");
+ else
+ printf(") = %d", ret);
+
+ putchar('\n');
+ return 0;
+}
+
static int trace__run(struct trace *trace)
{
struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
- struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
+ struct perf_evsel *evsel;
int err = -1, i, nr_events = 0, before;

if (evlist == NULL) {
@@ -125,21 +200,23 @@ static int trace__run(struct trace *trace)
goto out;
}

- evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
- if (evsel_enter == NULL) {
+ evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
+ if (evsel == NULL) {
printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
goto out_delete_evlist;
}

- perf_evlist__add(evlist, evsel_enter);
+ evsel->handler.func = trace__sys_enter;
+ perf_evlist__add(evlist, evsel);

- evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
- if (evsel_exit == NULL) {
+ evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
+ if (evsel == NULL) {
printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
goto out_delete_evlist;
}

- perf_evlist__add(evlist, evsel_exit);
+ evsel->handler.func = trace__sys_exit;
+ perf_evlist__add(evlist, evsel);

err = perf_evlist__create_maps(evlist, &trace->opts.target);
if (err < 0) {
@@ -170,9 +247,8 @@ again:

while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
const u32 type = event->header.type;
- struct syscall *sc;
+ tracepoint_handler handler;
struct perf_sample sample;
- int id;

++nr_events;

@@ -200,45 +276,11 @@ again:
continue;
}

- id = perf_evsel__intval(evsel, &sample, "id");
- if (id < 0) {
- printf("Invalid syscall %d id, skipping...\n", id);
- continue;
- }
-
- if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
- trace__read_syscall_info(trace, id))
- continue;
-
- if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
- continue;
-
- sc = &trace->syscalls.table[id];
-
if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
printf("%d ", sample.tid);

- if (evsel == evsel_enter) {
- void *args = perf_evsel__rawptr(evsel, &sample, "args");
-
- printf("%s(", sc->name);
- syscall__fprintf_args(sc, args, stdout);
- } else if (evsel == evsel_exit) {
- int ret = perf_evsel__intval(evsel, &sample, "ret");
-
- if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
- char bf[256];
- const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
- *e = audit_errno_to_name(-ret);
-
- printf(") = -1 %s %s", e, emsg);
- } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
- printf(") = 0 Timeout");
- else
- printf(") = %d", ret);
-
- putchar('\n');
- }
+ handler = evsel->handler.func;
+ handler(trace, evsel, &sample);
}
}

--
1.7.1

2012-10-04 18:24:38

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/42] perf tools: Convert to NEWT_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without libnewt, we can set NO_NEWT=1 as a argument of
make. It then defines NO_NEWT_SUPPORT macro for C code to do the proper
handling. However it usually used in a negative semantics - e.g. #ifndef -
so we saw double negations which can be misleading. Convert it to a
positive form to make it more readable.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 8 +++-----
tools/perf/ui/gtk/util.c | 2 +-
tools/perf/ui/helpline.h | 10 +++++-----
tools/perf/util/annotate.h | 8 ++++----
tools/perf/util/cache.h | 12 ++++++------
tools/perf/util/debug.c | 2 +-
tools/perf/util/debug.h | 6 +++---
tools/perf/util/hist.h | 18 +++++++++---------
8 files changed, 32 insertions(+), 34 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 99b2bb3..3d2181c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -554,16 +554,14 @@ ifndef NO_LIBAUDIT
endif
endif

-ifdef NO_NEWT
- BASIC_CFLAGS += -DNO_NEWT_SUPPORT
-else
+ifndef NO_NEWT
FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
- BASIC_CFLAGS += -DNO_NEWT_SUPPORT
else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
BASIC_CFLAGS += -I/usr/include/slang
+ BASIC_CFLAGS += -DNEWT_SUPPORT
EXTLIBS += -lnewt -lslang
LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/browser.o
@@ -603,7 +601,7 @@ else
LIB_OBJS += $(OUTPUT)ui/gtk/util.o
LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
# Make sure that it'd be included only once.
- ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
+ ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/util.o
endif
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 8aada5b..ccb046a 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -116,7 +116,7 @@ struct perf_error_ops perf_gtk_eops = {
* FIXME: Functions below should be implemented properly.
* For now, just add stubs for NO_NEWT=1 build.
*/
-#ifdef NO_NEWT_SUPPORT
+#ifndef NEWT_SUPPORT
void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
const char *title __maybe_unused)
{
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 2b667ee..e1f126b 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -23,16 +23,16 @@ void ui_helpline__puts(const char *msg);

extern char ui_helpline__current[512];

-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+extern char ui_helpline__last_msg[];
+int ui_helpline__show_help(const char *format, va_list ap);
+#else
static inline int ui_helpline__show_help(const char *format __maybe_unused,
va_list ap __maybe_unused)
{
return 0;
}
-#else
-extern char ui_helpline__last_msg[];
-int ui_helpline__show_help(const char *format, va_list ap);
-#endif /* NO_NEWT_SUPPORT */
+#endif /* NEWT_SUPPORT */

#ifdef NO_GTK2_SUPPORT
static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9b5b21e..39242dc 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -138,7 +138,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
bool print_lines, bool full_paths, int min_pcnt,
int max_lines);

-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+ void(*timer)(void *arg), void *arg, int delay_secs);
+#else
static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
struct map *map __maybe_unused,
int evidx __maybe_unused,
@@ -148,9 +151,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
{
return 0;
}
-#else
-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
- void(*timer)(void *arg), void *arg, int delay_secs);
#endif

extern const char *disassembler_style;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index ab17694..70f318d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,7 +33,7 @@ extern int pager_use_color;

extern int use_browser;

-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
static inline void setup_browser(bool fallback_to_pager)
{
if (fallback_to_pager)
@@ -44,15 +44,15 @@ static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
void setup_browser(bool fallback_to_pager);
void exit_browser(bool wait_for_ok);

-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+int ui__init(void);
+void ui__exit(bool wait_for_ok);
+#else
static inline int ui__init(void)
{
return -1;
}
static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
-#else
-int ui__init(void);
-void ui__exit(bool wait_for_ok);
#endif

#ifdef NO_GTK2_SUPPORT
@@ -65,7 +65,7 @@ static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
int perf_gtk__init(void);
void perf_gtk__exit(bool wait_for_ok);
#endif
-#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+#endif /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */

char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 66eb382..0f6ad70 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
return ret;
}

-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
int ui__warning(const char *format, ...)
{
va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index bb2e7d1..3fe9ade 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -15,7 +15,7 @@ void trace_event(union perf_event *event);
struct ui_progress;
struct perf_error_ops;

-#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
+#if !defined(NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
static inline void ui_progress__update(u64 curr __maybe_unused,
u64 total __maybe_unused,
const char *title __maybe_unused) {}
@@ -34,13 +34,13 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
return 0;
}

-#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+#else /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */

#include "../ui/progress.h"
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
#include "../ui/util.h"

-#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+#endif /* !NEWT_SUPPORT && NO_GTK2_SUPPORT */

int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
int ui__error_paranoid(void);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f011ad4..843638d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -154,7 +154,15 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,

struct perf_evlist;

-#ifdef NO_NEWT_SUPPORT
+#ifdef NEWT_SUPPORT
+#include "../ui/keysyms.h"
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+ void(*timer)(void *arg), void *arg, int delay_secs);
+
+int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
+ void(*timer)(void *arg), void *arg,
+ int refresh);
+#else
static inline
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
const char *help __maybe_unused,
@@ -177,14 +185,6 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
}
#define K_LEFT -1
#define K_RIGHT -2
-#else
-#include "../ui/keysyms.h"
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
- void(*timer)(void *arg), void *arg, int delay_secs);
-
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
- void(*timer)(void *arg), void *arg,
- int refresh);
#endif

#ifdef NO_GTK2_SUPPORT
--
1.7.1

2012-10-04 18:25:51

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/42] perf tools: Convert to LIBAUDIT_SUPPORT

From: Namhyung Kim <[email protected]>

For building perf without libaudit, we can set NO_LIBAUDIT=1 as a
argument of make. It then defines NO_LIBAUDIT_SUPPORT macro for C code
to do the proper handling. However it usually used in a negative
semantics - e.g. #ifndef - so we saw double negations which can be
misleading. Convert it to a positive form to make it more readable.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 ++----
tools/perf/perf.c | 2 +-
2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 6763024..99b2bb3 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -543,14 +543,12 @@ ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)util/unwind.o
endif

-ifdef NO_LIBAUDIT
- BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
-else
+ifndef NO_LIBAUDIT
FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
- BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
else
+ BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
EXTLIBS += -laudit
endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index dacae4b..6d50eb0 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -55,7 +55,7 @@ static struct cmd_struct commands[] = {
{ "lock", cmd_lock, 0 },
{ "kvm", cmd_kvm, 0 },
{ "test", cmd_test, 0 },
-#ifndef NO_LIBAUDIT_SUPPORT
+#ifdef LIBAUDIT_SUPPORT
{ "trace", cmd_trace, 0 },
#endif
{ "inject", cmd_inject, 0 },
--
1.7.1

2012-10-04 18:25:50

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/42] perf inject: Remove unused 'input_name' static var

From: Arnaldo Carvalho de Melo <[email protected]>

If we ever want to allow inject to work with something other than stdin,
we can put it back, but so far it is completely unused, so ditch it.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-inject.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index b5ab084..e249f24 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,7 +14,6 @@

#include "util/parse-options.h"

-static char const *input_name = "-";
static bool inject_build_ids;

static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
@@ -245,7 +244,7 @@ static int __cmd_inject(void)
perf_inject.tracing_data = perf_event__repipe_tracing_data;
}

- session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
+ session = perf_session__new("-", O_RDONLY, false, true, &perf_inject);
if (session == NULL)
return -ENOMEM;

--
1.7.1

2012-10-04 18:26:38

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/42] perf tools: Remove unused PYRF_OBJS variable on Makefile

From: Namhyung Kim <[email protected]>

It seems that the PYRF_OBJS variable is not used anymore or has no
effect at least. The util/setup.py tracks its dependency using
util/python-ext-sources file and resulting objects are saved under
python_ext_build/tmp/.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 16 +---------------
1 files changed, 1 insertions(+), 15 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 834f09f..9cd4913 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -185,7 +185,7 @@ strip-libs = $(filter-out -l%,$(1))
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py

-$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
+$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
$(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
--quiet build_ext; \
mkdir -p $(OUTPUT)python && \
@@ -446,20 +446,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o

PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)

-# Files needed for the python binding, perf.so
-# pyrf is just an internal name needed for all those wrappers.
-# This has to be in sync with what is in the 'sources' variable in
-# tools/perf/util/setup.py
-
-PYRF_OBJS += $(OUTPUT)util/cpumap.o
-PYRF_OBJS += $(OUTPUT)util/ctype.o
-PYRF_OBJS += $(OUTPUT)util/evlist.o
-PYRF_OBJS += $(OUTPUT)util/evsel.o
-PYRF_OBJS += $(OUTPUT)util/python.o
-PYRF_OBJS += $(OUTPUT)util/thread_map.o
-PYRF_OBJS += $(OUTPUT)util/util.o
-PYRF_OBJS += $(OUTPUT)util/xyarray.o
-
#
# Platform specific tweaks
#
--
1.7.1

2012-10-05 08:18:15

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/42] perf/core improvements and fixes


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 29a0fc9b2b6084e7a8810481df62a0fa496d8957:
>
> perf tools: Convert to LIBELF_SUPPORT (2012-09-28 21:07:36 -0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo
>
> for you to fetch changes up to 139c0815903de1a7865fe1d6beac5e995fefdf46:
>
> perf hists: Add more helpers for hist entry stat (2012-10-04 13:36:18 -0300)

Pulled, thanks Arnaldo.

Note that the old dependency related build failure thought to be
fixed in commit 860df5833e46 is back:

make[1]: *** No rule to make target
`/usr/lib/gcc/x86_64-redhat-linux/4.7.0/include/stddef.h', needed by `.trace-seq.d'. Stop.

'make clean' itself does not work in libtraceevent:

comet:~/tip/tools/lib/traceevent> make clean
make: *** No rule to make target `/usr/lib/gcc/x86_64-redhat-linux/4.7.0/include/stddef.h', needed by `.trace-seq.d'. Stop.

So I had to clean it out manually:

comet:~/tip/tools/lib/traceevent> git ls-files --others | xargs rm
comet:~/tip/tools/lib/traceevent>

and then things build fine.

I also noticed a 'perf trace' bug, after running 'perf trace' it
outputs lines but then gets hung:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6081 mingo 20 0 18.2g 14g 3544 D 18.6 91.2 0:20.28 perf

and then after half a minute it gets active again, outputting
lines and then segfaulting:

LOST 1 events!
31082 ) = 375
31082 write(fd: 3, buf: 140030569454096, count: 48LOST 1 events!
31082 select(n: 13, inp: 140030569376688, outp: 140030569376656, exp: 0, tvp: 031082 ) = 2
Segmentation fault

It's a 16-way box running:

Linux comet 3.5.4-1.fc17.x86_64 #1 SMP Mon Sep 17 15:03:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

Note how much the RSS is, 14 GB of RAM with less of 1 minute
running. The segfault might be related to a failed allocation
not being handled correctly perhaps.

Thanks,

Ingo

2012-10-05 08:44:46

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH] tools lib traceevent: Do not generate dependency for system header files

Ingo reported (again!) that 'make clean' on perf/traceevent does not
work due to some reason with system header file. Quotes Ingo:

"Note that the old dependency related build failure thought to be
fixed in commit 860df5833e46 is back:

make[1]: *** No rule to make target
`/usr/lib/gcc/x86_64-redhat-linux/4.7.0/include/stddef.h', needed by `.trace-seq.d'. Stop.

'make clean' itself does not work in libtraceevent:

comet:~/tip/tools/lib/traceevent> make clean
make: *** No rule to make target `/usr/lib/gcc/x86_64-redhat-linux/4.7.0/include/stddef.h', needed by `.trace-seq.d'. Stop.

So I had to clean it out manually:

comet:~/tip/tools/lib/traceevent> git ls-files --others | xargs rm
comet:~/tip/tools/lib/traceevent>

and then things build fine."

Try to fix it by excluding system headers from dependency generation.

Reported-by: Ingo Molnar <[email protected]>
Cc: Steven Rostedt <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/lib/traceevent/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 04d959fa0226..a20e32033431 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -253,7 +253,7 @@ all_deps := $(all_objs:%.o=.%.d)
# let .d file also depends on the source and header files
define check_deps
@set -e; $(RM) $@; \
- $(CC) -M $(CFLAGS) $< > $@.$$$$; \
+ $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
endef
--
1.7.11.4

2012-10-05 09:01:28

by Namhyung Kim

[permalink] [raw]
Subject: Re: [GIT PULL 00/42] perf/core improvements and fixes

Hi Ingo,

On Fri, 5 Oct 2012 10:18:04 +0200, Ingo Molnar wrote:
> I also noticed a 'perf trace' bug, after running 'perf trace' it
> outputs lines but then gets hung:
>
> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
> 6081 mingo 20 0 18.2g 14g 3544 D 18.6 91.2 0:20.28 perf
>
> and then after half a minute it gets active again, outputting
> lines and then segfaulting:
>
> LOST 1 events!
> 31082 ) = 375
> 31082 write(fd: 3, buf: 140030569454096, count: 48LOST 1 events!
> 31082 select(n: 13, inp: 140030569376688, outp: 140030569376656, exp: 0, tvp: 031082 ) = 2
> Segmentation fault
>
> It's a 16-way box running:
>
> Linux comet 3.5.4-1.fc17.x86_64 #1 SMP Mon Sep 17 15:03:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
>
> Note how much the RSS is, 14 GB of RAM with less of 1 minute
> running. The segfault might be related to a failed allocation
> not being handled correctly perhaps.

I also hit the segfault but it was due to a broken sample data:

Core was generated by `./perf trace'.
Program terminated with signal 11, Segmentation fault.
#0 perf_evsel__intval (evsel=evsel@entry=0xeae8c0, sample=sample@entry=0x7fff42278130, name=name@entry=0x55034d "id")
at util/evsel.c:1148
1148 value = *(u64 *)ptr;

(gdb) bt
#0 perf_evsel__intval (evsel=evsel@entry=0xeae8c0, sample=sample@entry=0x7fff42278130, name=name@entry=0x55034d "id")
at util/evsel.c:1148
#1 0x0000000000446987 in trace__syscall_info (sample=0x7fff42278130, evsel=0xeae8c0, trace=0x7fff422781b0)
at builtin-trace.c:147
#2 trace__sys_exit (trace=0x7fff422781b0, evsel=0xeae8c0, sample=0x7fff42278130) at builtin-trace.c:193
#3 0x00000000004470c1 in trace__run (argv=<optimized out>, argc=<optimized out>, trace=0x7fff422781b0) at builtin-trace.c:310
#4 cmd_trace (argc=<optimized out>, argv=<optimized out>, prefix=<optimized out>) at builtin-trace.c:396
#5 0x0000000000418c93 in run_builtin (p=p@entry=0x7b19d8, argc=argc@entry=1, argv=argv@entry=0x7fff4227a7a0) at perf.c:312
#6 0x000000000041846e in handle_internal_command (argv=0x7fff4227a7a0, argc=1) at perf.c:360
#7 run_argv (argv=0x7fff4227a590, argcp=0x7fff4227a59c) at perf.c:404
#8 main (argc=1, argv=0x7fff4227a7a0) at perf.c:502
(gdb) list
1143 break;
1144 case 4:
1145 value = *(u32 *)ptr;
1146 break;
1147 case 8:
1148 value = *(u64 *)ptr;
1149 break;
1150 default:
1151 return 0;
1152 }
(gdb) p ptr
$1 = (void *) 0x10
(gdb) p *sample
$2 = {ip = 0, pid = 0, tid = 0, time = 15762598695796738, addr = 0, id = 315, stream_id = 18446744073709551615, period = 1,
cpu = 143, raw_size = 0, raw_data = 0x0, callchain = 0x0, branch_stack = 0x0, user_regs = {regs = 0x0}, user_stack = {
offset = 0, size = 0, data = 0x0}}


In this case 'sample->raw_data' was NULL and other fields seemed invalid
as well. I guess we need some kind of protection?

Thanks,
Namhyung

2012-10-05 10:22:17

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/42] perf/core improvements and fixes


* Namhyung Kim <[email protected]> wrote:

> Hi Ingo,
>
> On Fri, 5 Oct 2012 10:18:04 +0200, Ingo Molnar wrote:
> > I also noticed a 'perf trace' bug, after running 'perf trace' it
> > outputs lines but then gets hung:
> >
> > PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
> > 6081 mingo 20 0 18.2g 14g 3544 D 18.6 91.2 0:20.28 perf
> >
> > and then after half a minute it gets active again, outputting
> > lines and then segfaulting:
> >
> > LOST 1 events!
> > 31082 ) = 375
> > 31082 write(fd: 3, buf: 140030569454096, count: 48LOST 1 events!
> > 31082 select(n: 13, inp: 140030569376688, outp: 140030569376656, exp: 0, tvp: 031082 ) = 2
> > Segmentation fault
> >
> > It's a 16-way box running:
> >
> > Linux comet 3.5.4-1.fc17.x86_64 #1 SMP Mon Sep 17 15:03:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
> >
> > Note how much the RSS is, 14 GB of RAM with less of 1 minute
> > running. The segfault might be related to a failed allocation
> > not being handled correctly perhaps.
>
> I also hit the segfault but it was due to a broken sample data:
>
> Core was generated by `./perf trace'.
> Program terminated with signal 11, Segmentation fault.
> #0 perf_evsel__intval (evsel=evsel@entry=0xeae8c0, sample=sample@entry=0x7fff42278130, name=name@entry=0x55034d "id")
> at util/evsel.c:1148
> 1148 value = *(u64 *)ptr;
>
> (gdb) bt
> #0 perf_evsel__intval (evsel=evsel@entry=0xeae8c0, sample=sample@entry=0x7fff42278130, name=name@entry=0x55034d "id")
> at util/evsel.c:1148
> #1 0x0000000000446987 in trace__syscall_info (sample=0x7fff42278130, evsel=0xeae8c0, trace=0x7fff422781b0)
> at builtin-trace.c:147
> #2 trace__sys_exit (trace=0x7fff422781b0, evsel=0xeae8c0, sample=0x7fff42278130) at builtin-trace.c:193
> #3 0x00000000004470c1 in trace__run (argv=<optimized out>, argc=<optimized out>, trace=0x7fff422781b0) at builtin-trace.c:310
> #4 cmd_trace (argc=<optimized out>, argv=<optimized out>, prefix=<optimized out>) at builtin-trace.c:396
> #5 0x0000000000418c93 in run_builtin (p=p@entry=0x7b19d8, argc=argc@entry=1, argv=argv@entry=0x7fff4227a7a0) at perf.c:312
> #6 0x000000000041846e in handle_internal_command (argv=0x7fff4227a7a0, argc=1) at perf.c:360
> #7 run_argv (argv=0x7fff4227a590, argcp=0x7fff4227a59c) at perf.c:404
> #8 main (argc=1, argv=0x7fff4227a7a0) at perf.c:502
> (gdb) list
> 1143 break;
> 1144 case 4:
> 1145 value = *(u32 *)ptr;
> 1146 break;
> 1147 case 8:
> 1148 value = *(u64 *)ptr;
> 1149 break;
> 1150 default:
> 1151 return 0;
> 1152 }
> (gdb) p ptr
> $1 = (void *) 0x10
> (gdb) p *sample
> $2 = {ip = 0, pid = 0, tid = 0, time = 15762598695796738, addr = 0, id = 315, stream_id = 18446744073709551615, period = 1,
> cpu = 143, raw_size = 0, raw_data = 0x0, callchain = 0x0, branch_stack = 0x0, user_regs = {regs = 0x0}, user_stack = {
> offset = 0, size = 0, data = 0x0}}
>
>
> In this case 'sample->raw_data' was NULL and other fields
> seemed invalid as well. I guess we need some kind of
> protection?

Yeah, the code should assume the perf.data to be 100% untrusted,
i.e. it can be random input and should never crash, lock up or
misbehave.

Thanks,

Ingo

2012-10-05 12:39:27

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 33/42] perf tools: Complete tracepoint event names

On Thu, Oct 04, 2012 at 03:08:33PM -0300, Arnaldo Carvalho de Melo wrote:
> From: Namhyung Kim <[email protected]>
>
> Currently tracepoint events cannot be completed because they contain a
> colon (:) character. The colon is considered as a word separator when
> bash completion is done - variable COMP_WORDBREAKS contains colon - so
> if a word being completed contains a colon it can be a problem.
>
> Recent versions of bash completion provide -n switch to
> _get_comp_words_by_ref and __ltrim_colon_completions functions in order
> to resolve this issue. Copy the latter in case not exists.

Thanks for fixing this! I scratched my head on that bug.