From 70f7b4a7f3f9a46807b644aa0fcfa7daa0d553e4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 21:56:38 -0400 Subject: perf kvm: Option to print events that exceed a duration This is useful to spot high latency blips. It is normal for HLT reasons to have long exit times, so strip those from the duration check. v2: changed threshold to duration per acme's request Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Runzhen Wang Cc: Xiao Guangrong Link: http://lkml.kernel.org/r/1375926999-75129-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 25 +++++++++++++++++++++---- tools/perf/perf.h | 3 +++ 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 2ceec817a2fb..fa2f3d79886a 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -106,6 +106,7 @@ struct perf_kvm_stat { u64 total_time; u64 total_count; u64 lost_events; + u64 duration; const char *pid_str; struct intlist *pid_list; @@ -473,7 +474,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id, static bool handle_end_event(struct perf_kvm_stat *kvm, struct vcpu_event_record *vcpu_record, struct event_key *key, - u64 timestamp) + struct perf_sample *sample) { struct kvm_event *event; u64 time_begin, time_diff; @@ -510,12 +511,24 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, vcpu_record->start_time = 0; /* seems to happen once in a while during live mode */ - if (timestamp < time_begin) { + if (sample->time < time_begin) { pr_debug("End time before begin time; skipping event.\n"); return true; } - time_diff = timestamp - time_begin; + time_diff = sample->time - time_begin; + + if (kvm->duration && time_diff > kvm->duration) { + char decode[32]; + + kvm->events_ops->decode_key(kvm, &event->key, decode); + if (strcmp(decode, "HLT")) { + pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", + sample->time, sample->pid, vcpu_record->vcpu_id, + decode, time_diff/1000); + } + } + return update_kvm_event(event, vcpu, time_diff); } @@ -562,7 +575,7 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm, return handle_begin_event(kvm, 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 handle_end_event(kvm, vcpu_record, &key, sample); return true; } @@ -1429,6 +1442,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, OPT_STRING('k', "key", &kvm->sort_key, "sort-key", "key for sorting: sample(sort by samples number)" " time (sort by avg time)"), + OPT_U64(0, "duration", &kvm->duration, + "show events other than HALT that take longer than duration usecs"), OPT_END() }; const char * const live_usage[] = { @@ -1467,6 +1482,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, usage_with_options(live_usage, live_options); } + kvm->duration *= NSEC_PER_USEC; /* convert usec to nsec */ + /* * target related setups */ diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 32bd102c32b6..cf20187eee0a 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -125,6 +125,9 @@ #ifndef NSEC_PER_SEC # define NSEC_PER_SEC 1000000000ULL #endif +#ifndef NSEC_PER_USEC +# define NSEC_PER_USEC 1000ULL +#endif static inline unsigned long long rdclock(void) { -- cgit v1.2.3-58-ga151 From 9a6d316692d59c4400a66b01db675abac432b4b2 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 21:56:39 -0400 Subject: perf kvm: Update documentation with live command Update perf-kvm documentation with new live subcommand. Add -p/--pid option for perf-kvm-stat-report as well. Signed-off-by: David Ahern Requested-by: Xiao Guangrong Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Runzhen Wang Cc: Xiao Guangrong Link: http://lkml.kernel.org/r/1375926999-75129-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-kvm.txt | 46 +++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt index 326f2cb333cb..ac84db2d2334 100644 --- a/tools/perf/Documentation/perf-kvm.txt +++ b/tools/perf/Documentation/perf-kvm.txt @@ -13,6 +13,7 @@ SYNOPSIS {top|record|report|diff|buildid-list} 'perf kvm' [--host] [--guest] [--guestkallsyms= --guestmodules= | --guestvmlinux=] {top|record|report|diff|buildid-list|stat} +'perf kvm stat [record|report|live] [] DESCRIPTION ----------- @@ -50,6 +51,10 @@ There are a couple of variants of perf kvm: 'perf kvm stat report' reports statistical data which includes events handled time, samples, and so on. + 'perf kvm stat live' reports statistical data in a live mode (similar to + record + report but with statistical data updated live at a given display + rate). + OPTIONS ------- -i:: @@ -85,13 +90,50 @@ STAT REPORT OPTIONS --vcpu=:: analyze events which occures on this vcpu. (default: all vcpus) ---events=:: - events to be analyzed. Possible values: vmexit, mmio, ioport. +--event=:: + event to be analyzed. Possible values: vmexit, mmio, ioport. (default: vmexit) -k:: --key=:: Sorting key. Possible values: sample (default, sort by samples number), time (sort by average time). +-p:: +--pid=:: + Analyze events only for given process ID(s) (comma separated list). + +STAT LIVE OPTIONS +----------------- +-d:: +--display:: + Time in seconds between display updates + +-m:: +--mmap-pages=:: + Number of mmap data pages. Must be a power of two. + +-a:: +--all-cpus:: + System-wide collection from all CPUs. + +-p:: +--pid=:: + Analyze events only for given process ID(s) (comma separated list). + +--vcpu=:: + analyze events which occures on this vcpu. (default: all vcpus) + + +--event=:: + event to be analyzed. Possible values: vmexit, mmio, ioport. + (default: vmexit) + +-k:: +--key=:: + Sorting key. Possible values: sample (default, sort by samples + number), time (sort by average time). + +--duration=:: + Show events other than HLT that take longer than duration usecs. SEE ALSO -------- -- cgit v1.2.3-58-ga151 From ad9def7ca020ef5b54968c89194f52d18ef1ef49 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:44 -0400 Subject: perf sched: Simplify arguments to read_events Destroy argument is not necessary. If session is not returned to caller, then clean it up. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-3-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 948183adb6e5..34ce57d24721 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1445,7 +1445,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_ return err; } -static int perf_sched__read_events(struct perf_sched *sched, bool destroy, +static int perf_sched__read_events(struct perf_sched *sched, struct perf_session **psession) { const struct perf_evsel_str_handler handlers[] = { @@ -1480,11 +1480,10 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy, sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; } - if (destroy) - perf_session__delete(session); - if (psession) *psession = session; + else + perf_session__delete(session); return 0; @@ -1529,8 +1528,11 @@ static int perf_sched__lat(struct perf_sched *sched) struct perf_session *session; setup_pager(); - if (perf_sched__read_events(sched, false, &session)) + + /* save session -- references to threads are held in work_list */ + if (perf_sched__read_events(sched, &session)) return -1; + perf_sched__sort_lat(sched); printf("\n ---------------------------------------------------------------------------------------------------------------\n"); @@ -1565,7 +1567,7 @@ static int perf_sched__map(struct perf_sched *sched) sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); setup_pager(); - if (perf_sched__read_events(sched, true, NULL)) + if (perf_sched__read_events(sched, NULL)) return -1; print_bad_events(sched); return 0; @@ -1580,7 +1582,7 @@ static int perf_sched__replay(struct perf_sched *sched) test_calibrations(sched); - if (perf_sched__read_events(sched, true, NULL)) + if (perf_sched__read_events(sched, NULL)) return -1; printf("nr_run_events: %ld\n", sched->nr_run_events); -- cgit v1.2.3-58-ga151 From ffb273dd7e3bd72e7d964fc0a0f6d441aceb7dae Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:45 -0400 Subject: perf sched: Remove thread lookup in sample handler Not used in the function, so no sense in doing the lookup here. Thread look up will be done in the timehist command, and no sense in doing it twice. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-4-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 34ce57d24721..52850240583a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1425,15 +1425,8 @@ 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->tid); int err = 0; - if (thread == NULL) { - pr_debug("problem processing %s event, skipping it.\n", - perf_evsel__name(evsel)); - return -1; - } - evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); -- cgit v1.2.3-58-ga151 From 4a957e4df1a212c447fd162d18dc7ee6320c1621 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:46 -0400 Subject: perf sched: Remove sched_process_exit tracepoint Event is not needed nor analyzed. Since perf-sched leverages perf-record to capture the sched data, we already capture task events like EXIT. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-5-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 52850240583a..42f45873d8f0 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1392,15 +1392,6 @@ static int process_sched_fork_event(struct perf_tool *tool, return 0; } -static int process_sched_exit_event(struct perf_tool *tool __maybe_unused, - struct perf_evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct machine *machine __maybe_unused) -{ - pr_debug("sched_exit event %p\n", evsel); - return 0; -} - static int process_sched_migrate_task_event(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, @@ -1447,7 +1438,6 @@ static int perf_sched__read_events(struct perf_sched *sched, { "sched:sched_wakeup", process_sched_wakeup_event, }, { "sched:sched_wakeup_new", process_sched_wakeup_event, }, { "sched:sched_process_fork", process_sched_fork_event, }, - { "sched:sched_process_exit", process_sched_exit_event, }, { "sched:sched_migrate_task", process_sched_migrate_task_event, }, }; struct perf_session *session; @@ -1634,7 +1624,6 @@ static int __cmd_record(int argc, const char **argv) "-e", "sched:sched_stat_sleep", "-e", "sched:sched_stat_iowait", "-e", "sched:sched_stat_runtime", - "-e", "sched:sched_process_exit", "-e", "sched:sched_process_fork", "-e", "sched:sched_wakeup", "-e", "sched:sched_migrate_task", -- cgit v1.2.3-58-ga151 From cb627505ae028a0cd88cc29ed72a4c168a08751d Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:47 -0400 Subject: perf sched: Remove sched_process_fork tracepoint The PERF_RECORD_FORK event is already collected as part of the use of cmd_record and those events are analyzed as part of the libperf machinery. Using the fork tracepoint as well just duplicates the event load. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-6-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 60 ++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 42f45873d8f0..f809cc7fb7d9 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -109,8 +109,9 @@ struct trace_sched_handler { int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine); - int (*fork_event)(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample); + /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */ + int (*fork_event)(struct perf_sched *sched, union perf_event *event, + struct machine *machine); int (*migrate_task_event)(struct perf_sched *sched, struct perf_evsel *evsel, @@ -717,22 +718,29 @@ static int replay_switch_event(struct perf_sched *sched, return 0; } -static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, - struct perf_sample *sample) +static int replay_fork_event(struct perf_sched *sched, + union perf_event *event, + struct machine *machine) { - const char *parent_comm = perf_evsel__strval(evsel, sample, "parent_comm"), - *child_comm = perf_evsel__strval(evsel, sample, "child_comm"); - const u32 parent_pid = perf_evsel__intval(evsel, sample, "parent_pid"), - child_pid = perf_evsel__intval(evsel, sample, "child_pid"); + struct thread *child, *parent; + + child = machine__findnew_thread(machine, event->fork.tid); + parent = machine__findnew_thread(machine, event->fork.ptid); + + if (child == NULL || parent == NULL) { + pr_debug("thread does not exist on fork event: child %p, parent %p\n", + child, parent); + return 0; + } if (verbose) { - printf("sched_fork event %p\n", evsel); - printf("... parent: %s/%d\n", parent_comm, parent_pid); - printf("... child: %s/%d\n", child_comm, child_pid); + printf("fork event\n"); + printf("... parent: %s/%d\n", parent->comm, parent->tid); + printf("... child: %s/%d\n", child->comm, child->tid); } - register_pid(sched, parent_pid, parent_comm); - register_pid(sched, child_pid, child_comm); + register_pid(sched, parent->tid, parent->comm); + register_pid(sched, child->tid, child->comm); return 0; } @@ -824,14 +832,6 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread) return 0; } -static int latency_fork_event(struct perf_sched *sched __maybe_unused, - struct perf_evsel *evsel __maybe_unused, - struct perf_sample *sample __maybe_unused) -{ - /* should insert the newcomer */ - return 0; -} - static char sched_out_state(u64 prev_state) { const char *str = TASK_STATE_TO_CHAR_STR; @@ -1379,15 +1379,19 @@ static int process_sched_runtime_event(struct perf_tool *tool, return 0; } -static int process_sched_fork_event(struct perf_tool *tool, - struct perf_evsel *evsel, - struct perf_sample *sample, - struct machine *machine __maybe_unused) +static int perf_sched__process_fork_event(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + /* run the fork event through the perf machineruy */ + perf_event__process_fork(tool, event, sample, machine); + + /* and then run additional processing needed for this command */ if (sched->tp_handler->fork_event) - return sched->tp_handler->fork_event(sched, evsel, sample); + return sched->tp_handler->fork_event(sched, event, machine); return 0; } @@ -1437,7 +1441,6 @@ static int perf_sched__read_events(struct perf_sched *sched, { "sched:sched_stat_runtime", process_sched_runtime_event, }, { "sched:sched_wakeup", process_sched_wakeup_event, }, { "sched:sched_wakeup_new", process_sched_wakeup_event, }, - { "sched:sched_process_fork", process_sched_fork_event, }, { "sched:sched_migrate_task", process_sched_migrate_task_event, }, }; struct perf_session *session; @@ -1652,7 +1655,7 @@ static struct perf_sched sched = { .sample = perf_sched__process_tracepoint_sample, .comm = perf_event__process_comm, .lost = perf_event__process_lost, - .fork = perf_event__process_fork, + .fork = perf_sched__process_fork_event, .ordered_samples = true, }, .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), @@ -1714,7 +1717,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) .wakeup_event = latency_wakeup_event, .switch_event = latency_switch_event, .runtime_event = latency_runtime_event, - .fork_event = latency_fork_event, .migrate_task_event = latency_migrate_task_event, }; struct trace_sched_handler map_ops = { -- cgit v1.2.3-58-ga151 From a6ffaf91302dc1689fc72da0068b87226747fbe0 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:51 -0400 Subject: perf tool: Simplify options to perf_evsel__print_ip Make print options based on flags. Simplifies addition of more print options which is the subject of upcoming patches. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-10-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 27 +++++++++++++++++++++++---- tools/perf/util/session.c | 14 +++++++++++--- tools/perf/util/session.h | 7 ++++++- 3 files changed, 40 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index cd616ff5d221..ee5d6f8b7415 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -66,6 +66,7 @@ struct output_option { static struct { bool user_set; bool wildcard_set; + unsigned int print_ip_opts; u64 fields; u64 invalid_fields; } output[PERF_TYPE_MAX] = { @@ -235,6 +236,7 @@ static int perf_session__check_output_opt(struct perf_session *session) { int j; struct perf_evsel *evsel; + struct perf_event_attr *attr; for (j = 0; j < PERF_TYPE_MAX; ++j) { evsel = perf_session__find_first_evtype(session, j); @@ -253,6 +255,24 @@ static int perf_session__check_output_opt(struct perf_session *session) if (evsel && output[j].fields && perf_evsel__check_attr(evsel, session)) return -1; + + if (evsel == NULL) + continue; + + attr = &evsel->attr; + + output[j].print_ip_opts = 0; + if (PRINT_FIELD(IP)) + output[j].print_ip_opts |= PRINT_IP_OPT_IP; + + if (PRINT_FIELD(SYM)) + output[j].print_ip_opts |= PRINT_IP_OPT_SYM; + + if (PRINT_FIELD(DSO)) + output[j].print_ip_opts |= PRINT_IP_OPT_DSO; + + if (PRINT_FIELD(SYMOFFSET)) + output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; } return 0; @@ -382,8 +402,7 @@ static void print_sample_bts(union perf_event *event, else printf("\n"); perf_evsel__print_ip(evsel, event, sample, machine, - PRINT_FIELD(SYM), PRINT_FIELD(DSO), - PRINT_FIELD(SYMOFFSET)); + output[attr->type].print_ip_opts); } printf(" => "); @@ -423,9 +442,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample, printf(" "); else printf("\n"); + perf_evsel__print_ip(evsel, event, sample, machine, - PRINT_FIELD(SYM), PRINT_FIELD(DSO), - PRINT_FIELD(SYMOFFSET)); + output[attr->type].print_ip_opts); } printf("\n"); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dedaeb22b7b9..e5fd65802eda 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1489,10 +1489,14 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample, struct machine *machine, - int print_sym, int print_dso, int print_symoffset) + unsigned int print_opts) { struct addr_location al; 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; if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { @@ -1516,7 +1520,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, if (!node) break; - printf("\t%16" PRIx64, node->ip); + if (print_ip) + printf("%16" PRIx64, node->ip); + if (print_sym) { printf(" "); if (print_symoffset) { @@ -1537,7 +1543,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, } } else { - printf("%16" PRIx64, sample->ip); + if (print_ip) + printf("%16" PRIx64, sample->ip); + if (print_sym) { printf(" "); if (print_symoffset) diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 8bed17e64a96..69e554a29c13 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -41,6 +41,11 @@ struct perf_session { char filename[1]; }; +#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) + struct perf_tool; struct perf_session *perf_session__new(const char *filename, int mode, @@ -103,7 +108,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample, struct machine *machine, - int print_sym, int print_dso, int print_symoffset); + unsigned int print_opts); int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); -- cgit v1.2.3-58-ga151 From b0b35f0179161a5e256eebffa274b0b6f023f451 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:52 -0400 Subject: perf evsel: Add option to print stack trace on single line Option is used by upcoming timehist command. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-11-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 8 ++++++-- tools/perf/util/session.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e5fd65802eda..0d895e7040e4 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1497,6 +1497,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 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; + char s = print_oneline ? ' ' : '\t'; if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { @@ -1521,7 +1523,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, break; if (print_ip) - printf("%16" PRIx64, node->ip); + printf("%c%16" PRIx64, s, node->ip); if (print_sym) { printf(" "); @@ -1537,7 +1539,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, map__fprintf_dsoname(node->map, stdout); printf(")"); } - printf("\n"); + + if (!print_oneline) + printf("\n"); callchain_cursor_advance(&callchain_cursor); } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 69e554a29c13..7c00ccb1173e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -45,6 +45,7 @@ struct perf_session { #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) struct perf_tool; -- cgit v1.2.3-58-ga151 From 307cbb92aa2bdc9eed7c74409ff4d5fc9135b4e2 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:53 -0400 Subject: perf evsel: Add option to limit stack depth in callchain dumps Option is used by upcoming timehist command. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-12-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 6 ++++-- tools/perf/util/session.c | 6 ++++-- tools/perf/util/session.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ee5d6f8b7415..33b2d830eabd 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -402,7 +402,8 @@ static void print_sample_bts(union perf_event *event, else printf("\n"); perf_evsel__print_ip(evsel, event, sample, machine, - output[attr->type].print_ip_opts); + output[attr->type].print_ip_opts, + PERF_MAX_STACK_DEPTH); } printf(" => "); @@ -444,7 +445,8 @@ static void process_event(union perf_event *event, struct perf_sample *sample, printf("\n"); perf_evsel__print_ip(evsel, event, sample, machine, - output[attr->type].print_ip_opts); + output[attr->type].print_ip_opts, + PERF_MAX_STACK_DEPTH); } printf("\n"); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0d895e7040e4..5a8996493d94 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1489,7 +1489,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample, struct machine *machine, - unsigned int print_opts) + unsigned int print_opts, unsigned int stack_depth) { struct addr_location al; struct callchain_cursor_node *node; @@ -1517,7 +1517,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, } callchain_cursor_commit(&callchain_cursor); - while (1) { + while (stack_depth) { node = callchain_cursor_current(&callchain_cursor); if (!node) break; @@ -1544,6 +1544,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, printf("\n"); callchain_cursor_advance(&callchain_cursor); + + stack_depth--; } } else { diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7c00ccb1173e..3aa75fb2225f 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -109,7 +109,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample, struct machine *machine, - unsigned int print_opts); + unsigned int print_opts, unsigned int stack_depth); int perf_session__cpu_bitmap(struct perf_session *session, const char *cpu_list, unsigned long *cpu_bitmap); -- cgit v1.2.3-58-ga151 From 93ea01c29d4ed5a9fcf6d9a95bc584e54a420834 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 7 Aug 2013 22:50:58 -0400 Subject: perf session: Change perf_session__has_traces to actually check for tracepoints Any event can have RAW data attribute set. The intent of the function is to determine if the session has tracepoints, so check for the type of each event explicitly. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375930261-77273-17-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 5a8996493d94..4d9028eef34a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1401,12 +1401,15 @@ int perf_session__process_events(struct perf_session *self, bool perf_session__has_traces(struct perf_session *session, const char *msg) { - if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) { - pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); - return false; + struct perf_evsel *evsel; + + list_for_each_entry(evsel, &session->evlist->entries, node) { + if (evsel->attr.type == PERF_TYPE_TRACEPOINT) + return true; } - return true; + pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); + return false; } int maps__set_kallsyms_ref_reloc_sym(struct map **maps, -- cgit v1.2.3-58-ga151 From 611a5ce8aa4cdb2daefbd9bed77ec3b3e9bd00ea Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:20 +0300 Subject: perf machine: Add symbol filter to struct machine The symbol filter needs to be applied machine-wide, so add it to struct machine. Currently tools pass the symbol filter as a parameter to various map-related functions. However a need to load a map can occur anywhere in the code, at which point the filter is needed. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 20 ++++++++++++++++++++ tools/perf/util/machine.h | 5 +++++ 2 files changed, 25 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 6fcc358138ae..4c7e0a28bf3d 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -25,6 +25,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) machine->kmaps.machine = machine; machine->pid = pid; + machine->symbol_filter = NULL; + machine->root_dir = strdup(root_dir); if (machine->root_dir == NULL) return -ENOMEM; @@ -95,6 +97,7 @@ void machines__init(struct machines *machines) { machine__init(&machines->host, "", HOST_KERNEL_ID); machines->guests = RB_ROOT; + machines->symbol_filter = NULL; } void machines__exit(struct machines *machines) @@ -118,6 +121,8 @@ struct machine *machines__add(struct machines *machines, pid_t pid, return NULL; } + machine->symbol_filter = machines->symbol_filter; + while (*p != NULL) { parent = *p; pos = rb_entry(parent, struct machine, rb_node); @@ -133,6 +138,21 @@ struct machine *machines__add(struct machines *machines, pid_t pid, return machine; } +void machines__set_symbol_filter(struct machines *machines, + symbol_filter_t symbol_filter) +{ + struct rb_node *nd; + + machines->symbol_filter = symbol_filter; + machines->host.symbol_filter = symbol_filter; + + for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { + struct machine *machine = rb_entry(nd, struct machine, rb_node); + + machine->symbol_filter = symbol_filter; + } +} + struct machine *machines__find(struct machines *machines, pid_t pid) { struct rb_node **p = &machines->guests.rb_node; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 5bb6244194d5..603ffba999d9 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -29,6 +29,7 @@ struct machine { struct list_head kernel_dsos; struct map_groups kmaps; struct map *vmlinux_maps[MAP__NR_TYPES]; + symbol_filter_t symbol_filter; }; static inline @@ -51,6 +52,7 @@ typedef void (*machine__process_t)(struct machine *machine, void *data); struct machines { struct machine host; struct rb_root guests; + symbol_filter_t symbol_filter; }; void machines__init(struct machines *machines); @@ -68,6 +70,9 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid); void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); char *machine__mmap_name(struct machine *machine, char *bf, size_t size); +void machines__set_symbol_filter(struct machines *machines, + symbol_filter_t symbol_filter); + int machine__init(struct machine *machine, const char *root_dir, pid_t pid); void machine__exit(struct machine *machine); void machine__delete_dead_threads(struct machine *machine); -- cgit v1.2.3-58-ga151 From 36035f78ae1714a0762a2b38b64942d6dcb6471d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:21 +0300 Subject: perf top: Set the machines symbol filter Take into use the machines symbol filter member. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 440c3b371401..a63ade22cbc2 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -717,7 +717,7 @@ static void perf_event__process_sample(struct perf_tool *tool, top->exact_samples++; if (perf_event__preprocess_sample(event, machine, &al, sample, - symbol_filter) < 0 || + machine->symbol_filter) < 0 || al.filtered) return; @@ -938,6 +938,8 @@ static int __cmd_top(struct perf_top *top) if (top->session == NULL) return -ENOMEM; + machines__set_symbol_filter(&top->session->machines, symbol_filter); + if (!objdump_path) { ret = perf_session_env__lookup_objdump(&top->session->header.env); if (ret) -- cgit v1.2.3-58-ga151 From b8681711271a0124d9495dae2e1ac0616b0ed47a Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:22 +0300 Subject: perf report: Set the machines symbol filter Take into use the machines' symbol filter member. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index d785d89ed226..f06a5a228c7c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -49,7 +49,6 @@ struct perf_report { bool mem_mode; struct perf_read_values show_threads_values; const char *pretty_printing_style; - symbol_filter_t annotate_init; const char *cpu_list; const char *symbol_filter_str; float min_percent; @@ -306,7 +305,7 @@ static int process_sample_event(struct perf_tool *tool, int ret; if (perf_event__preprocess_sample(event, machine, &al, sample, - rep->annotate_init) < 0) { + machine->symbol_filter) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; @@ -924,7 +923,8 @@ repeat: */ if (use_browser == 1 && sort__has_sym) { symbol_conf.priv_size = sizeof(struct annotation); - report.annotate_init = symbol__annotate_init; + machines__set_symbol_filter(&session->machines, + symbol__annotate_init); /* * For searching by name on the "Browse map details". * providing it only in verbose mode not to bloat too -- cgit v1.2.3-58-ga151 From 2d8cc6851c7b92857e1171ba5fe587d38d886161 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:23 +0300 Subject: perf mem: Remove unused symbol filter member Member 'annotate_init' of struct perf_mem is unused. Remove it. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-5-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-mem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index a8ff6d264e50..f96168c769c2 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -14,7 +14,6 @@ static const char *mem_operation = MEM_OPERATION_LOAD; struct perf_mem { struct perf_tool tool; char const *input_name; - symbol_filter_t annotate_init; bool hide_unresolved; bool dump_raw; const char *cpu_list; @@ -70,7 +69,7 @@ dump_raw_samples(struct perf_tool *tool, const char *fmt; if (perf_event__preprocess_sample(event, machine, &al, sample, - mem->annotate_init) < 0) { + NULL) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; -- cgit v1.2.3-58-ga151 From 476d35c2f3a48f81691daad06bc9668c516428d9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:24 +0300 Subject: perf annotate: Set the machines symbol filter Take into use the machines symbol filter member. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-6-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index db491e9a812b..9754cb140a59 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -91,7 +91,7 @@ static int process_sample_event(struct perf_tool *tool, struct addr_location al; if (perf_event__preprocess_sample(event, machine, &al, sample, - symbol__annotate_init) < 0) { + machine->symbol_filter) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; @@ -195,6 +195,8 @@ static int __cmd_annotate(struct perf_annotate *ann) if (session == NULL) return -ENOMEM; + machines__set_symbol_filter(&session->machines, symbol__annotate_init); + if (ann->cpu_list) { ret = perf_session__cpu_bitmap(session, ann->cpu_list, ann->cpu_bitmap); -- cgit v1.2.3-58-ga151 From e44baa3ea1eaa09d7d247a9b245fcff06561bf96 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:25 +0300 Subject: perf tools: Remove filter parameter of perf_event__preprocess_sample() Now that the symbol filter is recorded on the machine there is no need to pass it to perf_event__preprocess_sample(). So remove it. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 3 +-- tools/perf/builtin-diff.c | 2 +- tools/perf/builtin-mem.c | 3 +-- tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-top.c | 3 +-- tools/perf/tests/hists_link.c | 4 ++-- tools/perf/util/event.c | 8 ++++---- tools/perf/util/event.h | 3 +-- tools/perf/util/session.c | 3 +-- 10 files changed, 14 insertions(+), 20 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 9754cb140a59..f988d380c52f 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -90,8 +90,7 @@ static int process_sample_event(struct perf_tool *tool, struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); struct addr_location al; - if (perf_event__preprocess_sample(event, machine, &al, sample, - machine->symbol_filter) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 93de3ac177c5..f28799e94f2a 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -319,7 +319,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, { struct addr_location al; - if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index f96168c769c2..706a1faa9559 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -68,8 +68,7 @@ dump_raw_samples(struct perf_tool *tool, struct addr_location al; const char *fmt; - if (perf_event__preprocess_sample(event, machine, &al, sample, - NULL) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f06a5a228c7c..958a56a0e39e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -304,8 +304,7 @@ static int process_sample_event(struct perf_tool *tool, struct addr_location al; int ret; - if (perf_event__preprocess_sample(event, machine, &al, sample, - machine->symbol_filter) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 33b2d830eabd..a7d623f39c46 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -520,7 +520,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, return 0; } - if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { pr_err("problem processing %d event, skipping it.\n", event->header.type); return -1; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a63ade22cbc2..e37521fc715a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -716,8 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool, if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) top->exact_samples++; - if (perf_event__preprocess_sample(event, machine, &al, sample, - machine->symbol_filter) < 0 || + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0 || al.filtered) return; diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 89085a9615e2..50bfb01183ea 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -220,7 +220,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) }; if (perf_event__preprocess_sample(&event, machine, &al, - &sample, 0) < 0) + &sample) < 0) goto out; he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); @@ -244,7 +244,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) }; if (perf_event__preprocess_sample(&event, machine, &al, - &sample, 0) < 0) + &sample) < 0) goto out; he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index cc7c0c9c9ea6..f3cf771d362e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -683,8 +683,7 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine, int perf_event__preprocess_sample(const union perf_event *event, struct machine *machine, struct addr_location *al, - struct perf_sample *sample, - symbol_filter_t filter) + struct perf_sample *sample) { u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; struct thread *thread = machine__findnew_thread(machine, event->ip.pid); @@ -709,7 +708,7 @@ int perf_event__preprocess_sample(const union perf_event *event, machine__create_kernel_maps(machine); thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - event->ip.ip, al, filter); + event->ip.ip, al, machine->symbol_filter); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); @@ -727,7 +726,8 @@ int perf_event__preprocess_sample(const union perf_event *event, dso->long_name))))) goto out_filtered; - al->sym = map__find_symbol(al->map, al->addr, filter); + al->sym = map__find_symbol(al->map, al->addr, + machine->symbol_filter); } if (symbol_conf.sym_list && diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 6119a649d861..15db071d96b5 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -234,8 +234,7 @@ struct addr_location; int perf_event__preprocess_sample(const union perf_event *self, struct machine *machine, struct addr_location *al, - struct perf_sample *sample, - symbol_filter_t filter); + struct perf_sample *sample); const char *perf_event__name(unsigned int id); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4d9028eef34a..de16a7736859 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1503,8 +1503,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; char s = print_oneline ? ' ' : '\t'; - if (perf_event__preprocess_sample(event, machine, &al, sample, - NULL) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { error("problem processing %d event, skipping it.\n", event->header.type); return; -- cgit v1.2.3-58-ga151 From 61710bdee324aab1c148c8573ee49cea59d05874 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:26 +0300 Subject: perf tools: Remove filter parameter of thread__find_addr_location() Now that the symbol filter is recorded on the machine there is no need to pass it to thread__find_addr_location(). So remove it. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 9 +++++---- tools/perf/util/machine.c | 8 ++++---- tools/perf/util/thread.h | 3 +-- tools/perf/util/unwind.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index f3cf771d362e..9d301c923108 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -670,12 +670,13 @@ try_again: void thread__find_addr_location(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, - struct addr_location *al, - symbol_filter_t filter) + struct addr_location *al) { - thread__find_addr_map(thread, machine, cpumode, type, addr, al, filter); + thread__find_addr_map(thread, machine, cpumode, type, addr, al, + machine->symbol_filter); if (al->map != NULL) - al->sym = map__find_symbol(al->map, al->addr, filter); + al->sym = map__find_symbol(al->map, al->addr, + machine->symbol_filter); else al->sym = NULL; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 4c7e0a28bf3d..4514e7e9b659 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1130,7 +1130,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread, * or else, the symbol is unknown */ thread__find_addr_location(thread, machine, m, MAP__FUNCTION, - ip, &al, NULL); + ip, &al); if (al.sym) goto found; } @@ -1148,8 +1148,8 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread, memset(&al, 0, sizeof(al)); - thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, &al, - NULL); + thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, + &al); ams->addr = addr; ams->al_addr = al.addr; ams->sym = al.sym; @@ -1244,7 +1244,7 @@ static int machine__resolve_callchain_sample(struct machine *machine, al.filtered = false; thread__find_addr_location(thread, machine, cpumode, - MAP__FUNCTION, ip, &al, NULL); + MAP__FUNCTION, ip, &al); if (al.sym != NULL) { if (sort__has_parent && !*parent && symbol__match_regex(al.sym, &parent_regex)) diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index f98d1d983547..0ab47d860d41 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -45,8 +45,7 @@ void thread__find_addr_map(struct thread *thread, struct machine *machine, void thread__find_addr_location(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, - struct addr_location *al, - symbol_filter_t filter); + struct addr_location *al); static inline void *thread__priv(struct thread *thread) { diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 5bbd4947c27d..abac3f97d95d 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c @@ -473,7 +473,7 @@ static int entry(u64 ip, struct thread *thread, struct machine *machine, thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER, - MAP__FUNCTION, ip, &al, NULL); + MAP__FUNCTION, ip, &al); e.ip = ip; e.map = al.map; -- cgit v1.2.3-58-ga151 From 326f59bf645ea6c99709c67d9712df46019fa7a8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 8 Aug 2013 14:32:27 +0300 Subject: perf tools: Remove filter parameter of thread__find_addr_map() Now that the symbol filter is recorded on the machine there is no need to pass it to thread__find_addr_map(). So remove it. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1375961547-30267-9-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 2 +- tools/perf/builtin-script.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/build-id.c | 2 +- tools/perf/util/event.c | 9 ++++----- tools/perf/util/thread.h | 2 +- tools/perf/util/unwind.c | 4 ++-- 7 files changed, 12 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f012a98c726c..1d8de2e4a407 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -206,7 +206,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, } thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - event->ip.ip, &al, NULL); + event->ip.ip, &al); if (al.map != NULL) { if (!al.map->dso->hit) { diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a7d623f39c46..2ad9d5b6fb3c 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -361,10 +361,10 @@ static void print_sample_addr(union perf_event *event, return; thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - sample->addr, &al, NULL); + sample->addr, &al); if (!al.map) thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, - sample->addr, &al, NULL); + sample->addr, &al); al.cpu = sample->cpu; al.sym = NULL; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 8e0943b966d7..eec1421a7e6b 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -147,7 +147,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, - &al, NULL); + &al); if (!al.map || !al.map->dso) { pr_debug("thread__find_addr_map failed\n"); return -1; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 3a0f5089379c..5295625c0c00 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -33,7 +33,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, } thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - event->ip.ip, &al, NULL); + event->ip.ip, &al); if (al.map != NULL) al.map->dso->hit = 1; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 9d301c923108..49713ae46551 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -592,7 +592,7 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, void thread__find_addr_map(struct thread *self, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, - struct addr_location *al, symbol_filter_t filter) + struct addr_location *al) { struct map_groups *mg = &self->mg; bool load_map = false; @@ -663,7 +663,7 @@ try_again: * must be done prior to using kernel maps. */ if (load_map) - map__load(al->map, filter); + map__load(al->map, machine->symbol_filter); al->addr = al->map->map_ip(al->map, al->addr); } } @@ -672,8 +672,7 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al) { - thread__find_addr_map(thread, machine, cpumode, type, addr, al, - machine->symbol_filter); + thread__find_addr_map(thread, machine, cpumode, type, addr, al); if (al->map != NULL) al->sym = map__find_symbol(al->map, al->addr, machine->symbol_filter); @@ -709,7 +708,7 @@ int perf_event__preprocess_sample(const union perf_event *event, machine__create_kernel_maps(machine); thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, - event->ip.ip, al, machine->symbol_filter); + event->ip.ip, al); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 0ab47d860d41..13c62c909392 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -41,7 +41,7 @@ static inline struct map *thread__find_map(struct thread *self, void thread__find_addr_map(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, - struct addr_location *al, symbol_filter_t filter); + struct addr_location *al); void thread__find_addr_location(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index abac3f97d95d..2f891f7e70bf 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c @@ -272,7 +272,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui) struct addr_location al; thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, - MAP__FUNCTION, ip, &al, NULL); + MAP__FUNCTION, ip, &al); return al.map; } @@ -349,7 +349,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, ssize_t size; thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, - MAP__FUNCTION, addr, &al, NULL); + MAP__FUNCTION, addr, &al); if (!al.map) { pr_debug("unwind: no map for %lx\n", (unsigned long)addr); return -1; -- cgit v1.2.3-58-ga151 From 309b5185047c5309bbc576025f6c5e257edd9f69 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 13 Aug 2013 22:32:12 -0600 Subject: perf tests: Fix compile failure on do_sort_something MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b55ae0a9 added code-reading.c which fails to compile on Fedora 16 with compiler version: $ gcc --version gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2) Failure message is: tests/code-reading.c: In function ‘do_sort_something’: tests/code-reading.c:305:13: error: stack protector not protecting local variables: variable length buffer [-Werror=stack-protector] cc1: all warnings being treated as errors make: *** [/tmp/junk/tests/code-reading.o] Error 1 make: *** Waiting for unfinished jobs.... v2: as Adrian noticed changed sizeof to ARRAY_SIZE Signed-off-by: David Ahern Acked-by: Adrian Hunter Cc: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1376454732-83728-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index eec1421a7e6b..df9afd9cab4c 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -304,15 +304,14 @@ static int comp(const void *a, const void *b) static void do_sort_something(void) { - size_t sz = 40960; - int buf[sz], i; + int buf[40960], i; - for (i = 0; i < (int)sz; i++) - buf[i] = sz - i - 1; + for (i = 0; i < (int)ARRAY_SIZE(buf); i++) + buf[i] = ARRAY_SIZE(buf) - i - 1; - qsort(buf, sz, sizeof(int), comp); + qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp); - for (i = 0; i < (int)sz; i++) { + for (i = 0; i < (int)ARRAY_SIZE(buf); i++) { if (buf[i] != i) { pr_debug("qsort failed\n"); break; -- cgit v1.2.3-58-ga151 From c5885749e4ebe568cca969d43488a233e69e6454 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 14 Aug 2013 12:04:26 +0200 Subject: perf tools: Improve robustness of topology parsing code This patch improves the robustness of the build_cpu_topo() routine by allowing either the CPU parsing or the thread parsing to fail and yet get perf to produce some topology data which could be useful for the analysis. Without this patch, if the cpu parsing fails, the thread parsing is not attempted vice-versa. Signed-off-by: Stephane Eranian Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20130814100426.GA3444@quad Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f558f83769af..a33197a4fd21 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -716,18 +716,19 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu) char filename[MAXPATHLEN]; char *buf = NULL, *p; size_t len = 0; + ssize_t sret; u32 i = 0; int ret = -1; sprintf(filename, CORE_SIB_FMT, cpu); fp = fopen(filename, "r"); if (!fp) - return -1; - - if (getline(&buf, &len, fp) <= 0) - goto done; + goto try_threads; + sret = getline(&buf, &len, fp); fclose(fp); + if (sret <= 0) + goto try_threads; p = strchr(buf, '\n'); if (p) @@ -743,7 +744,9 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu) buf = NULL; len = 0; } + ret = 0; +try_threads: sprintf(filename, THRD_SIB_FMT, cpu); fp = fopen(filename, "r"); if (!fp) -- cgit v1.2.3-58-ga151 From 2ae3a312c0ccd8ff615372f00aab1700aac27474 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 9 Aug 2013 12:28:31 -0300 Subject: perf trace: Allow specifying which syscalls to trace Similar to -e in strace, i.e. a comma separated list of syscall names to trace. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-5zku7q5wug3103k1dzn3yy63@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 4 +++ tools/perf/builtin-trace.c | 52 +++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 68718ccdd178..3b3552a8959e 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -26,6 +26,10 @@ OPTIONS --all-cpus:: System-wide collection from all CPUs. +-e:: +--expr:: + List of events to show, currently only syscall names. + -p:: --pid=:: Record events on existing process ID (comma separated list). diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index da7ae01c8394..120fdfb3d920 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -5,6 +5,7 @@ #include "util/machine.h" #include "util/thread.h" #include "util/parse-options.h" +#include "util/strlist.h" #include "util/thread_map.h" #include @@ -47,6 +48,7 @@ static struct syscall_fmt *syscall_fmt__find(const char *name) struct syscall { struct event_format *tp_format; const char *name; + bool filtered; struct syscall_fmt *fmt; }; @@ -110,6 +112,7 @@ struct trace { struct perf_record_opts opts; struct machine host; u64 base_time; + struct strlist *ev_qualifier; unsigned long nr_events; bool sched; bool multiple_threads; @@ -226,6 +229,16 @@ static int trace__read_syscall_info(struct trace *trace, int id) sc = trace->syscalls.table + id; sc->name = name; + + if (trace->ev_qualifier && !strlist__find(trace->ev_qualifier, name)) { + sc->filtered = true; + /* + * No need to do read tracepoint information since this will be + * filtered out. + */ + return 0; + } + sc->fmt = syscall_fmt__find(sc->name); snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); @@ -302,11 +315,19 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, char *msg; void *args; size_t printed = 0; - struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); + struct thread *thread; struct syscall *sc = trace__syscall_info(trace, evsel, sample); - struct thread_trace *ttrace = thread__trace(thread); + struct thread_trace *ttrace; + + if (sc == NULL) + return -1; - if (ttrace == NULL || sc == NULL) + if (sc->filtered) + return 0; + + thread = machine__findnew_thread(&trace->host, sample->tid); + ttrace = thread__trace(thread); + if (ttrace == NULL) return -1; args = perf_evsel__rawptr(evsel, sample, "args"); @@ -345,11 +366,19 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, { int ret; u64 duration = 0; - struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); - struct thread_trace *ttrace = thread__trace(thread); + struct thread *thread; struct syscall *sc = trace__syscall_info(trace, evsel, sample); + struct thread_trace *ttrace; + + if (sc == NULL) + return -1; - if (ttrace == NULL || sc == NULL) + if (sc->filtered) + return 0; + + thread = machine__findnew_thread(&trace->host, sample->tid); + ttrace = thread__trace(thread); + if (ttrace == NULL) return -1; ret = perf_evsel__intval(evsel, sample, "ret"); @@ -634,7 +663,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) .mmap_pages = 1024, }, }; + const char *ev_qualifier_str = NULL; const struct option trace_options[] = { + OPT_STRING('e', "expr", &ev_qualifier_str, "expr", + "list of events to trace"), OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", "trace events on existing process id"), OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", @@ -660,6 +692,14 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) argc = parse_options(argc, argv, trace_options, trace_usage, 0); + if (ev_qualifier_str != NULL) { + trace.ev_qualifier = strlist__new(true, ev_qualifier_str); + if (trace.ev_qualifier == NULL) { + puts("Not enough memory to parse event qualifier"); + return -ENOMEM; + } + } + err = perf_target__validate(&trace.opts.target); if (err) { perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); -- cgit v1.2.3-58-ga151