diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-08-05 10:32:54 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-08-05 10:33:55 +0200 |
commit | 3272cab4063467410802367a8d69f06c65b2a866 (patch) | |
tree | 1c665f8572b0aab2a5343d32b5eaa6713669b04f /tools/perf | |
parent | f629299b544b6cc12b4e3e85fec96f4ce5809482 (diff) | |
parent | 140d0b2108faebc77c6523296e211e509cb9f5f9 (diff) |
Merge branch 'linus' into perf/urgent
Merge reason: Include most of the merge window trees, to do fixes on top.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
34 files changed, 1816 insertions, 1029 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 6f5a498608b..85c5f026930 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -66,6 +66,12 @@ OPTIONS used. This interfaces starts by centering on the line with more samples, TAB/UNTAB cycles through the lines with more samples. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 02bafce4b34..2780d9ce48b 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -34,9 +34,11 @@ OPTIONS Specify vmlinux path which has debuginfo (Dwarf binary). -m:: ---module=MODNAME:: +--module=MODNAME|PATH:: Specify module name in which perf-probe searches probe points - or lines. + or lines. If a path of module file is passed, perf-probe + treat it as an offline module (this means you can add a probe on + a module which has not been loaded yet). -s:: --source=PATH:: diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8ba03d6e539..04253c07d19 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -80,15 +80,24 @@ OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. --g [type,min]:: +-g [type,min,order]:: --call-graph:: - Display call chains using type and min percent threshold. + Display call chains using type, min percent threshold and order. type can be either: - flat: single column, linear exposure of call chains. - graph: use a graph tree, displaying absolute overhead rates. - fractal: like graph, but displays relative rates. Each branch of the tree is considered as a new profiled object. + - Default: fractal,0.5. + + order can be either: + - callee: callee based call graph. + - caller: inverted caller based call graph. + + Default: fractal,0.5,callee. + +-G:: +--inverted:: + alias for inverted caller based call graph. --pretty=<key>:: Pretty printing style. key: normal, raw @@ -119,6 +128,12 @@ OPTIONS --symfs=<directory>:: Look for files with symbols relative to this directory. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-stat[1] diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 86c87e214b1..db017867d9e 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -115,10 +115,10 @@ OPTIONS -f:: --fields:: Comma separated list of fields to print. Options are: - comm, tid, pid, time, cpu, event, trace, sym. Field - list can be prepended with the type, trace, sw or hw, + comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. + Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. - e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace + e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace perf script -f <fields> @@ -132,17 +132,17 @@ OPTIONS The arguments are processed in the order received. A later usage can reset a prior request. e.g.: - -f trace: -f comm,tid,time,sym + -f trace: -f comm,tid,time,ip,sym The first -f suppresses trace events (field list is ""), but then the - second invocation sets the fields to comm,tid,time,sym. In this case a + second invocation sets the fields to comm,tid,time,ip,sym. In this case a warning is given to the user: "Overriding previous field request for all events." Alternativey, consider the order: - -f comm,tid,time,sym -f trace: + -f comm,tid,time,ip,sym -f trace: The first -f sets the fields for all events and the second -f suppresses trace events. The user is given a warning message about @@ -182,6 +182,12 @@ OPTIONS --hide-call-graph:: When printing symbols do not display call chain. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-script-perl[1], diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c16836611d2..56d62d3fb16 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -282,6 +282,7 @@ LIB_H += util/thread.h LIB_H += util/thread_map.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h +LIB_H += util/dwarf-aux.h LIB_H += util/probe-event.h LIB_H += util/pstack.h LIB_H += util/cpumap.h @@ -438,6 +439,7 @@ else BASIC_CFLAGS += -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += $(OUTPUT)util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 7b139e1e7e8..555aefd7fe0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -28,6 +28,8 @@ #include "util/hist.h" #include "util/session.h" +#include <linux/bitmap.h> + static char const *input_name = "perf.data"; static bool force, use_tui, use_stdio; @@ -38,6 +40,9 @@ static bool print_line; static const char *sym_hist_filter; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); + static int perf_evlist__add_sample(struct perf_evlist *evlist, struct perf_sample *sample, struct perf_evsel *evsel, @@ -90,6 +95,9 @@ static int process_sample_event(union perf_event *event, return -1; } + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { pr_warning("problem incrementing symbol count, " @@ -177,6 +185,12 @@ static int __cmd_annotate(void) if (session == NULL) return -ENOMEM; + if (cpu_list) { + ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); + if (ret) + goto out_delete; + } + ret = perf_session__process_events(session, &event_ops); if (ret) goto out_delete; @@ -252,6 +266,7 @@ static const struct option options[] = { "print matching source lines (may be slow)"), OPT_BOOLEAN('P', "full-paths", &full_paths, "Don't shorten the displayed pathnames"), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2c0e64d0b4a..5f2a5c7046d 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -242,7 +242,8 @@ static const struct option options[] = { OPT_STRING('s', "source", &symbol_conf.source_prefix, "directory", "path to kernel source"), OPT_STRING('m', "module", ¶ms.target_module, - "modname", "target module name"), + "modname|path", + "target module name (for online) or path (for offline)"), #endif OPT__DRY_RUN(&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8e2c8579818..80dc5b790e4 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -740,7 +740,7 @@ static bool force, append_file; const struct option record_options[] = { OPT_CALLBACK('e', "event", &evsel_list, "event", "event selector. use 'perf list' to list available events", - parse_events), + parse_events_option), OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter), OPT_INTEGER('p', "pid", &target_pid, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 287a173523a..f854efda768 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -33,6 +33,8 @@ #include "util/sort.h" #include "util/hist.h" +#include <linux/bitmap.h> + static char const *input_name = "perf.data"; static bool force, use_tui, use_stdio; @@ -45,9 +47,13 @@ static struct perf_read_values show_threads_values; static const char default_pretty_printing_style[] = "normal"; static const char *pretty_printing_style = default_pretty_printing_style; -static char callchain_default_opt[] = "fractal,0.5"; +static char callchain_default_opt[] = "fractal,0.5,callee"; +static bool inverted_callchain; static symbol_filter_t annotate_init; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); + static int perf_session__add_hist_entry(struct perf_session *session, struct addr_location *al, struct perf_sample *sample, @@ -116,6 +122,9 @@ static int process_sample_event(union perf_event *event, if (al.filtered || (hide_unresolved && al.sym == NULL)) return 0; + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + if (al.map != NULL) al.map->dso->hit = 1; @@ -262,6 +271,12 @@ static int __cmd_report(void) if (session == NULL) return -ENOMEM; + if (cpu_list) { + ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); + if (ret) + goto out_delete; + } + if (show_threads) perf_read_values_init(&show_threads_values); @@ -386,13 +401,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, if (!tok) goto setup; - tok2 = strtok(NULL, ","); callchain_param.min_percent = strtod(tok, &endptr); if (tok == endptr) return -1; - if (tok2) + /* get the print limit */ + tok2 = strtok(NULL, ","); + if (!tok2) + goto setup; + + if (tok2[0] != 'c') { callchain_param.print_limit = strtod(tok2, &endptr); + tok2 = strtok(NULL, ","); + if (!tok2) + goto setup; + } + + /* get the call chain order */ + if (!strcmp(tok2, "caller")) + callchain_param.order = ORDER_CALLER; + else if (!strcmp(tok2, "callee")) + callchain_param.order = ORDER_CALLEE; + else + return -1; setup: if (callchain_register_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); @@ -436,9 +467,10 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, "Only display entries with parent-match"), - OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", - "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. " - "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), + OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order", + "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. " + "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), + OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", @@ -455,6 +487,7 @@ static const struct option options[] = { "Only display entries resolved to a symbol"), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; @@ -467,6 +500,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) else if (use_tui) use_browser = 1; + if (inverted_callchain) + callchain_param.order = ORDER_CALLER; + if (strcmp(input_name, "-") != 0) setup_browser(true); else @@ -504,7 +540,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) if (parent_pattern != default_parent_pattern) { if (sort_dimension__add("parent") < 0) return -1; - sort_parent.elide = 1; + + /* + * Only show the parent fields if we explicitly + * sort that way. If we only use parent machinery + * for filtering, we don't want it. + */ + if (!strstr(sort_order, "parent")) + sort_parent.elide = 1; } else symbol_conf.exclude_other = false; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 22747de7234..09024ec2ab2 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -13,6 +13,7 @@ #include "util/util.h" #include "util/evlist.h" #include "util/evsel.h" +#include <linux/bitmap.h> static char const *script_name; static char const *generate_script_lang; @@ -21,6 +22,8 @@ static u64 last_timestamp; static u64 nr_unordered; extern const struct option record_options[]; static bool no_callchain; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); enum perf_output_field { PERF_OUTPUT_COMM = 1U << 0, @@ -30,7 +33,10 @@ enum perf_output_field { PERF_OUTPUT_CPU = 1U << 4, PERF_OUTPUT_EVNAME = 1U << 5, PERF_OUTPUT_TRACE = 1U << 6, - PERF_OUTPUT_SYM = 1U << 7, + PERF_OUTPUT_IP = 1U << 7, + PERF_OUTPUT_SYM = 1U << 8, + PERF_OUTPUT_DSO = 1U << 9, + PERF_OUTPUT_ADDR = 1U << 10, }; struct output_option { @@ -44,7 +50,10 @@ struct output_option { {.str = "cpu", .field = PERF_OUTPUT_CPU}, {.str = "event", .field = PERF_OUTPUT_EVNAME}, {.str = "trace", .field = PERF_OUTPUT_TRACE}, + {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, + {.str = "dso", .field = PERF_OUTPUT_DSO}, + {.str = "addr", .field = PERF_OUTPUT_ADDR}, }; /* default set to maintain compatibility with current format */ @@ -60,7 +69,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -70,7 +80,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -88,7 +99,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -157,9 +169,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, !perf_session__has_traces(session, "record -R")) return -EINVAL; - if (PRINT_FIELD(SYM)) { + if (PRINT_FIELD(IP)) { if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", - PERF_OUTPUT_SYM)) + PERF_OUTPUT_IP)) return -EINVAL; if (!no_callchain && @@ -167,6 +179,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, symbol_conf.use_callchain = false; } + if (PRINT_FIELD(ADDR) && + perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", + PERF_OUTPUT_ADDR)) + return -EINVAL; + + if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { + pr_err("Display of symbols requested but neither sample IP nor " + "sample address\nis selected. Hence, no addresses to convert " + "to symbols.\n"); + return -EINVAL; + } + if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { + pr_err("Display of DSO requested but neither sample IP nor " + "sample address\nis selected. Hence, no addresses to convert " + "to DSO.\n"); + return -EINVAL; + } + if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID)) @@ -230,7 +260,7 @@ static void print_sample_start(struct perf_sample *sample, if (PRINT_FIELD(COMM)) { if (latency_format) printf("%8.8s ", thread->comm); - else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain) + else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) printf("%s ", thread->comm); else printf("%16s ", thread->comm); @@ -271,6 +301,63 @@ static void print_sample_start(struct perf_sample *sample, } } +static bool sample_addr_correlates_sym(struct perf_event_attr *attr) +{ + if ((attr->type == PERF_TYPE_SOFTWARE) && + ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) || + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) || + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) + return true; + + return false; +} + +static void print_sample_addr(union perf_event *event, + struct perf_sample *sample, + struct perf_session *session, + struct thread *thread, + struct perf_event_attr *attr) +{ + struct addr_location al; + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + const char *symname, *dsoname; + + printf("%16" PRIx64, sample->addr); + + if (!sample_addr_correlates_sym(attr)) + return; + + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, + event->ip.pid, sample->addr, &al); + if (!al.map) + thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, + event->ip.pid, sample->addr, &al); + + al.cpu = sample->cpu; + al.sym = NULL; + + if (al.map) + al.sym = map__find_symbol(al.map, al.addr, NULL); + + if (PRINT_FIELD(SYM)) { + if (al.sym && al.sym->name) + symname = al.sym->name; + else + symname = ""; + + printf(" %16s", symname); + } + + if (PRINT_FIELD(DSO)) { + if (al.map && al.map->dso && al.map->dso->name) + dsoname = al.map->dso->name; + else + dsoname = ""; + + printf(" (%s)", dsoname); + } +} + static void process_event(union perf_event *event __unused, struct perf_sample *sample, struct perf_evsel *evsel, @@ -288,12 +375,16 @@ static void process_event(union perf_event *event __unused, print_trace_event(sample->cpu, sample->raw_data, sample->raw_size); - if (PRINT_FIELD(SYM)) { + if (PRINT_FIELD(ADDR)) + print_sample_addr(event, sample, session, thread, attr); + + if (PRINT_FIELD(IP)) { if (!symbol_conf.use_callchain) printf(" "); else printf("\n"); - perf_session__print_symbols(event, sample, session); + perf_session__print_ip(event, sample, session, + PRINT_FIELD(SYM), PRINT_FIELD(DSO)); } printf("\n"); @@ -365,6 +456,10 @@ static int process_sample_event(union perf_event *event, last_timestamp = sample->time; return 0; } + + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + scripting_ops->process_event(event, sample, evsel, session, thread); session->hists.stats.total_period += sample->period; @@ -985,8 +1080,9 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_CALLBACK('f', "fields", NULL, "str", - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", + "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", parse_output_fields), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; @@ -1167,6 +1263,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) if (session == NULL) return -ENOMEM; + if (cpu_list) { + if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) + return -1; + } + if (!no_callchain) symbol_conf.use_callchain = true; else diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a9f06715e44..1ad04ce29c3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -61,6 +61,8 @@ #include <locale.h> #define DEFAULT_SEPARATOR " " +#define CNTR_NOT_SUPPORTED "<not supported>" +#define CNTR_NOT_COUNTED "<not counted>" static struct perf_event_attr default_attrs[] = { @@ -448,6 +450,7 @@ static int run_perf_stat(int argc __used, const char **argv) if (verbose) ui__warning("%s event is not supported by the kernel.\n", event_name(counter)); + counter->supported = false; continue; } @@ -466,6 +469,7 @@ static int run_perf_stat(int argc __used, const char **argv) die("Not all events could be opened.\n"); return -1; } + counter->supported = true; } if (perf_evlist__set_filters(evsel_list)) { @@ -513,7 +517,10 @@ static void print_noise_pct(double total, double avg) if (avg) pct = 100.0*total/avg; - fprintf(stderr, " ( +-%6.2f%% )", pct); + if (csv_output) + fprintf(stderr, "%s%.2f%%", csv_sep, pct); + else + fprintf(stderr, " ( +-%6.2f%% )", pct); } static void print_noise(struct perf_evsel *evsel, double avg) @@ -861,7 +868,7 @@ static void print_counter_aggr(struct perf_evsel *counter) if (scaled == -1) { fprintf(stderr, "%*s%s%*s", csv_output ? 0 : 18, - "<not counted>", + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, csv_sep, csv_output ? 0 : -24, event_name(counter)); @@ -878,13 +885,13 @@ static void print_counter_aggr(struct perf_evsel *counter) else abs_printout(-1, counter, avg); + print_noise(counter, avg); + if (csv_output) { fputc('\n', stderr); return; } - print_noise(counter, avg); - if (scaled) { double avg_enabled, avg_running; @@ -914,7 +921,8 @@ static void print_counter(struct perf_evsel *counter) csv_output ? 0 : -4, evsel_list->cpus->map[cpu], csv_sep, csv_output ? 0 : 18, - "<not counted>", csv_sep, + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, + csv_sep, csv_output ? 0 : -24, event_name(counter)); @@ -1024,7 +1032,7 @@ static int stat__set_big_num(const struct option *opt __used, static const struct option options[] = { OPT_CALLBACK('e', "event", &evsel_list, "event", "event selector. use 'perf list' to list available events", - parse_events), + parse_events_option), OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter), OPT_BOOLEAN('i', "no-inherit", &no_inherit, diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 2da9162262b..55f4c76f282 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -12,6 +12,7 @@ #include "util/parse-events.h" #include "util/symbol.h" #include "util/thread_map.h" +#include "../../include/linux/hw_breakpoint.h" static long page_size; @@ -245,8 +246,8 @@ static int trace_event__id(const char *evname) int err = -1, fd; if (asprintf(&filename, - "/sys/kernel/debug/tracing/events/syscalls/%s/id", - evname) < 0) + "%s/syscalls/%s/id", + debugfs_path, evname) < 0) return -1; fd = open(filename, O_RDONLY); @@ -600,6 +601,246 @@ out_free_threads: #undef nsyscalls } +#define TEST_ASSERT_VAL(text, cond) \ +do { \ + if (!cond) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + return -1; \ + } \ +} while (0) + +static int test__checkevent_tracepoint(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong sample_type", + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == + evsel->attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); + return 0; +} + +static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); + + list_for_each_entry(evsel, &evlist->entries, node) { + TEST_ASSERT_VAL("wrong type", + PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong sample_type", + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) + == evsel->attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", + 1 == evsel->attr.sample_period); + } + return 0; +} + +static int test__checkevent_raw(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong conf |