aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-02-03 10:58:57 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-02-13 14:47:12 -0500
commit14a052df1cfa563093f20847d52caad4be5d2adc (patch)
treeac47528034c496169c9691f17df0f924be13ed7b /tools
parente596663ebb28a068f5cca57f83285b7b293a2c83 (diff)
perf trace: Allow mixing with other events
Basically adopting 'perf record' --event command line argument syntax: # trace -e \!mprotect,mmap,munmap,open,close,read,fstat,access,arch_prctl --event sched:*switch,sched:*exec,sched:*exit usleep 1 0.048 ( ): sched:sched_process_exec:filename=/bin/usleep pid=24732 old_pid=24732) 0.078 (0.002 ms): usleep/24732 brk( ) = 0x78f000 0.430 (0.002 ms): usleep/24732 brk( ) = 0x78f000 0.434 (0.003 ms): usleep/24732 brk(brk: 0x7b0000 ) = 0x7b0000 0.438 (0.001 ms): usleep/24732 brk( ) = 0x7b0000 0.460 (0.004 ms): usleep/24732 nanosleep(rqtp: 0x7ffff3696a40) ... 0.460 ( ): sched:sched_switch:prev_comm=usleep prev_pid=24732 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120) 0.515 (0.058 ms): usleep/24732 ... [continued]: nanosleep()) = 0 0.520 (0.000 ms): usleep/24732 exit_group( 0.550 ( ): sched:sched_process_exit:comm=usleep pid=24732 prio=120) # Next steps, probably in this order: 1) Use ordered_events code, the logic in trace needs the events to be time ordered when needed, i.e. when multiple CPUs are involved. 2) Callchains! 3) Automatically account for interruptions when saying how long things took. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: David Ahern <dsahern@gmail.com> Cc: Don Zickus <dzickus@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-gpst8mph575yb4wgf91qibyb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-trace.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index feabd08ec90d..a44ac9336219 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1219,6 +1219,7 @@ struct trace {
1219 struct syscall *table; 1219 struct syscall *table;
1220 } syscalls; 1220 } syscalls;
1221 struct record_opts opts; 1221 struct record_opts opts;
1222 struct perf_evlist *evlist;
1222 struct machine *host; 1223 struct machine *host;
1223 struct thread *current; 1224 struct thread *current;
1224 u64 base_time; 1225 u64 base_time;
@@ -1833,6 +1834,24 @@ out_dump:
1833 return 0; 1834 return 0;
1834} 1835}
1835 1836
1837static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1838 union perf_event *event __maybe_unused,
1839 struct perf_sample *sample)
1840{
1841 trace__printf_interrupted_entry(trace, sample);
1842 trace__fprintf_tstamp(trace, sample->time, trace->output);
1843 fprintf(trace->output, "(%9.9s): %s:", " ", evsel->name);
1844
1845 if (evsel->tp_format) {
1846 event_format__fprintf(evsel->tp_format, sample->cpu,
1847 sample->raw_data, sample->raw_size,
1848 trace->output);
1849 }
1850
1851 fprintf(trace->output, ")\n");
1852 return 0;
1853}
1854
1836static void print_location(FILE *f, struct perf_sample *sample, 1855static void print_location(FILE *f, struct perf_sample *sample,
1837 struct addr_location *al, 1856 struct addr_location *al,
1838 bool print_dso, bool print_sym) 1857 bool print_dso, bool print_sym)
@@ -2067,7 +2086,7 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2067 2086
2068static int trace__run(struct trace *trace, int argc, const char **argv) 2087static int trace__run(struct trace *trace, int argc, const char **argv)
2069{ 2088{
2070 struct perf_evlist *evlist = perf_evlist__new(); 2089 struct perf_evlist *evlist = trace->evlist;
2071 struct perf_evsel *evsel; 2090 struct perf_evsel *evsel;
2072 int err = -1, i; 2091 int err = -1, i;
2073 unsigned long before; 2092 unsigned long before;
@@ -2076,11 +2095,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2076 2095
2077 trace->live = true; 2096 trace->live = true;
2078 2097
2079 if (evlist == NULL) {
2080 fprintf(trace->output, "Not enough memory to run!\n");
2081 goto out;
2082 }
2083
2084 if (trace->trace_syscalls && 2098 if (trace->trace_syscalls &&
2085 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2099 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2086 trace__sys_exit)) 2100 trace__sys_exit))
@@ -2227,7 +2241,7 @@ out_disable:
2227 2241
2228out_delete_evlist: 2242out_delete_evlist:
2229 perf_evlist__delete(evlist); 2243 perf_evlist__delete(evlist);
2230out: 2244 trace->evlist = NULL;
2231 trace->live = false; 2245 trace->live = false;
2232 return err; 2246 return err;
2233{ 2247{
@@ -2498,6 +2512,14 @@ static int parse_pagefaults(const struct option *opt, const char *str,
2498 return 0; 2512 return 0;
2499} 2513}
2500 2514
2515static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2516{
2517 struct perf_evsel *evsel;
2518
2519 evlist__for_each(evlist, evsel)
2520 evsel->handler = handler;
2521}
2522
2501int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2523int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2502{ 2524{
2503 const char * const trace_usage[] = { 2525 const char * const trace_usage[] = {
@@ -2532,6 +2554,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2532 const char *output_name = NULL; 2554 const char *output_name = NULL;
2533 const char *ev_qualifier_str = NULL; 2555 const char *ev_qualifier_str = NULL;
2534 const struct option trace_options[] = { 2556 const struct option trace_options[] = {
2557 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2558 "event selector. use 'perf list' to list available events",
2559 parse_events_option),
2535 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2560 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2536 "show the thread COMM next to its id"), 2561 "show the thread COMM next to its id"),
2537 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2562 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
@@ -2573,6 +2598,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2573 int err; 2598 int err;
2574 char bf[BUFSIZ]; 2599 char bf[BUFSIZ];
2575 2600
2601 trace.evlist = perf_evlist__new();
2602 if (trace.evlist == NULL)
2603 return -ENOMEM;
2604
2605 if (trace.evlist == NULL) {
2606 pr_err("Not enough memory to run!\n");
2607 goto out;
2608 }
2609
2576 argc = parse_options(argc, argv, trace_options, trace_usage, 2610 argc = parse_options(argc, argv, trace_options, trace_usage,
2577 PARSE_OPT_STOP_AT_NON_OPTION); 2611 PARSE_OPT_STOP_AT_NON_OPTION);
2578 2612
@@ -2581,6 +2615,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2581 trace.opts.sample_time = true; 2615 trace.opts.sample_time = true;
2582 } 2616 }
2583 2617
2618 if (trace.evlist->nr_entries > 0)
2619 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2620
2584 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 2621 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2585 return trace__record(&trace, argc-1, &argv[1]); 2622 return trace__record(&trace, argc-1, &argv[1]);
2586 2623