From ee8d7787e197a0b1829c3f17dc1287224f14f35e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 21 Nov 2012 18:58:50 -0300 Subject: perf top: Add missing newline on pr_err call The perf_event__process_sample function, when not finding a machine associated with a sample, was calling pr_err without a newline, garbling the screen on TUI mode due to a problem introduced by a recent ui_helpline patch. On --stdio it would just concatenate the messages for each sample with no machine associated, fix it by adding the newline. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-vuz88welqvp15c2uybd9osnz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/perf/builtin-top.c') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c9ff3950cd4b..987e1b8a9c2e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -727,7 +727,7 @@ static void perf_event__process_sample(struct perf_tool *tool, } if (!machine) { - pr_err("%u unprocessable samples recorded.", + pr_err("%u unprocessable samples recorded.\n", top->session->hists.stats.nr_unprocessable_samples++); return; } -- cgit v1.2.3 From 7be5ebe8767eaa482e18f566de5f56c1519abf59 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Dec 2012 14:53:43 -0300 Subject: perf evsel: Update sample_size when setting sample_type bits We use evsel->sample_size to detect underflows in perf_evsel__parse_sample, but we were failing to update it after perf_evsel__init(), i.e. when we decide, after creating an evsel, that we want some extra field bit set. Fix it by introducing methods to set a bit that will take care of correctly adjusting evsel->sample_size. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-2ny5pzsing0dcth7hws48x9c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 11 ++++++----- tools/perf/tests/perf-record.c | 6 +++--- tools/perf/util/evlist.c | 2 +- tools/perf/util/evsel.c | 45 ++++++++++++++++++++++++++++++------------ tools/perf/util/evsel.h | 11 +++++++++++ 6 files changed, 54 insertions(+), 23 deletions(-) (limited to 'tools/perf/builtin-top.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f3151d3c70ce..0be6605db9ea 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -286,7 +286,7 @@ try_again: */ opts->sample_id_all_missing = true; if (!opts->sample_time && !opts->raw_samples && !time_needed) - attr->sample_type &= ~PERF_SAMPLE_TIME; + perf_evsel__reset_sample_bit(pos, TIME); goto retry_sample_id; } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 987e1b8a9c2e..31a7c51aac76 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -901,24 +901,25 @@ static void perf_top__start_counters(struct perf_top *top) list_for_each_entry(counter, &evlist->entries, node) { struct perf_event_attr *attr = &counter->attr; - attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; + perf_evsel__set_sample_bit(counter, IP); + perf_evsel__set_sample_bit(counter, TID); if (top->freq) { - attr->sample_type |= PERF_SAMPLE_PERIOD; + perf_evsel__set_sample_bit(counter, PERIOD); attr->freq = 1; attr->sample_freq = top->freq; } if (evlist->nr_entries > 1) { - attr->sample_type |= PERF_SAMPLE_ID; + perf_evsel__set_sample_bit(counter, ID); attr->read_format |= PERF_FORMAT_ID; } if (perf_target__has_cpu(&top->target)) - attr->sample_type |= PERF_SAMPLE_CPU; + perf_evsel__set_sample_bit(counter, CPU); if (symbol_conf.use_callchain) - attr->sample_type |= PERF_SAMPLE_CALLCHAIN; + perf_evsel__set_sample_bit(counter, CALLCHAIN); attr->mmap = 1; attr->comm = 1; diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 70e0d4421df8..5902772492b6 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -103,9 +103,9 @@ int test__PERF_RECORD(void) * Config the evsels, setting attr->comm on the first one, etc. */ evsel = perf_evlist__first(evlist); - evsel->attr.sample_type |= PERF_SAMPLE_CPU; - evsel->attr.sample_type |= PERF_SAMPLE_TID; - evsel->attr.sample_type |= PERF_SAMPLE_TIME; + perf_evsel__set_sample_bit(evsel, CPU); + perf_evsel__set_sample_bit(evsel, TID); + perf_evsel__set_sample_bit(evsel, TIME); perf_evlist__config_attrs(evlist, &opts); err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d0e1e821fe85..265565942ae5 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -61,7 +61,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist, perf_evsel__config(evsel, opts); if (evlist->nr_entries > 1) - evsel->attr.sample_type |= PERF_SAMPLE_ID; + perf_evsel__set_sample_bit(evsel, ID); } } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index bb58b05f905f..fc80f5a32fa6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -50,6 +50,24 @@ void hists__init(struct hists *hists) pthread_mutex_init(&hists->lock, NULL); } +void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, + enum perf_event_sample_format bit) +{ + if (!(evsel->attr.sample_type & bit)) { + evsel->attr.sample_type |= bit; + evsel->sample_size += sizeof(u64); + } +} + +void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, + enum perf_event_sample_format bit) +{ + if (evsel->attr.sample_type & bit) { + evsel->attr.sample_type &= ~bit; + evsel->sample_size -= sizeof(u64); + } +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { @@ -445,7 +463,8 @@ void perf_evsel__config(struct perf_evsel *evsel, PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; - attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; + perf_evsel__set_sample_bit(evsel, IP); + perf_evsel__set_sample_bit(evsel, TID); /* * We default some events to a 1 default interval. But keep @@ -454,7 +473,7 @@ void perf_evsel__config(struct perf_evsel *evsel, if (!attr->sample_period || (opts->user_freq != UINT_MAX && opts->user_interval != ULLONG_MAX)) { if (opts->freq) { - attr->sample_type |= PERF_SAMPLE_PERIOD; + perf_evsel__set_sample_bit(evsel, PERIOD); attr->freq = 1; attr->sample_freq = opts->freq; } else { @@ -469,16 +488,16 @@ void perf_evsel__config(struct perf_evsel *evsel, attr->inherit_stat = 1; if (opts->sample_address) { - attr->sample_type |= PERF_SAMPLE_ADDR; + perf_evsel__set_sample_bit(evsel, ADDR); attr->mmap_data = track; } if (opts->call_graph) { - attr->sample_type |= PERF_SAMPLE_CALLCHAIN; + perf_evsel__set_sample_bit(evsel, CALLCHAIN); if (opts->call_graph == CALLCHAIN_DWARF) { - attr->sample_type |= PERF_SAMPLE_REGS_USER | - PERF_SAMPLE_STACK_USER; + perf_evsel__set_sample_bit(evsel, REGS_USER); + perf_evsel__set_sample_bit(evsel, STACK_USER); attr->sample_regs_user = PERF_REGS_MASK; attr->sample_stack_user = opts->stack_dump_size; attr->exclude_callchain_user = 1; @@ -486,20 +505,20 @@ void perf_evsel__config(struct perf_evsel *evsel, } if (perf_target__has_cpu(&opts->target)) - attr->sample_type |= PERF_SAMPLE_CPU; + perf_evsel__set_sample_bit(evsel, CPU); if (opts->period) - attr->sample_type |= PERF_SAMPLE_PERIOD; + perf_evsel__set_sample_bit(evsel, PERIOD); if (!opts->sample_id_all_missing && (opts->sample_time || !opts->no_inherit || perf_target__has_cpu(&opts->target))) - attr->sample_type |= PERF_SAMPLE_TIME; + perf_evsel__set_sample_bit(evsel, TIME); if (opts->raw_samples) { - attr->sample_type |= PERF_SAMPLE_TIME; - attr->sample_type |= PERF_SAMPLE_RAW; - attr->sample_type |= PERF_SAMPLE_CPU; + perf_evsel__set_sample_bit(evsel, TIME); + perf_evsel__set_sample_bit(evsel, RAW); + perf_evsel__set_sample_bit(evsel, CPU); } if (opts->no_delay) { @@ -507,7 +526,7 @@ void perf_evsel__config(struct perf_evsel *evsel, attr->wakeup_events = 1; } if (opts->branch_stack) { - attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; + perf_evsel__set_sample_bit(evsel, BRANCH_STACK); attr->branch_sample_type = opts->branch_stack; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3f7ff471de2b..739853969243 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -118,6 +118,17 @@ void perf_evsel__free_fd(struct perf_evsel *evsel); void perf_evsel__free_id(struct perf_evsel *evsel); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); +void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, + enum perf_event_sample_format bit); +void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, + enum perf_event_sample_format bit); + +#define perf_evsel__set_sample_bit(evsel, bit) \ + __perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit) + +#define perf_evsel__reset_sample_bit(evsel, bit) \ + __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit) + int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, const char *filter); -- cgit v1.2.3 From 7a5a5ca5fe3df8636c96b49591c23baf7c415dd4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Dec 2012 15:21:30 -0300 Subject: perf evsel: Introduce method to request IDs be used When mmaping multiple events we need to find the right evsel that matches an event in the ring buffer. For that we need to set the PERF_FORMAT_ID bit in perf_event_attr.read_format so that when we read the event fds we get that id to then hash it and be able later to use perf_evlist__id2evsel to find the right evsel. We also need to set the PERF_SAMPLE_ID bit in perf_event_attr.sample_type to ask for that id to be stashed in each sample, so that we can demux it. So add a perf_evsel__set_sample_id() method to do those two things in one operation. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-1z4xcmbud30lamklfe80oopu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 6 ++---- tools/perf/tests/mmap-basic.c | 3 +-- tools/perf/util/evsel.c | 6 ++++++ tools/perf/util/evsel.h | 2 ++ 4 files changed, 11 insertions(+), 6 deletions(-) (limited to 'tools/perf/builtin-top.c') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 31a7c51aac76..a30647487ba3 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -910,10 +910,8 @@ static void perf_top__start_counters(struct perf_top *top) attr->sample_freq = top->freq; } - if (evlist->nr_entries > 1) { - perf_evsel__set_sample_bit(counter, ID); - attr->read_format |= PERF_FORMAT_ID; - } + if (evlist->nr_entries > 1) + perf_evsel__set_sample_id(counter); if (perf_target__has_cpu(&top->target)) perf_evsel__set_sample_bit(counter, CPU); diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 4743b6d7a09a..cdd50755af51 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -70,8 +70,7 @@ int test__basic_mmap(void) } evsels[i]->attr.wakeup_events = 1; - evsels[i]->attr.read_format |= PERF_FORMAT_ID; - perf_evsel__set_sample_bit(evsels[i], ID); + perf_evsel__set_sample_id(evsels[i]); perf_evlist__add(evlist, evsels[i]); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index fc80f5a32fa6..9dde7e933be9 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -68,6 +68,12 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, } } +void perf_evsel__set_sample_id(struct perf_evsel *evsel) +{ + perf_evsel__set_sample_bit(evsel, ID); + evsel->attr.read_format |= PERF_FORMAT_ID; +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 739853969243..5c089775064f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -129,6 +129,8 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, #define perf_evsel__reset_sample_bit(evsel, bit) \ __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit) +void perf_evsel__set_sample_id(struct perf_evsel *evsel); + int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, const char *filter); -- cgit v1.2.3 From 2376c67a7bbc7849b806688ba2efb8520c21c458 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 11 Dec 2012 16:48:41 -0300 Subject: perf top: Use perf_evlist__config() Using struct perf_record_opts to specify how to configure the evsel perf_event_attrs. This gets top closer to record in the way it sets up evsels, with the aim of sharing more and more to the point that both will be a single utility. In this direction top now uses the same callchain option parsing as record and that brings DWARF callchains to top, something that was already available for record. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-u03o0bsrqcjgskciso3pvsjr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-top.txt | 2 +- tools/perf/builtin-top.c | 204 +++++++++++----------------------- tools/perf/util/top.c | 22 ++-- tools/perf/util/top.h | 8 +- 4 files changed, 79 insertions(+), 157 deletions(-) (limited to 'tools/perf/builtin-top.c') diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 5b80d84d6b4a..a414bc95fd52 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -60,7 +60,7 @@ Default is to monitor all CPUS. -i:: --inherit:: - Child tasks inherit counters, only makes sens with -p option. + Child tasks do not inherit counters. -k :: --vmlinux=:: diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a30647487ba3..b7d2ea62dbc6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -596,7 +596,7 @@ static void *display_thread_tui(void *arg) * via --uid. */ list_for_each_entry(pos, &top->evlist->entries, node) - pos->hists.uid_filter_str = top->target.uid_str; + pos->hists.uid_filter_str = top->record_opts.target.uid_str; perf_evlist__tui_browse_hists(top->evlist, help, &hbt, &top->session->header.env); @@ -894,34 +894,13 @@ static void perf_top__start_counters(struct perf_top *top) { struct perf_evsel *counter; struct perf_evlist *evlist = top->evlist; + struct perf_record_opts *opts = &top->record_opts; - if (top->group) - perf_evlist__set_leader(evlist); + perf_evlist__config(evlist, opts); list_for_each_entry(counter, &evlist->entries, node) { struct perf_event_attr *attr = &counter->attr; - perf_evsel__set_sample_bit(counter, IP); - perf_evsel__set_sample_bit(counter, TID); - - if (top->freq) { - perf_evsel__set_sample_bit(counter, PERIOD); - attr->freq = 1; - attr->sample_freq = top->freq; - } - - if (evlist->nr_entries > 1) - perf_evsel__set_sample_id(counter); - - if (perf_target__has_cpu(&top->target)) - perf_evsel__set_sample_bit(counter, CPU); - - if (symbol_conf.use_callchain) - perf_evsel__set_sample_bit(counter, CALLCHAIN); - - attr->mmap = 1; - attr->comm = 1; - attr->inherit = top->inherit; fallback_missing_features: if (top->exclude_guest_missing) attr->exclude_guest = attr->exclude_host = 0; @@ -995,7 +974,7 @@ try_again: } } - if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) { + if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { ui__error("Failed to mmap with %d (%s)\n", errno, strerror(errno)); goto out_err; @@ -1015,7 +994,7 @@ static int perf_top__setup_sample_type(struct perf_top *top) ui__error("Selected -g but \"sym\" not present in --sort/-s."); return -EINVAL; } - } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) { + } else if (callchain_param.mode != CHAIN_NONE) { if (callchain_register_param(&callchain_param) < 0) { ui__error("Can't register callchain params.\n"); return -EINVAL; @@ -1027,6 +1006,7 @@ static int perf_top__setup_sample_type(struct perf_top *top) static int __cmd_top(struct perf_top *top) { + struct perf_record_opts *opts = &top->record_opts; pthread_t thread; int ret; /* @@ -1041,7 +1021,7 @@ static int __cmd_top(struct perf_top *top) if (ret) goto out_delete; - if (perf_target__has_task(&top->target)) + if (perf_target__has_task(&opts->target)) perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, perf_event__process, &top->session->host_machine); @@ -1052,6 +1032,17 @@ static int __cmd_top(struct perf_top *top) top->session->evlist = top->evlist; perf_session__set_id_hdr_size(top->session); + /* + * When perf is starting the traced process, all the events (apart from + * group members) have enable_on_exec=1 set, so don't spoil it by + * prematurely enabling them. + * + * XXX 'top' still doesn't start workloads like record, trace, but should, + * so leave the check here. + */ + if (!perf_target__none(&opts->target)) + perf_evlist__enable(top->evlist); + /* Wait for a minimal set of events before starting the snapshot */ poll(top->evlist->pollfd, top->evlist->nr_fds, 100); @@ -1092,116 +1083,56 @@ out_delete: static int parse_callchain_opt(const struct option *opt, const char *arg, int unset) { - struct perf_top *top = (struct perf_top *)opt->value; - char *tok, *tok2; - char *endptr; - /* * --no-call-graph */ - if (unset) { - top->dont_use_callchains = true; + if (unset) return 0; - } symbol_conf.use_callchain = true; - if (!arg) - return 0; - - tok = strtok((char *)arg, ","); - if (!tok) - return -1; - - /* get the output mode */ - if (!strncmp(tok, "graph", strlen(arg))) - callchain_param.mode = CHAIN_GRAPH_ABS; - - else if (!strncmp(tok, "flat", strlen(arg))) - callchain_param.mode = CHAIN_FLAT; - - else if (!strncmp(tok, "fractal", strlen(arg))) - callchain_param.mode = CHAIN_GRAPH_REL; - - else if (!strncmp(tok, "none", strlen(arg))) { - callchain_param.mode = CHAIN_NONE; - symbol_conf.use_callchain = false; - - return 0; - } else - return -1; - - /* get the min percentage */ - tok = strtok(NULL, ","); - if (!tok) - goto setup; - - callchain_param.min_percent = strtod(tok, &endptr); - if (tok == endptr) - return -1; - - /* get the print limit */ - tok2 = strtok(NULL, ","); - if (!tok2) - goto setup; - - if (tok2[0] != 'c') { - callchain_param.print_limit = strtod(tok2, &endptr); - tok2 = strtok(NULL, ","); - if (!tok2) - goto setup; - } - - /* get the call chain order */ - if (!strcmp(tok2, "caller")) - callchain_param.order = ORDER_CALLER; - else if (!strcmp(tok2, "callee")) - callchain_param.order = ORDER_CALLEE; - else - return -1; -setup: - if (callchain_register_param(&callchain_param) < 0) { - fprintf(stderr, "Can't register callchain params\n"); - return -1; - } - return 0; + return record_parse_callchain_opt(opt, arg, unset); } int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) { - struct perf_evsel *pos; int status; char errbuf[BUFSIZ]; struct perf_top top = { .count_filter = 5, .delay_secs = 2, - .freq = 4000, /* 4 KHz */ - .mmap_pages = 128, - .sym_pcnt_filter = 5, - .target = { - .uses_mmap = true, + .record_opts = { + .mmap_pages = UINT_MAX, + .user_freq = UINT_MAX, + .user_interval = ULLONG_MAX, + .freq = 4000, /* 4 KHz */ + .target = { + .uses_mmap = true, + }, }, + .sym_pcnt_filter = 5, }; - char callchain_default_opt[] = "fractal,0.5,callee"; + struct perf_record_opts *opts = &top.record_opts; + struct perf_target *target = &opts->target; const struct option options[] = { OPT_CALLBACK('e', "event", &top.evlist, "event", "event selector. use 'perf list' to list available events", parse_events_option), - OPT_INTEGER('c', "count", &top.default_interval, - "event period to sample"), - OPT_STRING('p', "pid", &top.target.pid, "pid", + OPT_U64('c', "count", &opts->user_interval, "event period to sample"), + OPT_STRING('p', "pid", &target->pid, "pid", "profile events on existing process id"), - OPT_STRING('t', "tid", &top.target.tid, "tid", + OPT_STRING('t', "tid", &target->tid, "tid", "profile events on existing thread id"), - OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide, + OPT_BOOLEAN('a', "all-cpus", &target->system_wide, "system-wide collection from all CPUs"), - OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu", + OPT_STRING('C', "cpu", &target->cpu_list, "cpu", "list of cpus to monitor"), OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, "hide kernel symbols"), - OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"), + OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages, + "number of mmap data pages"), OPT_INTEGER('r', "realtime", &top.realtime_prio, "collect data with this RT SCHED_FIFO priority"), OPT_INTEGER('d', "delay", &top.delay_secs, @@ -1210,16 +1141,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "dump the symbol table used for profiling"), OPT_INTEGER('f', "count-filter", &top.count_filter, "only display functions with more events than this"), - OPT_BOOLEAN('g', "group", &top.group, + OPT_BOOLEAN('g', "group", &opts->group, "put the counters into a counter group"), - OPT_BOOLEAN('i', "inherit", &top.inherit, - "child tasks inherit counters"), + OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit, + "child tasks do not inherit counters"), OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", "symbol to annotate"), - OPT_BOOLEAN('z', "zero", &top.zero, - "zero history across updates"), - OPT_INTEGER('F', "freq", &top.freq, - "profile at this frequency"), + OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"), + OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"), OPT_INTEGER('E', "entries", &top.print_entries, "display this many functions"), OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, @@ -1232,10 +1161,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "sort by key(s): pid, comm, dso, symbol, parent"), OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, "Show a column with the number of samples"), - OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order", - "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " - "Default: fractal,0.5,callee", &parse_callchain_opt, - callchain_default_opt), + OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, + "mode[,dump_size]", record_callchain_help, + &parse_callchain_opt, "fp"), OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, "Show a column with the sum of periods"), OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", @@ -1250,7 +1178,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), - OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), + OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), OPT_END() }; const char * const top_usage[] = { @@ -1280,27 +1208,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(false); - status = perf_target__validate(&top.target); + status = perf_target__validate(target); if (status) { - perf_target__strerror(&top.target, status, errbuf, BUFSIZ); + perf_target__strerror(target, status, errbuf, BUFSIZ); ui__warning("%s", errbuf); } - status = perf_target__parse_uid(&top.target); + status = perf_target__parse_uid(target); if (status) { int saved_errno = errno; - perf_target__strerror(&top.target, status, errbuf, BUFSIZ); + perf_target__strerror(target, status, errbuf, BUFSIZ); ui__error("%s", errbuf); status = -saved_errno; goto out_delete_evlist; } - if (perf_target__none(&top.target)) - top.target.system_wide = true; + if (perf_target__none(target)) + target->system_wide = true; - if (perf_evlist__create_maps(top.evlist, &top.target) < 0) + if (perf_evlist__create_maps(top.evlist, target) < 0) usage_with_options(top_usage, options); if (!top.evlist->nr_entries && @@ -1314,24 +1242,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (top.delay_secs < 1) top.delay_secs = 1; + if (opts->user_interval != ULLONG_MAX) + opts->default_interval = opts->user_interval; + if (opts->user_freq != UINT_MAX) + opts->freq = opts->user_freq; + /* * User specified count overrides default frequency. */ - if (top.default_interval) - top.freq = 0; - else if (top.freq) { - top.default_interval = top.freq; + if (opts->default_interval) + opts->freq = 0; + else if (opts->freq) { + opts->default_interval = opts->freq; } else { ui__error("frequency and count are zero, aborting\n"); - exit(EXIT_FAILURE); - } - - list_for_each_entry(pos, &top.evlist->entries, node) { - /* - * Fill in the ones not specifically initialized via -c: - */ - if (!pos->attr.sample_period) - pos->attr.sample_period = top.default_interval; + status = -EINVAL; + goto out_delete_evlist; } top.sym_evsel = perf_evlist__first(top.evlist); diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 884dde9b9bc1..54d37a4753c5 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) float samples_per_sec = top->samples / top->delay_secs; float ksamples_per_sec = top->kernel_samples / top->delay_secs; float esamples_percent = (100.0 * top->exact_samples) / top->samples; + struct perf_record_opts *opts = &top->record_opts; + struct perf_target *target = &opts->target; size_t ret = 0; if (!perf_guest) { @@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) struct perf_evsel *first = perf_evlist__first(top->evlist); ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", (uint64_t)first->attr.sample_period, - top->freq ? "Hz" : ""); + opts->freq ? "Hz" : ""); } ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel)); ret += SNPRINTF(bf + ret, size - ret, "], "); - if (top->target.pid) + if (target->pid) ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", - top->target.pid); - else if (top->target.tid) + target->pid); + else if (target->tid) ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", - top->target.tid); - else if (top->target.uid_str != NULL) + target->tid); + else if (target->uid_str != NULL) ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", - top->target.uid_str); + target->uid_str); else ret += SNPRINTF(bf + ret, size - ret, " (all"); - if (top->target.cpu_list) + if (target->cpu_list) ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", top->evlist->cpus->nr > 1 ? "s" : "", - top->target.cpu_list); + target->cpu_list); else { - if (top->target.tid) + if (target->tid) ret += SNPRINTF(bf + ret, size - ret, ")"); else ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 86ff1b15059b..927c229c2d9a 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -14,7 +14,7 @@ struct perf_session; struct perf_top { struct perf_tool tool; struct perf_evlist *evlist; - struct perf_target target; + struct perf_record_opts record_opts; /* * Symbols will be added here in perf_event__process_sample and will * get out after decayed. @@ -24,15 +24,11 @@ struct perf_top { u64 exact_samples; u64 guest_us_samples, guest_kernel_samples; int print_entries, count_filter, delay_secs; - int freq; bool hide_kernel_symbols, hide_user_symbols, zero; bool use_tui, use_stdio; bool sort_has_symbols; - bool dont_use_callchains; bool kptr_restrict_warned; bool vmlinux_warned; - bool inherit; - bool group; bool sample_id_all_missing; bool exclude_guest_missing; bool dump_symtab; @@ -40,8 +36,6 @@ struct perf_top { struct perf_evsel *sym_evsel; struct perf_session *session; struct winsize winsize; - unsigned int mmap_pages; - int default_interval; int realtime_prio; int sym_pcnt_filter; const char *sym_filter; -- cgit v1.2.3