From 202ff9684a912c96e0f2fac65e34280a97ad3611 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 10:11:07 -0300 Subject: [PATCH 01/11] perf trace: Support callchains for --event too We already were able to ask for callchains for a specific event: # trace -e nanosleep --call dwarf --event sched:sched_switch/call-graph=fp/ usleep 1 This would enable tracing just the "nanosleep" syscall, with callchains at syscall exit and would ask the kernel for frame pointer callchains to be enabled for the "sched:sched_switch" tracepoint event, its just that we were not resolving the callchain and printing it in 'perf trace', do it: # trace -e nanosleep --call dwarf --event sched:sched_switch/call-graph=fp/ usleep 1 0.425 ( 0.013 ms): usleep/6718 nanosleep(rqtp: 0x7ffcc1d16e20) ... 0.425 ( ): sched:sched_switch:usleep:6718 [120] S ==> swapper/2:0 [120]) __schedule+0xfe200402 ([kernel.kallsyms]) schedule+0xfe200035 ([kernel.kallsyms]) do_nanosleep+0xfe20006f ([kernel.kallsyms]) hrtimer_nanosleep+0xfe2000dc ([kernel.kallsyms]) sys_nanosleep+0xfe20007a ([kernel.kallsyms]) do_syscall_64+0xfe200062 ([kernel.kallsyms]) return_from_SYSCALL_64+0xfe200000 ([kernel.kallsyms]) __nanosleep+0xffff008b8cbe2010 (/usr/lib64/libc-2.22.so) 0.486 ( 0.073 ms): usleep/6718 ... [continued]: nanosleep()) = 0 __nanosleep+0x10 (/usr/lib64/libc-2.22.so) usleep+0x34 (/usr/lib64/libc-2.22.so) main+0x1eb (/usr/bin/usleep) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) _start+0x29 (/usr/bin/usleep) # Pretty compact, huh? DWARF callchains for raw_syscalls:sys_exit + frame pointer callchains for a tracepoint, if your hardware supports LBR, go wild with /call-graph=lbr/, guess the next step is to lift this from 'perf script': -F, --fields 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,period,iregs,brstack,brstacksym,flags Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-2e7yiv5hqdm8jywlmfivvx2v@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 41 ++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2ec53edcf649..a6e05e1bb350 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2114,6 +2114,28 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, return err; } +static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample) +{ + struct addr_location al; + /* TODO: user-configurable print_opts */ + const unsigned int print_opts = PRINT_IP_OPT_SYM | + PRINT_IP_OPT_DSO | + PRINT_IP_OPT_UNKNOWN_AS_ADDR; + + if (sample->callchain == NULL) + return 0; + + if (machine__resolve(trace->host, &al, sample) < 0) { + pr_err("Problem processing %s callchain, skipping...\n", + perf_evsel__name(evsel)); + return 0; + } + + return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, + scripting_max_stack, trace->output); +} + static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) @@ -2193,21 +2215,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, fputc('\n', trace->output); - if (sample->callchain) { - struct addr_location al; - /* TODO: user-configurable print_opts */ - const unsigned int print_opts = PRINT_IP_OPT_SYM | - PRINT_IP_OPT_DSO | - PRINT_IP_OPT_UNKNOWN_AS_ADDR; - - if (machine__resolve(trace->host, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); - goto out_put; - } - perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts, - scripting_max_stack, trace->output); - } + trace__fprintf_callchain(trace, evsel, sample); out: ttrace->entry_pending = false; err = 0; @@ -2355,6 +2363,9 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, } fprintf(trace->output, ")\n"); + + trace__fprintf_callchain(trace, evsel, sample); + return 0; } From 3407df8bbc3a91d9aa4910130026ab6b3a261b87 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:24 +0200 Subject: [PATCH 02/11] perf thread_map: Add has() method Adding thread_map__has() to return bool of pid presence in threads map. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 12 ++++++++++++ tools/perf/util/thread_map.h | 1 + 2 files changed, 13 insertions(+) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 267112b4e3db..878ac0687b0a 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event) return threads; } + +bool thread_map__has(struct thread_map *threads, pid_t pid) +{ + int i; + + for (i = 0; i < threads->nr; ++i) { + if (threads->map[i].pid == pid) + return true; + } + + return false; +} diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 85e4c7c4fbde..9a065ea69ff1 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -55,4 +55,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread) } void thread_map__read_comms(struct thread_map *threads); +bool thread_map__has(struct thread_map *threads, pid_t pid); #endif /* __PERF_THREAD_MAP_H */ From e632aa69c919462a7f93c8799b97c8a9ddd48fc2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:25 +0200 Subject: [PATCH 03/11] perf cpu_map: Add has() method Adding cpu_map__has() to return bool of cpu presence in cpus map. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 12 ++++++++++++ tools/perf/util/cpumap.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 9bcf2bed3a6d..02d801670f30 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -587,3 +587,15 @@ int cpu__setup_cpunode_map(void) closedir(dir1); return 0; } + +bool cpu_map__has(struct cpu_map *cpus, int cpu) +{ + int i; + + for (i = 0; i < cpus->nr; ++i) { + if (cpus->map[i] == cpu) + return true; + } + + return false; +} diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 81a2562aaa2b..1a0a35073ce1 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -66,4 +66,6 @@ int cpu__get_node(int cpu); int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int (*f)(struct cpu_map *map, int cpu, void *data), void *data); + +bool cpu_map__has(struct cpu_map *cpus, int cpu); #endif /* __PERF_CPUMAP_H */ From 99623c628f5425f09b5321cf621af1da29c0c47d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:26 +0200 Subject: [PATCH 04/11] perf sched: Add compact display option Add compact map display that does not output the whole cpu matrix, only cpus that got event. $ perf sched map --compact *A0 1082427.094098 secs A0 => perf:19404 (CPU 2) A0 *. 1082427.094127 secs . => swapper:0 (CPU 1) A0 . *B0 1082427.094174 secs B0 => rcuos/2:25 (CPU 3) A0 . *. 1082427.094177 secs *C0 . . 1082427.094187 secs C0 => migration/2:21 C0 *A0 . 1082427.094193 secs *. A0 . 1082427.094195 secs *D0 A0 . 1082427.094402 secs D0 => rngd:968 *. A0 . 1082427.094406 secs . *E0 . 1082427.095221 secs E0 => kworker/1:1:5333 . E0 *F0 1082427.095227 secs F0 => xterm:3342 It helps to display sane output for small thread loads on big cpu servers. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-4-git-send-email-jolsa@kernel.org [ Add entry in 'perf sched' man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 7 +++ tools/perf/builtin-sched.c | 62 ++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 8ff4df956951..89b0c5b7fe84 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -50,6 +50,13 @@ OPTIONS --dump-raw-trace=:: Display verbose dump of the sched data. +OPTIONS for 'perf sched map' +---------------------------- + +--compact:: + Show only CPUs with activity. Helps visualizing on high core + count systems. + SEE ALSO -------- linkperf:perf-record[1] diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 871b55ae22a4..64dd94667055 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -122,6 +122,12 @@ struct trace_sched_handler { struct machine *machine); }; +struct perf_sched_map { + DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); + int *comp_cpus; + bool comp; +}; + struct perf_sched { struct perf_tool tool; const char *sort_order; @@ -173,6 +179,7 @@ struct perf_sched { struct list_head sort_list, cmp_pid; bool force; bool skip_merge; + struct perf_sched_map map; }; static u64 get_nsecs(void) @@ -1347,13 +1354,24 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int new_shortname; u64 timestamp0, timestamp = sample->time; s64 delta; - int cpu, this_cpu = sample->cpu; + int i, this_cpu = sample->cpu; + int cpus_nr; + bool new_cpu = false; BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); if (this_cpu > sched->max_cpu) sched->max_cpu = this_cpu; + if (sched->map.comp) { + cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS); + if (!test_and_set_bit(this_cpu, sched->map.comp_cpus_mask)) { + sched->map.comp_cpus[cpus_nr++] = this_cpu; + new_cpu = true; + } + } else + cpus_nr = sched->max_cpu; + timestamp0 = sched->cpu_last_switched[this_cpu]; sched->cpu_last_switched[this_cpu] = timestamp; if (timestamp0) @@ -1400,7 +1418,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, new_shortname = 1; } - for (cpu = 0; cpu <= sched->max_cpu; cpu++) { + for (i = 0; i < cpus_nr; i++) { + int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; + if (cpu != this_cpu) printf(" "); else @@ -1414,12 +1434,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, printf(" %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - printf("%s => %s:%d\n", + printf("%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); - } else { - printf("\n"); } + if (sched->map.comp && new_cpu) + printf(" (CPU %d)", this_cpu); + + printf("\n"); + thread__put(sched_in); return 0; @@ -1675,9 +1698,22 @@ static int perf_sched__lat(struct perf_sched *sched) return 0; } +static int setup_map_cpus(struct perf_sched *sched) +{ + sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); + + if (sched->map.comp) { + sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int)); + return sched->map.comp_cpus ? 0 : -1; + } + + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { - sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); + if (setup_map_cpus(sched)) + return -1; setup_pager(); if (perf_sched__read_events(sched)) @@ -1831,6 +1867,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "dump raw trace in ASCII"), OPT_END() }; + const struct option map_options[] = { + OPT_BOOLEAN(0, "compact", &sched.map.comp, + "map output in compact mode"), + OPT_END() + }; const char * const latency_usage[] = { "perf sched latency []", NULL @@ -1839,6 +1880,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "perf sched replay []", NULL }; + const char * const map_usage[] = { + "perf sched map []", + NULL + }; const char *const sched_subcommands[] = { "record", "latency", "map", "replay", "script", NULL }; const char *sched_usage[] = { @@ -1887,6 +1932,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) setup_sorting(&sched, latency_options, latency_usage); return perf_sched__lat(&sched); } else if (!strcmp(argv[0], "map")) { + if (argc) { + argc = parse_options(argc, argv, map_options, replay_usage, 0); + if (argc) + usage_with_options(map_usage, map_options); + } sched.tp_handler = &map_ops; setup_sorting(&sched, latency_options, latency_usage); return perf_sched__map(&sched); From 8cd91195e5efc5166fc48eec6cf83ef93133b7b6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:27 +0200 Subject: [PATCH 05/11] perf sched: Use color_fprintf for output As preparation for next patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 64dd94667055..9ef28973f198 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -11,6 +11,7 @@ #include "util/session.h" #include "util/tool.h" #include "util/cloexec.h" +#include "util/color.h" #include #include "util/trace-event.h" @@ -1357,6 +1358,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int i, this_cpu = sample->cpu; int cpus_nr; bool new_cpu = false; + const char *color = PERF_COLOR_NORMAL; BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); @@ -1422,26 +1424,26 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; if (cpu != this_cpu) - printf(" "); + color_fprintf(stdout, color, " "); else - printf("*"); + color_fprintf(stdout, color, "*"); if (sched->curr_thread[cpu]) - printf("%2s ", sched->curr_thread[cpu]->shortname); + color_fprintf(stdout, color, "%2s ", sched->curr_thread[cpu]->shortname); else - printf(" "); + color_fprintf(stdout, color, " "); } - printf(" %12.6f secs ", (double)timestamp/1e9); + color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - printf("%s => %s:%d", + color_fprintf(stdout, color, "%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); } if (sched->map.comp && new_cpu) - printf(" (CPU %d)", this_cpu); + color_fprintf(stdout, color, " (CPU %d)", this_cpu); - printf("\n"); + color_fprintf(stdout, color, "\n"); thread__put(sched_in); From 097be0f5034fc9edaf84253b773b14bc2af9a708 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:28 +0200 Subject: [PATCH 06/11] perf thread_map: Make new_by_tid_str constructor public It will be used in following patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 2 +- tools/perf/util/thread_map.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 878ac0687b0a..5654fe15e036 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void) return threads; } -static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) +struct thread_map *thread_map__new_by_tid_str(const char *tid_str) { struct thread_map *threads = NULL, *nt; int ntasks = 0; diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 9a065ea69ff1..bd3b971588da 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map); struct thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid); +struct thread_map *thread_map__new_by_tid_str(const char *tid_str); + size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); static inline int thread_map__nr(struct thread_map *threads) From a151a37a760aab41c115af8d5016e449228e8d2e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:29 +0200 Subject: [PATCH 07/11] perf sched map: Color given pids Adding --color-pids option to display selected pids in color (blue by default). It helps on navigating through the 'perf sched map' output. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-7-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 + tools/perf/builtin-sched.c | 77 +++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 89b0c5b7fe84..67913de3aee7 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--color-pids:: + Highlight the given pids. + SEE ALSO -------- linkperf:perf-record[1] diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ef28973f198..b5361a1d20e1 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -11,6 +11,7 @@ #include "util/session.h" #include "util/tool.h" #include "util/cloexec.h" +#include "util/thread_map.h" #include "util/color.h" #include @@ -123,10 +124,14 @@ struct trace_sched_handler { struct machine *machine); }; +#define COLOR_PIDS PERF_COLOR_BLUE + struct perf_sched_map { DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); int *comp_cpus; bool comp; + struct thread_map *color_pids; + const char *color_pids_str; }; struct perf_sched { @@ -1347,6 +1352,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool, return 0; } +union map_priv { + void *ptr; + bool color; +}; + +static bool thread__has_color(struct thread *thread) +{ + union map_priv priv = { + .ptr = thread__priv(thread), + }; + + return priv.color; +} + +static struct thread* +map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid) +{ + struct thread *thread = machine__findnew_thread(machine, pid, tid); + union map_priv priv = { + .color = false, + }; + + if (!sched->map.color_pids || !thread || thread__priv(thread)) + return thread; + + if (thread_map__has(sched->map.color_pids, tid)) + priv.color = true; + + thread__set_priv(thread, priv.ptr); + return thread; +} + static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1386,7 +1423,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, return -1; } - sched_in = machine__findnew_thread(machine, -1, next_pid); + sched_in = map__findnew_thread(sched, machine, -1, next_pid); if (sched_in == NULL) return -1; @@ -1422,6 +1459,11 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, for (i = 0; i < cpus_nr; i++) { int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; + struct thread *curr_thread = sched->curr_thread[cpu]; + const char *pid_color = color; + + if (curr_thread && thread__has_color(curr_thread)) + pid_color = COLOR_PIDS; if (cpu != this_cpu) color_fprintf(stdout, color, " "); @@ -1429,14 +1471,19 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, color_fprintf(stdout, color, "*"); if (sched->curr_thread[cpu]) - color_fprintf(stdout, color, "%2s ", sched->curr_thread[cpu]->shortname); + color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); else color_fprintf(stdout, color, " "); } color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { - color_fprintf(stdout, color, "%s => %s:%d", + const char *pid_color = color; + + if (thread__has_color(sched_in)) + pid_color = COLOR_PIDS; + + color_fprintf(stdout, pid_color, "%s => %s:%d", sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); } @@ -1712,11 +1759,31 @@ static int setup_map_cpus(struct perf_sched *sched) return 0; } +static int setup_color_pids(struct perf_sched *sched) +{ + struct thread_map *map; + + if (!sched->map.color_pids_str) + return 0; + + map = thread_map__new_by_tid_str(sched->map.color_pids_str); + if (!map) { + pr_err("failed to get thread map from %s\n", sched->map.color_pids_str); + return -1; + } + + sched->map.color_pids = map; + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { if (setup_map_cpus(sched)) return -1; + if (setup_color_pids(sched)) + return -1; + setup_pager(); if (perf_sched__read_events(sched)) return -1; @@ -1872,6 +1939,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) const struct option map_options[] = { OPT_BOOLEAN(0, "compact", &sched.map.comp, "map output in compact mode"), + OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids", + "highlight given pids in map"), OPT_END() }; const char * const latency_usage[] = { @@ -1935,7 +2004,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) return perf_sched__lat(&sched); } else if (!strcmp(argv[0], "map")) { if (argc) { - argc = parse_options(argc, argv, map_options, replay_usage, 0); + argc = parse_options(argc, argv, map_options, map_usage, 0); if (argc) usage_with_options(map_usage, map_options); } From cf294f24f8c83bca6aa8e96b5cc4f78bed887f92 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:30 +0200 Subject: [PATCH 08/11] perf sched map: Color given cpus Adding --color-cpus option to display selected cpus with background color (red by default). It helps on navigating through the perf sched map output. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-8-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 +++ tools/perf/builtin-sched.c | 36 ++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 67913de3aee7..58bff6cbc3f3 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--color-cpus:: + Highlight the given cpus. + --color-pids:: Highlight the given pids. diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b5361a1d20e1..7de04b297c14 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -125,6 +125,7 @@ struct trace_sched_handler { }; #define COLOR_PIDS PERF_COLOR_BLUE +#define COLOR_CPUS PERF_COLOR_BG_RED struct perf_sched_map { DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS); @@ -132,6 +133,8 @@ struct perf_sched_map { bool comp; struct thread_map *color_pids; const char *color_pids_str; + struct cpu_map *color_cpus; + const char *color_cpus_str; }; struct perf_sched { @@ -1461,14 +1464,18 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; struct thread *curr_thread = sched->curr_thread[cpu]; const char *pid_color = color; + const char *cpu_color = color; if (curr_thread && thread__has_color(curr_thread)) pid_color = COLOR_PIDS; + if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu)) + cpu_color = COLOR_CPUS; + if (cpu != this_cpu) - color_fprintf(stdout, color, " "); + color_fprintf(stdout, cpu_color, " "); else - color_fprintf(stdout, color, "*"); + color_fprintf(stdout, cpu_color, "*"); if (sched->curr_thread[cpu]) color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); @@ -1753,7 +1760,8 @@ static int setup_map_cpus(struct perf_sched *sched) if (sched->map.comp) { sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int)); - return sched->map.comp_cpus ? 0 : -1; + if (!sched->map.comp_cpus) + return -1; } return 0; @@ -1776,6 +1784,23 @@ static int setup_color_pids(struct perf_sched *sched) return 0; } +static int setup_color_cpus(struct perf_sched *sched) +{ + struct cpu_map *map; + + if (!sched->map.color_cpus_str) + return 0; + + map = cpu_map__new(sched->map.color_cpus_str); + if (!map) { + pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str); + return -1; + } + + sched->map.color_cpus = map; + return 0; +} + static int perf_sched__map(struct perf_sched *sched) { if (setup_map_cpus(sched)) @@ -1784,6 +1809,9 @@ static int perf_sched__map(struct perf_sched *sched) if (setup_color_pids(sched)) return -1; + if (setup_color_cpus(sched)) + return -1; + setup_pager(); if (perf_sched__read_events(sched)) return -1; @@ -1941,6 +1969,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "map output in compact mode"), OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids", "highlight given pids in map"), + OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus", + "highlight given CPUs in map"), OPT_END() }; const char * const latency_usage[] = { From 73643bb6a21c85509c7ae4c316f502c5a19cce65 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 12 Apr 2016 15:29:31 +0200 Subject: [PATCH 09/11] perf sched map: Display only given cpus Introducing --cpus option that will display only given cpus. Could be used together with color-cpus option. $ perf sched map --cpus 0,1 *A0 309999.786924 secs A0 => rcu_sched:7 *. 309999.786930 secs *B0 . 309999.786931 secs B0 => rcuos/2:25 B0 *A0 309999.786947 secs Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1460467771-26532-9-git-send-email-jolsa@kernel.org [ Added entry to man page ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-sched.txt | 3 +++ tools/perf/builtin-sched.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 58bff6cbc3f3..1cc08cc47ac5 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -57,6 +57,9 @@ OPTIONS for 'perf sched map' Show only CPUs with activity. Helps visualizing on high core count systems. +--cpus:: + Show just entries with activities for the given CPUs. + --color-cpus:: Highlight the given cpus. diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 7de04b297c14..afa057666c2a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -135,6 +135,8 @@ struct perf_sched_map { const char *color_pids_str; struct cpu_map *color_cpus; const char *color_cpus_str; + struct cpu_map *cpus; + const char *cpus_str; }; struct perf_sched { @@ -1469,6 +1471,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, if (curr_thread && thread__has_color(curr_thread)) pid_color = COLOR_PIDS; + if (sched->map.cpus && !cpu_map__has(sched->map.cpus, cpu)) + continue; + if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu)) cpu_color = COLOR_CPUS; @@ -1483,6 +1488,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, color_fprintf(stdout, color, " "); } + if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu)) + goto out; + color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { const char *pid_color = color; @@ -1497,6 +1505,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, if (sched->map.comp && new_cpu) color_fprintf(stdout, color, " (CPU %d)", this_cpu); +out: color_fprintf(stdout, color, "\n"); thread__put(sched_in); @@ -1756,6 +1765,8 @@ static int perf_sched__lat(struct perf_sched *sched) static int setup_map_cpus(struct perf_sched *sched) { + struct cpu_map *map; + sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); if (sched->map.comp) { @@ -1764,6 +1775,16 @@ static int setup_map_cpus(struct perf_sched *sched) return -1; } + if (!sched->map.cpus_str) + return 0; + + map = cpu_map__new(sched->map.cpus_str); + if (!map) { + pr_err("failed to get cpus map from %s\n", sched->map.cpus_str); + return -1; + } + + sched->map.cpus = map; return 0; } @@ -1971,6 +1992,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) "highlight given pids in map"), OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus", "highlight given CPUs in map"), + OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus", + "display given CPUs in map"), OPT_END() }; const char * const latency_usage[] = { From e20ab86e51218f9949f41fb39a6c4f63b662f135 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 15:16:15 -0300 Subject: [PATCH 10/11] perf evsel: Move some methods from session.[ch] to evsel.[ch] Those were converted to be evsel methods long ago, move the source to where it belongs. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-vja8rjmkw3gd5ungaeyb5s2j@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 14 ++-- tools/perf/builtin-trace.c | 6 +- tools/perf/util/evsel.c | 131 ++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 13 ++++ tools/perf/util/session.c | 130 ----------------------------------- tools/perf/util/session.h | 13 ---- 6 files changed, 154 insertions(+), 153 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ddd5b79e94c2..838c0bc38105 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -317,19 +317,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr) output[type].print_ip_opts = 0; if (PRINT_FIELD(IP)) - output[type].print_ip_opts |= PRINT_IP_OPT_IP; + output[type].print_ip_opts |= EVSEL__PRINT_IP; if (PRINT_FIELD(SYM)) - output[type].print_ip_opts |= PRINT_IP_OPT_SYM; + output[type].print_ip_opts |= EVSEL__PRINT_SYM; if (PRINT_FIELD(DSO)) - output[type].print_ip_opts |= PRINT_IP_OPT_DSO; + output[type].print_ip_opts |= EVSEL__PRINT_DSO; if (PRINT_FIELD(SYMOFFSET)) - output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; + output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET; if (PRINT_FIELD(SRCLINE)) - output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; + output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE; } /* @@ -574,9 +574,9 @@ static void print_sample_bts(struct perf_sample *sample, printf("\n"); } else { printf(" "); - if (print_opts & PRINT_IP_OPT_SRCLINE) { + if (print_opts & EVSEL__PRINT_SRCLINE) { print_srcline_last = true; - print_opts &= ~PRINT_IP_OPT_SRCLINE; + print_opts &= ~EVSEL__PRINT_SRCLINE; } } perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a6e05e1bb350..b842ddd3ad0c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2119,9 +2119,9 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evse { struct addr_location al; /* TODO: user-configurable print_opts */ - const unsigned int print_opts = PRINT_IP_OPT_SYM | - PRINT_IP_OPT_DSO | - PRINT_IP_OPT_UNKNOWN_AS_ADDR; + const unsigned int print_opts = EVSEL__PRINT_SYM | + EVSEL__PRINT_DSO | + EVSEL__PRINT_UNKNOWN_AS_ADDR; if (sample->callchain == NULL) return 0; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d475a4ec8b57..6e86598682be 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2343,6 +2343,137 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, return ++printed; } +int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) +{ + int printed = 0; + struct callchain_cursor_node *node; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_oneline = print_opts & EVSEL__PRINT_ONELINE; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + char s = print_oneline ? ' ' : '\t'; + + if (sample->callchain) { + struct addr_location node_al; + + if (thread__resolve_callchain(al->thread, evsel, + sample, NULL, NULL, + stack_depth) != 0) { + if (verbose) + error("Failed to resolve callchain. Skipping\n"); + return printed; + } + callchain_cursor_commit(&callchain_cursor); + + if (print_symoffset) + node_al = *al; + + while (stack_depth) { + u64 addr = 0; + + node = callchain_cursor_current(&callchain_cursor); + if (!node) + break; + + if (node->sym && node->sym->ignore) + goto next; + + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); + + if (node->map) + addr = node->map->map_ip(node->map, node->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + node_al.addr = addr; + node_al.map = node->map; + + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(node->sym, &node_al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(node->sym, &node_al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(node->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(node->map, addr, "\n ", fp); + + if (!print_oneline) + printed += fprintf(fp, "\n"); + + stack_depth--; +next: + callchain_cursor_advance(&callchain_cursor); + } + } + + return printed; +} + +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp) +{ + int printed = 0; + int print_ip = print_opts & EVSEL__PRINT_IP; + int print_sym = print_opts & EVSEL__PRINT_SYM; + int print_dso = print_opts & EVSEL__PRINT_DSO; + int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; + int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; + int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; + + if (symbol_conf.use_callchain && sample->callchain) { + printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, + print_opts, stack_depth, fp); + } else if (!(al->sym && al->sym->ignore)) { + printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); + + if (print_ip) + printed += fprintf(fp, "%16" PRIx64, sample->ip); + + if (print_sym) { + printed += fprintf(fp, " "); + if (print_symoffset) { + printed += __symbol__fprintf_symname_offs(al->sym, al, + print_unknown_as_addr, fp); + } else { + printed += __symbol__fprintf_symname(al->sym, al, + print_unknown_as_addr, fp); + } + } + + if (print_dso) { + printed += fprintf(fp, " ("); + printed += map__fprintf_dsoname(al->map, fp); + printed += fprintf(fp, ")"); + } + + if (print_srcline) + printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); + } + + return printed; +} + + bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1bd6c2e02dfa..36edd3c91d5c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -387,12 +387,25 @@ struct perf_attr_details { int perf_evsel__fprintf(struct perf_evsel *evsel, struct perf_attr_details *details, FILE *fp); +#define EVSEL__PRINT_IP (1<<0) +#define EVSEL__PRINT_SYM (1<<1) +#define EVSEL__PRINT_DSO (1<<2) +#define EVSEL__PRINT_SYMOFFSET (1<<3) +#define EVSEL__PRINT_ONELINE (1<<4) +#define EVSEL__PRINT_SRCLINE (1<<5) +#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6) + int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, int left_alignment, unsigned int print_opts, unsigned int stack_depth, FILE *fp); +int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, + struct addr_location *al, int left_alignment, + unsigned int print_opts, unsigned int stack_depth, + FILE *fp); + bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0516d06a2741..91d4528d71fa 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1953,136 +1953,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) -{ - int printed = 0; - struct callchain_cursor_node *node; - int print_ip = print_opts & PRINT_IP_OPT_IP; - int print_sym = print_opts & PRINT_IP_OPT_SYM; - int print_dso = print_opts & PRINT_IP_OPT_DSO; - int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; - int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; - int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; - int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; - char s = print_oneline ? ' ' : '\t'; - - if (sample->callchain) { - struct addr_location node_al; - - if (thread__resolve_callchain(al->thread, evsel, - sample, NULL, NULL, - stack_depth) != 0) { - if (verbose) - error("Failed to resolve callchain. Skipping\n"); - return printed; - } - callchain_cursor_commit(&callchain_cursor); - - if (print_symoffset) - node_al = *al; - - while (stack_depth) { - u64 addr = 0; - - node = callchain_cursor_current(&callchain_cursor); - if (!node) - break; - - if (node->sym && node->sym->ignore) - goto next; - - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); - - if (node->map) - addr = node->map->map_ip(node->map, node->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - node_al.addr = addr; - node_al.map = node->map; - - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(node->sym, &node_al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(node->sym, &node_al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(node->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(node->map, addr, "\n ", fp); - - if (!print_oneline) - printed += fprintf(fp, "\n"); - - stack_depth--; -next: - callchain_cursor_advance(&callchain_cursor); - } - } - - return printed; -} - -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp) -{ - int printed = 0; - int print_ip = print_opts & PRINT_IP_OPT_IP; - int print_sym = print_opts & PRINT_IP_OPT_SYM; - int print_dso = print_opts & PRINT_IP_OPT_DSO; - int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; - int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE; - int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR; - - if (symbol_conf.use_callchain && sample->callchain) { - printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment, - print_opts, stack_depth, fp); - } else if (!(al->sym && al->sym->ignore)) { - printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); - - if (print_ip) - printed += fprintf(fp, "%16" PRIx64, sample->ip); - - if (print_sym) { - printed += fprintf(fp, " "); - if (print_symoffset) { - printed += __symbol__fprintf_symname_offs(al->sym, al, - print_unknown_as_addr, fp); - } else { - printed += __symbol__fprintf_symname(al->sym, al, - print_unknown_as_addr, fp); - } - } - - if (print_dso) { - printed += fprintf(fp, " ("); - printed += map__fprintf_dsoname(al->map, fp); - printed += fprintf(fp, ")"); - } - - if (print_srcline) - printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); - } - - return printed; -} - int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap) { diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 4257fac56618..4bd758553450 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -36,14 +36,6 @@ struct perf_session { struct perf_tool *tool; }; -#define PRINT_IP_OPT_IP (1<<0) -#define PRINT_IP_OPT_SYM (1<<1) -#define PRINT_IP_OPT_DSO (1<<2) -#define PRINT_IP_OPT_SYMOFFSET (1<<3) -#define PRINT_IP_OPT_ONELINE (1<<4) -#define PRINT_IP_OPT_SRCLINE (1<<5) -#define PRINT_IP_OPT_UNKNOWN_AS_ADDR (1<<6) - struct perf_tool; struct perf_session *perf_session__new(struct perf_data_file *file, @@ -105,11 +97,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample, - struct addr_location *al, int left_alignment, - unsigned int print_opts, unsigned int stack_depth, - FILE *fp); - int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); From 59247e33ff494e3643cdff54b64bf72575052b76 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Apr 2016 16:05:02 -0300 Subject: [PATCH 11/11] perf trace: Do not accept --no-syscalls together with -e Doesn't make sense and was causing a segfault, fix it. # trace -e clone --no-syscalls --event sched:*exec firefox The -e option can't be used with --no-syscalls. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-ccrahezikdk2uebptzr1eyyi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b842ddd3ad0c..d49c131bb5de 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3344,6 +3344,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) goto out; } + err = -1; + if (trace.trace_pgfaults) { trace.opts.sample_address = true; trace.opts.sample_time = true; @@ -3368,6 +3370,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) return -1; } + if (!trace.trace_syscalls && ev_qualifier_str) { + pr_err("The -e option can't be used with --no-syscalls.\n"); + goto out; + } + if (output_name != NULL) { err = trace__open_output(&trace, output_name); if (err < 0) {