perf: consolidate all the open counters loops
v2 cover perf: consolidate all the open counters loops
This patch set consolidates all of the open counters loops into a single common one.
Rebased to latest perf/core. Added more hooks to ui stubs file.
David Ahern (9):
perf python: add ui stubs file
perf top: make use of perf_record_opts
perf evlist: introduce open counters method
perf top: use the new perf_evlist__open_counters method perf record: use the new perf_evlist__open_counters method perf stat: move user options to perf_record_opts perf evlist: add stat unique code to open_counters method perf stat: move to perf_evlist__open_counters perf evsel: remove perf_evsel__open_per_cpu
tools/perf/builtin-record.c | 116 +---------------- tools/perf/builtin-stat.c | 246 ++++++++++++++++-------------------- tools/perf/builtin-top.c | 146 ++++++--------------- tools/perf/util/evlist.c | 143 ++++++++++++++++++++- tools/perf/util/evlist.h | 4 + tools/perf/util/evsel.c | 6 - tools/perf/util/evsel.h | 2 - tools/perf/util/python-ext-sources | 1 + tools/perf/util/python_stubs.c | 54 ++++++++ tools/perf/util/top.c | 20 +-- tools/perf/util/top.h | 9 +- 11 files changed, 366 insertions(+), 381 deletions(-) create mode 100644 tools/perf/util/python_stubs.c
Signature · 1 line
1.7.10.1
PATCH v2 1/9 perf python: add ui stubs file
stdio based implementations of ui_xxxx based functions for the python library. Needed for patch 3 - consolidating open counters method.
--- tools/perf/util/python-ext-sources | 1 + tools/perf/util/python_stubs.c | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tools/perf/util/python_stubs.c
tools/perf/util/python-ext-sources +1 -0
@@ -19,3 +19,4 @@ util/debugfs.c util/rblist.c util/strlist.c ../../lib/rbtree.c +util/python_stubs.c
tools/perf/util/python_stubs.c new file +54 -0
54 lines not on this page · raw message
Signature · 1 line
1.7.10.1
Namhyung Kim
maintainerRe: [PATCH 1/9] perf python: add ui stubs file
Hi David,
Quoted 2 lines · David Ahern
stdio based implementations of
ui_xxxxbased functions for the python library. Needed for patch 3 - consolidating open counters method.
How about adding ui/util.c to the python-ext-sources?
Thanks,
Namhyung
Re: [PATCH 1/9] perf python: add ui stubs file
Quoted 7 lines · Namhyung Kim
Hi David,
Quoted 2 lines · David Ahern
stdio based implementations of
ui_xxxxbased functions for the python library. Needed for patch 3 - consolidating open counters method.How about adding
ui/util.cto the python-ext-sources?
Handles some of the ui_xxxx functions, but still missing some symbols -- verbose, eprintf, ui__error_paranoid. The point of the python_stubs.c was a short term solution for the ui handlers. Arnaldo had some ideas on what is really needed.
David
Re: [PATCH 1/9] perf python: add ui stubs file
Em Tue, Oct 30, 2012 at 08:45:28AM -0600, David Ahern escreveu:
Quoted 11 lines · Namhyung Kim
Quoted 5 lines · David Ahern
Quoted 2 lines
stdio based implementations of
ui_xxxxbased functions for the python library. Needed for patch 3 - consolidating open counters method.How about adding
ui/util.cto the python-ext-sources?Handles some of the
ui_xxxxfunctions, but still missing some symbols -- verbose, eprintf,ui__error_paranoid. The point of thepython_stubs.cwas a short term solution for the ui handlers. Arnaldo had some ideas on what is really needed.
Yes, and that is something like what Namhyung did for perf_target, i.e. don't call ui__ stuff from the evsel/evlist classes but use a perf_evlist__strerror, merge perf_evlist__open_counters() with perf_evlist__open(), use just perf_evlist__open() everywhere, so that all tools get the fallbacks for features not present in older kernels, etc.
- Arnaldo
Namhyung Kim
maintainerRe: [PATCH 1/9] perf python: add ui stubs file
Quoted 13 lines · Arnaldo Carvalho de Melo
Em Tue, Oct 30, 2012 at 08:45:28AM -0600, David Ahern escreveu:
Quoted 11 lines · Namhyung Kim
Quoted 5 lines · David Ahern
Quoted 2 lines
stdio based implementations of
ui_xxxxbased functions for the python library. Needed for patch 3 - consolidating open counters method.How about adding
ui/util.cto the python-ext-sources?Handles some of the
ui_xxxxfunctions, but still missing some symbols -- verbose, eprintf,ui__error_paranoid. The point of thepython_stubs.cwas a short term solution for the ui handlers. Arnaldo had some ideas on what is really needed.
Quoted 6 lines
Yes, and that is something like what Namhyung did for
perf_target, i.e. don't callui__stuff from the evsel/evlist classes but use aperf_evlist__strerror, mergeperf_evlist__open_counters()withperf_evlist__open(), use justperf_evlist__open()everywhere, so that all tools get the fallbacks for features not present in older kernels, etc.
Yeah, it'd be better definitely. But the problem is we might emit warnings even in the internal fallback loop. Not sure how to handle it with this approach.
Thanks,
Namhyung
PATCH v2 2/9 perf top: make use of perf_record_opts
In reply to David AhernChanges top code to use the perf_record_opts struct. Stepping stone to consolidating the open counters code.
--- tools/perf/builtin-top.c | 84 ++++++++++++++++++++++++---------------------- tools/perf/util/top.c | 20 +++++------ tools/perf/util/top.h | 9 +---- 3 files changed, 54 insertions(+), 59 deletions(-)
tools/perf/builtin-top.c +43 -41
@@ -591,7 +591,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->opts.target.uid_str; perf_evlist__tui_browse_hists(top->evlist, help, perf_top__sort_new_samples,
@@ -891,7 +891,7 @@ static void perf_top__start_counters(struct perf_top *top)struct perf_evsel *counter;struct perf_evlist *evlist = top->evlist; -if (top->group) +if (top->opts.group)perf_evlist__set_leader (evlist);list_for_each_entry (counter, &evlist->entries, node) {
@@ -899,10 +899,10 @@ static void perf_top__start_counters(struct perf_top *top) attr->sample_type =PERF_SAMPLE_IP |PERF_SAMPLE_TID ; -if (top->freq) { +if (top->opts.freq) { attr->sample_type |=PERF_SAMPLE_PERIOD ; attr->freq =1 ; - attr->sample_freq = top->freq; + attr->sample_freq = top->opts.freq; }if (evlist->nr_entries >1 ) {
@@ -910,7 +910,7 @@ static void perf_top__start_counters(struct perf_top *top) attr->read_format |=PERF_FORMAT_ID ; } -if (perf_target__has_cpu (&top->target)) +if (perf_target__has_cpu (&top->opts.target)) attr->sample_type |=PERF_SAMPLE_CPU ;if (symbol_conf.use_callchain)
@@ -918,12 +918,12 @@ static void perf_top__start_counters(struct perf_top *top) attr->mmap =1 ; attr->comm =1 ; - attr->inherit = top->inherit; + attr->inherit = !top->opts.no_inherit; fallback_missing_features: -if (top->exclude_guest_missing) +if (top->opts.exclude_guest_missing) attr->exclude_guest = attr->exclude_host =0 ; retry_sample_id: - attr->sample_id_all = top->sample_id_all_missing ?0 :1 ; + attr->sample_id_all = top->opts.sample_id_all_missing ?0 :1 ; try_again:if (perf_evsel__open (counter, top->evlist->cpus, top->evlist->threads) <0 ) {
@@ -933,17 +933,17 @@ try_again:ui__error_paranoid (); goto out_err; }else if (err ==EINVAL ) { -if (!top->exclude_guest_missing && +if (!top->opts.exclude_guest_missing && (attr->exclude_guest || attr->exclude_host)) {pr_debug ("Old kernel, cannot exclude " "guest or host samples.\n" ); - top->exclude_guest_missing = true; + top->opts.exclude_guest_missing = true; goto fallback_missing_features; - }else if (!top->sample_id_all_missing) { + }else if (!top->opts.sample_id_all_missing) {/* * Old kernel, no attr->sample_id_type_all field */ - top->sample_id_all_missing = true; + top->opts.sample_id_all_missing = true; goto retry_sample_id; } }
@@ -992,7 +992,7 @@ try_again: } } -if (perf_evlist__mmap (evlist, top->mmap_pages, false) <0 ) { +if (perf_evlist__mmap (evlist, top->opts.mmap_pages, false) <0 ) {ui__error ("Failed to mmap with %d (%s)\n" , errno,strerror (errno)); goto out_err;
@@ -1038,7 +1038,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 (&top->opts.target))perf_event__synthesize_thread_map (&top->tool, top->evlist->threads, perf_event__process, &top->session->host_machine);
@@ -1172,11 +1172,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)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, + .opts = { + .freq =4000 ,/* 4 KHz */ + .mmap_pages =128 , + .target = { + .uses_mmap = true, + }, }, };char callchain_default_opt[] ="fractal,0.5,callee" ;
@@ -1184,21 +1186,21 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)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" , &top.opts.default_interval, +"event period to sample" ), +OPT_STRING ('p' ,"pid" , &top.opts.target.pid,"pid" ,"profile events on existing process id" ), -OPT_STRING ('t' ,"tid" , &top.target.tid,"tid" , +OPT_STRING ('t' ,"tid" , &top.opts.target.tid,"tid" ,"profile events on existing thread id" ), -OPT_BOOLEAN ('a' ,"all-cpus" , &top.target.system_wide, +OPT_BOOLEAN ('a' ,"all-cpus" , &top.opts.target.system_wide,"system-wide collection from all CPUs" ), -OPT_STRING ('C' ,"cpu" , &top.target.cpu_list,"cpu" , +OPT_STRING ('C' ,"cpu" , &top.opts.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" , &top.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,
@@ -1207,15 +1209,15 @@ 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" , &top.opts.group,"put the counters into a counter group" ), -OPT_BOOLEAN ('i' ,"inherit" , &top.inherit, +OPT_BOOLEAN ('i' ,"inherit" , &top.opts.no_inherit,"child tasks 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, +OPT_UINTEGER ('F' ,"freq" , &top.opts.freq,"profile at this frequency" ),OPT_INTEGER ('E' ,"entries" , &top.print_entries, "display this many functions"),
@@ -1247,7 +1249,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" , &top.opts.target.uid_str,"user" ,"user to profile" ),OPT_END () }; const char * const top_usage[] = {
@@ -1277,27 +1279,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 (&top.opts.target);if (status) { -perf_target__strerror (&top.target, status, errbuf,BUFSIZ ); +perf_target__strerror (&top.opts.target, status, errbuf,BUFSIZ );ui__warning ("%s" , errbuf); } - status =perf_target__parse_uid (&top.target); + status =perf_target__parse_uid (&top.opts.target);if (status) {int saved_errno = errno; -perf_target__strerror (&top.target, status, errbuf,BUFSIZ ); +perf_target__strerror (&top.opts.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 (&top.opts.target)) + top.opts.target.system_wide = true; -if (perf_evlist__create_maps (top.evlist, &top.target) <0 ) +if (perf_evlist__create_maps (top.evlist, &top.opts.target) <0 )usage_with_options (top_usage, options); if (!top.evlist->nr_entries &&
@@ -1314,10 +1316,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)/* * User specified count overrides default frequency. */ -if (top.default_interval) - top.freq =0 ; -else if (top.freq) { - top.default_interval = top.freq; +if (top.opts.default_interval) + top.opts.freq =0 ; +else if (top.opts.freq) { + top.opts.default_interval = top.opts.freq; }else {ui__error ("frequency and count are zero, aborting\n" );exit (EXIT_FAILURE );
@@ -1328,7 +1330,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)* Fill in the ones not specifically initialized via -c: */ if (!pos->attr.sample_period) - pos->attr.sample_period = top.default_interval; + pos->attr.sample_period = top.opts.default_interval; } top.sym_evsel =perf_evlist__first (top.evlist);
tools/perf/util/top.c +10 -10
@@ -61,31 +61,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" :"" ); + top->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 (top->opts.target.pid) ret +=SNPRINTF (bf + ret, size - ret," (target_pid: %s" , - top->target.pid); -else if (top->target.tid) + top->opts.target.pid); +else if (top->opts.target.tid) ret +=SNPRINTF (bf + ret, size - ret," (target_tid: %s" , - top->target.tid); -else if (top->target.uid_str !=NULL ) + top->opts.target.tid); +else if (top->opts.target.uid_str !=NULL ) ret +=SNPRINTF (bf + ret, size - ret," (uid: %s" , - top->target.uid_str); + top->opts.target.uid_str);else ret +=SNPRINTF (bf + ret, size - ret," (all" ); -if (top->target.cpu_list) +if (top->opts.target.cpu_list) ret +=SNPRINTF (bf + ret, size - ret,", CPU%s: %s)" , top->evlist->cpus->nr >1 ?"s" :"" , - top->target.cpu_list); + top->opts.target.cpu_list);else { -if (top->target.tid) +if (top->opts.target.tid) ret +=SNPRINTF (bf + ret, size - ret,")" );else ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
tools/perf/util/top.h +1 -8
@@ -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 opts;/* * Symbols will be added here in perf_event__process_sample and will * get out after decayed.
@@ -24,24 +24,17 @@ 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;struct hist_entry *sym_filter_entry;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;
Signature · 1 line
1.7.10.1
Namhyung Kim
maintainerRe: [PATCH 2/9] perf top: make use of perf_record_opts
Quoted 2 lines · David Ahern
Changes top code to use the
perf_record_optsstruct. Stepping stone to consolidating the open counters code.
Maybe time to rename perf_record_opts to perf_open_opts or just perf_opts?
Thanks,
Namhyung
Re: [PATCH 2/9] perf top: make use of perf_record_opts
Quoted 5 lines · Namhyung Kim
Quoted 2 lines · David Ahern
Changes top code to use the
perf_record_optsstruct. Stepping stone to consolidating the open counters code.Maybe time to rename
perf_record_optstoperf_open_optsor justperf_opts?
It's still the record time opts. Either way, a rename is for a different patch series.
David
PATCH v2 3/9 perf evlist: introduce open counters method
In reply to David AhernSuperset of the open counters code in perf-top and perf-record - combining retry handling and error handling. Should be functionally equivalent.
--- tools/perf/util/evlist.c | 131 +++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/evlist.h | 3 ++ 2 files changed, 133 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +130 -1
@@ -15,7 +15,7 @@#include "evlist.h" #include "evsel.h" #include <unistd.h> - +#include "debug.h" #include "parse-events.h" #include <sys/mman.h>
@@ -838,3 +838,132 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)return printed +fprintf (fp,"\n" );; } + +int perf_evlist__open_counters (struct perf_evlist *evlist, +struct perf_record_opts *opts) +{ +struct perf_evsel *pos; +int rc =0 ; + +list_for_each_entry (pos, &evlist->entries, node) { +struct perf_event_attr *attr = &pos->attr; + +/* +* Carried over from perf-record: +* Check if parse_single_tracepoint_event has already asked for +* PERF_SAMPLE_TIME. +* +* XXX this is kludgy but short term fix for problems introduced by +* eac23d1c that broke 'perf script' by having different sample_types +* when using multiple tracepoint events when we use a perf binary +* that tries to use sample_id_all on an older kernel. +* +* We need to move counter creation to perf_session, support +* different sample_types, etc. +*/ +bool time_needed = attr->sample_type &PERF_SAMPLE_TIME ; + +fallback_missing_features: +if (opts->exclude_guest_missing) + attr->exclude_guest = attr->exclude_host =0 ; +retry_sample_id: + attr->sample_id_all = opts->sample_id_all_missing ?0 :1 ; +try_again: +if (perf_evsel__open (pos, evlist->cpus, evlist->threads) <0 ) { +int err = errno; + +if (err ==EPERM || err ==EACCES ) { +ui__error_paranoid (); + rc = -err; + goto out; + }else if (err ==ENODEV && opts->target.cpu_list) { +pr_err ("No such device - did you specify" +" an out-of-range profile CPU?\n" ); + rc = -err; + goto out; + }else if (err ==EINVAL ) { +if (!opts->exclude_guest_missing && + (attr->exclude_guest || attr->exclude_host)) { +pr_debug ("Old kernel, cannot exclude " +"guest or host samples.\n" ); + opts->exclude_guest_missing = true; + goto fallback_missing_features; + }else if (!opts->sample_id_all_missing) { +/* +* Old kernel, no attr->sample_id_type_all field +*/ + opts->sample_id_all_missing = true; +if (!opts->sample_time && + !opts->raw_samples && + !time_needed) + attr->sample_type &= ~PERF_SAMPLE_TIME ; + goto retry_sample_id; + } + } + +/* +* If it's cycles then fall back to hrtimer +* based cpu-clock-tick sw counter, which +* is always available even if no PMU support: +* +* PPC returns ENXIO until 2.6.37 (behavior changed +* with commit b0a873e). +*/ +if ((err ==ENOENT || err ==ENXIO ) && + (attr->type ==PERF_TYPE_HARDWARE ) && + (attr->config ==PERF_COUNT_HW_CPU_CYCLES )) { + +if (verbose) +ui__warning ("Cycles event not supported,\n" +"trying to fall back to cpu-clock-ticks\n" ); + + attr->type =PERF_TYPE_SOFTWARE ; + attr->config =PERF_COUNT_SW_CPU_CLOCK ; +if (pos->name) { +free (pos->name); + pos->name =NULL ; + } + goto try_again; + } + +if (err ==ENOENT ) { +ui__error ("The %s event is not supported.\n" , +perf_evsel__name (pos)); + rc = -err; + goto out; + }else if (err ==EMFILE ) { +ui__error ("Too many events are opened.\n" +"Try again after reducing the number of events\n" ); + rc = -err; + goto out; + }else if ((err ==EOPNOTSUPP ) && (attr->precise_ip)) { +ui__error ("\'precise\' request may not be supported. " +"Try removing 'p' modifier\n" ); + goto out; + } + +ui__error ("sys_perf_event_open() syscall returned with " +"%d (%s) for event %s. /bin/dmesg may provide" +"additional information.\n" , + err,strerror (err),perf_evsel__name (pos)); + +#if defined(__i386__) || defined(__x86_64__) +if ((attr->type ==PERF_TYPE_HARDWARE ) && + (err ==EOPNOTSUPP )) { +pr_err ("No hardware sampling interrupt available." +" No APIC? If so then you can boot the kernel" +" with the \"lapic\" boot parameter to" +" force-enable it.\n" ); + rc = -err; + goto out; + } +#endif + +pr_err ("No CONFIG_PERF_EVENTS=y kernel support configured?\n" ); + rc = -err; + goto out; + } + } +out: +return rc; +}
tools/perf/util/evlist.h +3 -0
@@ -135,4 +135,7 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) }size_t perf_evlist__fprintf (struct perf_evlist *evlist,FILE *fp); + +int perf_evlist__open_counters (struct perf_evlist *evlist, +struct perf_record_opts *opts);#endif /* __PERF_EVLIST_H */
Signature · 1 line
1.7.10.1
PATCH v2 4/9 perf top: use the new perf_evlist__open_counters method
In reply to David AhernRemove open counters code with all the retry and error handling in favor of the new perf_evlist__open_counters method which is based on the top code.
--- tools/perf/builtin-top.c | 74 ++-------------------------------------------- 1 file changed, 3 insertions(+), 71 deletions(-)
tools/perf/builtin-top.c +3 -71
@@ -919,79 +919,11 @@ static void perf_top__start_counters(struct perf_top *top) attr->mmap =1 ; attr->comm =1 ; attr->inherit = !top->opts.no_inherit; -fallback_missing_features: -if (top->opts.exclude_guest_missing) - attr->exclude_guest = attr->exclude_host =0 ; -retry_sample_id: - attr->sample_id_all = top->opts.sample_id_all_missing ?0 :1 ; -try_again: -if (perf_evsel__open (counter, top->evlist->cpus, - top->evlist->threads) <0 ) { -int err = errno; - -if (err ==EPERM || err ==EACCES ) { -ui__error_paranoid (); - goto out_err; - }else if (err ==EINVAL ) { -if (!top->opts.exclude_guest_missing && - (attr->exclude_guest || attr->exclude_host)) { -pr_debug ("Old kernel, cannot exclude " -"guest or host samples.\n" ); - top->opts.exclude_guest_missing = true; - goto fallback_missing_features; - }else if (!top->opts.sample_id_all_missing) { -/* -* Old kernel, no attr->sample_id_type_all field -*/ - top->opts.sample_id_all_missing = true; - goto retry_sample_id; - } - } -/* -* If it's cycles then fall back to hrtimer -* based cpu-clock-tick sw counter, which -* is always available even if no PMU support: -*/ -if ((err ==ENOENT || err ==ENXIO ) && - (attr->type ==PERF_TYPE_HARDWARE ) && - (attr->config ==PERF_COUNT_HW_CPU_CYCLES )) { - -if (verbose) -ui__warning ("Cycles event not supported,\n" -"trying to fall back to cpu-clock-ticks\n" ); - - attr->type =PERF_TYPE_SOFTWARE ; - attr->config =PERF_COUNT_SW_CPU_CLOCK ; -if (counter->name) { -free (counter->name); - counter->name =NULL ; - } - goto try_again; - } - -if (err ==ENOENT ) { -ui__error ("The %s event is not supported.\n" , -perf_evsel__name (counter)); - goto out_err; - }else if (err ==EMFILE ) { -ui__error ("Too many events are opened.\n" -"Try again after reducing the number of events\n" ); - goto out_err; - }else if ((err ==EOPNOTSUPP ) && (attr->precise_ip)) { -ui__error ("\'precise\' request may not be supported. " -"Try removing 'p' modifier\n" ); - goto out_err; - } - -ui__error ("The sys_perf_event_open() syscall " -"returned with %d (%s). /bin/dmesg " -"may provide additional information.\n" -"No CONFIG_PERF_EVENTS=y kernel support " -"configured?\n" , err,strerror (err)); - goto out_err; - } } +if (perf_evlist__open_counters (evlist, &top->opts) !=0 ) + goto out_err; +if (perf_evlist__mmap (evlist, top->opts.mmap_pages, false) <0 ) {ui__error ("Failed to mmap with %d (%s)\n" , errno,strerror (errno));
Signature · 1 line
1.7.10.1
PATCH v2 5/9 perf record: use the new perf_evlist__open_counters method
In reply to David AhernRemove open counters code with all the retry and error handling in favor of the new perf_evlist__open_counters method which is based on the existing code.
--- tools/perf/builtin-record.c | 116 ++----------------------------------------- 1 file changed, 3 insertions(+), 113 deletions(-)
tools/perf/builtin-record.c +3 -113
@@ -224,7 +224,6 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,static int perf_record__open (struct perf_record *rec) { -struct perf_evsel *pos;struct perf_evlist *evlist = rec->evlist;struct perf_session *session = rec->session;struct perf_record_opts *opts = &rec->opts;
@@ -235,118 +234,9 @@ static int perf_record__open(struct perf_record *rec)if (opts->group)perf_evlist__set_leader (evlist); -list_for_each_entry (pos, &evlist->entries, node) { -struct perf_event_attr *attr = &pos->attr; -/* -* Check if parse_single_tracepoint_event has already asked for -* PERF_SAMPLE_TIME. -* -* XXX this is kludgy but short term fix for problems introduced by -* eac23d1c that broke 'perf script' by having different sample_types -* when using multiple tracepoint events when we use a perf binary -* that tries to use sample_id_all on an older kernel. -* -* We need to move counter creation to perf_session, support -* different sample_types, etc. -*/ -bool time_needed = attr->sample_type &PERF_SAMPLE_TIME ; - -fallback_missing_features: -if (opts->exclude_guest_missing) - attr->exclude_guest = attr->exclude_host =0 ; -retry_sample_id: - attr->sample_id_all = opts->sample_id_all_missing ?0 :1 ; -try_again: -if (perf_evsel__open (pos, evlist->cpus, evlist->threads) <0 ) { -int err = errno; - -if (err ==EPERM || err ==EACCES ) { -ui__error_paranoid (); - rc = -err; - goto out; - }else if (err ==ENODEV && opts->target.cpu_list) { -pr_err ("No such device - did you specify" -" an out-of-range profile CPU?\n" ); - rc = -err; - goto out; - }else if (err ==EINVAL ) { -if (!opts->exclude_guest_missing && - (attr->exclude_guest || attr->exclude_host)) { -pr_debug ("Old kernel, cannot exclude " -"guest or host samples.\n" ); - opts->exclude_guest_missing = true; - goto fallback_missing_features; - }else if (!opts->sample_id_all_missing) { -/* -* Old kernel, no attr->sample_id_type_all field -*/ - opts->sample_id_all_missing = true; -if (!opts->sample_time && !opts->raw_samples && !time_needed) - attr->sample_type &= ~PERF_SAMPLE_TIME ; - - goto retry_sample_id; - } - } - -/* -* If it's cycles then fall back to hrtimer -* based cpu-clock-tick sw counter, which -* is always available even if no PMU support. -* -* PPC returns ENXIO until 2.6.37 (behavior changed -* with commit b0a873e). -*/ -if ((err ==ENOENT || err ==ENXIO ) - && attr->type ==PERF_TYPE_HARDWARE - && attr->config ==PERF_COUNT_HW_CPU_CYCLES ) { - -if (verbose) -ui__warning ("The cycles event is not supported, " -"trying to fall back to cpu-clock-ticks\n" ); - attr->type =PERF_TYPE_SOFTWARE ; - attr->config =PERF_COUNT_SW_CPU_CLOCK ; -if (pos->name) { -free (pos->name); - pos->name =NULL ; - } - goto try_again; - } - -if (err ==ENOENT ) { -ui__error ("The %s event is not supported.\n" , -perf_evsel__name (pos)); - rc = -err; - goto out; - }else if ((err ==EOPNOTSUPP ) && (attr->precise_ip)) { -ui__error ("\'precise\' request may not be supported. " -"Try removing 'p' modifier\n" ); - rc = -err; - goto out; - } - -printf ("\n" ); -error ("sys_perf_event_open() syscall returned with %d " -"(%s) for event %s. /bin/dmesg may provide " -"additional information.\n" , - err,strerror (err),perf_evsel__name (pos)); - -#if defined(__i386__) || defined(__x86_64__) -if (attr->type ==PERF_TYPE_HARDWARE && - err ==EOPNOTSUPP ) { -pr_err ("No hardware sampling interrupt available." -" No APIC? If so then you can boot the kernel" -" with the \"lapic\" boot parameter to" -" force-enable it.\n" ); - rc = -err; - goto out; - } -#endif - -pr_err ("No CONFIG_PERF_EVENTS=y kernel support configured?\n" ); - rc = -err; - goto out; - } - } + rc =perf_evlist__open_counters (evlist, opts); +if (rc !=0 ) + goto out;if (perf_evlist__apply_filters (evlist)) { error("failed to set filter with %d (%s)\n", errno,
Signature · 1 line
1.7.10.1
PATCH v2 6/9 perf stat: move user options to perf_record_opts
In reply to David AhernThis is required for perf-stat to use perf_evlist__open_counters. And move opts to a stack variable.
--- tools/perf/builtin-stat.c | 167 +++++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 66 deletions(-)
tools/perf/builtin-stat.c +101 -66
@@ -67,12 +67,8 @@static struct perf_evlist *evsel_list; -static struct perf_target target = { - .uid =UINT_MAX , -};static int run_count =1 ; -static bool no_inherit = false;static bool scale = true;static bool no_aggr = false;static pid_t child_pid =-1 ;
@@ -82,7 +78,6 @@ static bool big_num = true;static int big_num_opt =-1 ;static const char *csv_sep =NULL ;static bool csv_output = false; -static bool group = false;static FILE *output =NULL ;static const char *pre_cmd =NULL ;static const char *post_cmd =NULL ;
@@ -106,14 +101,16 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) evsel->priv =NULL ; } -static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel) +static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel, +struct perf_target *target) { -return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; +return (evsel->cpus && !target->cpu_list) ? evsel->cpus : evsel_list->cpus; } -static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel) +static inline int perf_evsel__nr_cpus (struct perf_evsel *evsel, +struct perf_target *target) { -return perf_evsel__cpus (evsel)->nr; +return perf_evsel__cpus (evsel, target)->nr; }static struct stats runtime_nsecs_stats[MAX_NR_CPUS ];
@@ -130,8 +127,10 @@ static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];static struct stats walltime_nsecs_stats;static int create_perf_stat_counter (struct perf_evsel *evsel, -struct perf_evsel *first) +struct perf_evsel *first, +struct perf_record_opts *opts) { +struct perf_target *target = &opts->target;struct perf_event_attr *attr = &evsel->attr;bool exclude_guest_missing = false;int ret;
@@ -140,20 +139,22 @@ static int create_perf_stat_counter(struct perf_evsel *evsel, attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED |PERF_FORMAT_TOTAL_TIME_RUNNING ; - attr->inherit = !no_inherit; + attr->inherit = !opts->no_inherit; retry:if (exclude_guest_missing) evsel->attr.exclude_guest = evsel->attr.exclude_host =0 ; -if (perf_target__has_cpu (&target)) { - ret =perf_evsel__open_per_cpu (evsel,perf_evsel__cpus (evsel)); +if (perf_target__has_cpu (target)) { + ret =perf_evsel__open_per_cpu (evsel, +perf_evsel__cpus (evsel, target));if (ret) goto check_ret;return 0 ; } -if (!perf_target__has_task (&target) && (!group || evsel == first)) { +if (!perf_target__has_task (target) && + (!opts->group || evsel == first)) { attr->disabled =1 ; attr->enable_on_exec =1 ; }
@@ -222,13 +223,15 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)* Read out the results of a single counter: * aggregate counts across CPUs in system-wide mode */ -static int read_counter_aggr (struct perf_evsel *counter) +static int read_counter_aggr (struct perf_evsel *counter, +struct perf_record_opts *opts) { +struct perf_target *target = &opts->target;struct perf_stat *ps = counter->priv;u64 *count = counter->counts->aggr.values;int i; -if (__perf_evsel__read (counter,perf_evsel__nr_cpus (counter), +if (__perf_evsel__read (counter,perf_evsel__nr_cpus (counter, target), evsel_list->threads->nr, scale) <0 )return -1 ;
@@ -252,12 +255,14 @@ static int read_counter_aggr(struct perf_evsel *counter)* Read out the results of a single counter: * do not aggregate counts across CPUs in system-wide mode */ -static int read_counter (struct perf_evsel *counter) +static int read_counter (struct perf_evsel *counter, +struct perf_record_opts *opts) { +struct cpu_map *cmap =perf_evsel__cpus (counter, &opts->target);u64 *count;int cpu; -for (cpu =0 ; cpu <perf_evsel__nr_cpus (counter); cpu++) { +for (cpu =0 ; cpu < cmap->nr; cpu++) {if (__perf_evsel__read_on_cpu (counter, cpu,0 , scale) <0 )return -1 ;
@@ -269,10 +274,13 @@ static int read_counter(struct perf_evsel *counter)return 0 ; } -static int __run_perf_stat (int argc__maybe_unused ,const char **argv) +static int __run_perf_stat (int argc__maybe_unused , +const char **argv, +struct perf_record_opts *opts) {unsigned long long t0, t1;struct perf_evsel *counter, *first; +struct cpu_map *cmap;int status =0 ;int child_ready_pipe[2 ], go_pipe[2 ];const bool forks = (argc >0 );
@@ -316,7 +324,7 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)exit (-1 ); } -if (perf_target__none (&target)) +if (perf_target__none (&opts->target)) evsel_list->threads->map[0 ] = child_pid;/*
@@ -329,13 +337,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)close (child_ready_pipe[0 ]); } -if (group) +if (opts->group)perf_evlist__set_leader (evsel_list); first =perf_evlist__first (evsel_list);list_for_each_entry (counter, &evsel_list->entries, node) { -if (create_perf_stat_counter (counter, first) <0 ) { +if (create_perf_stat_counter (counter, first, opts) <0 ) {/* * PPC returns ENXIO for HW counters until 2.6.37 * (behavior changed with commit b0a873e).
@@ -354,7 +362,7 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)error ("You may not have permission to collect %sstats.\n" "\t Consider tweaking" " /proc/sys/kernel/perf_event_paranoid or running as root." , - target.system_wide ?"system-wide " :"" ); + opts->target.system_wide ?"system-wide " :"" ); }else { error("open_counter returned with %d (%s). " "/bin/dmesg may provide additional information.\n",
@@ -395,13 +403,15 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)if (no_aggr) {list_for_each_entry (counter, &evsel_list->entries, node) { -read_counter (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter),1 ); + cmap =perf_evsel__cpus (counter, &opts->target); +read_counter (counter, opts); +perf_evsel__close_fd (counter, cmap->nr,1 ); } }else {list_for_each_entry (counter, &evsel_list->entries, node) { -read_counter_aggr (counter); -perf_evsel__close_fd (counter,perf_evsel__nr_cpus (counter), + cmap =perf_evsel__cpus (counter, &opts->target); +read_counter_aggr (counter, opts); +perf_evsel__close_fd (counter, cmap->nr, evsel_list->threads->nr); } }
@@ -409,7 +419,9 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)return WEXITSTATUS (status); } -static int run_perf_stat (int argc__maybe_unused ,const char **argv) +static int run_perf_stat (int argc__maybe_unused , +const char **argv, +struct perf_record_opts *opts) {int ret;
@@ -422,7 +434,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)if (sync_run)sync (); - ret =__run_perf_stat (argc, argv); + ret =__run_perf_stat (argc, argv, opts);if (ret)return ret;
@@ -456,16 +468,20 @@ static void print_noise(struct perf_evsel *evsel, double avg)print_noise_pct (stddev_stats (&ps->res_stats[0 ]), avg); } -static void nsec_printout (int cpu,struct perf_evsel *evsel,double avg) +static void nsec_printout (int cpu,struct perf_evsel *evsel, +double avg,struct perf_record_opts *opts) {double msecs = avg /1e6 ;char cpustr[16 ] = {'\0' , };const char *fmt = csv_output ?"%s%.6f%s%s" :"%s%18.6f%s%-25s" ; +struct cpu_map *cmap; -if (no_aggr) +if (no_aggr) { + cmap =perf_evsel__cpus (evsel, &opts->target);sprintf (cpustr,"CPU%*d%s" , csv_output ?0 :-4 , -perf_evsel__cpus (evsel)->map[cpu], csv_sep); + cmap->map[cpu], csv_sep); + }fprintf (output, fmt, cpustr, msecs, csv_sep,perf_evsel__name (evsel));
@@ -661,11 +677,13 @@ static void print_ll_cache_misses(int cpu,fprintf (output," of all LL-cache hits " ); } -static void abs_printout (int cpu,struct perf_evsel *evsel,double avg) +static void abs_printout (int cpu,struct perf_evsel *evsel, +double avg,struct perf_record_opts *opts) {double total, ratio =0.0 ;char cpustr[16 ] = {'\0' , };const char *fmt; +struct cpu_map *cmap;if (csv_output) fmt ="%s%.0f%s%s" ;
@@ -674,11 +692,12 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)else fmt ="%s%18.0f%s%-25s" ; -if (no_aggr) +if (no_aggr) { + cmap =perf_evsel__cpus (evsel, &opts->target);sprintf (cpustr,"CPU%*d%s" , csv_output ?0 :-4 , -perf_evsel__cpus (evsel)->map[cpu], csv_sep); -else + cmap->map[cpu], csv_sep); + }else cpu =0 ;fprintf (output, fmt, cpustr, avg, csv_sep,perf_evsel__name (evsel));
@@ -785,7 +804,8 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)* Print out the results of a single counter: * aggregated counts in system-wide mode */ -static void print_counter_aggr (struct perf_evsel *counter) +static void print_counter_aggr (struct perf_evsel *counter, +struct perf_record_opts *opts) {struct perf_stat *ps = counter->priv;double avg =avg_stats (&ps->res_stats[0 ]);
@@ -807,9 +827,9 @@ static void print_counter_aggr(struct perf_evsel *counter) }if (nsec_counter (counter)) -nsec_printout (-1 , counter, avg); +nsec_printout (-1 , counter, avg, opts);else -abs_printout (-1 , counter, avg); +abs_printout (-1 , counter, avg, opts);print_noise (counter, avg);
@@ -833,19 +853,21 @@ static void print_counter_aggr(struct perf_evsel *counter)* Print out the results of a single counter: * does not use aggregated count in system-wide */ -static void print_counter (struct perf_evsel *counter) +static void print_counter (struct perf_evsel *counter, +struct perf_record_opts *opts) { +struct cpu_map *cmap =perf_evsel__cpus (counter, &opts->target);u64 ena, run, val;int cpu; -for (cpu =0 ; cpu <perf_evsel__nr_cpus (counter); cpu++) { +for (cpu =0 ; cpu < cmap->nr; cpu++) { val = counter->counts->cpu[cpu].val; ena = counter->counts->cpu[cpu].ena; run = counter->counts->cpu[cpu].run;if (run ==0 || ena ==0 ) { fprintf(output, "CPU%*d%s%*s%s%*s", csv_output ? 0 : -4, - perf_evsel__cpus(counter)->map[cpu], csv_sep, + cmap->map[cpu], csv_sep, csv_output ? 0 : 18, counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, csv_sep,
@@ -861,9 +883,9 @@ static void print_counter(struct perf_evsel *counter) }if (nsec_counter (counter)) -nsec_printout (cpu, counter, val); +nsec_printout (cpu, counter, val, opts);else -abs_printout (cpu, counter, val); +abs_printout (cpu, counter, val, opts);if (!csv_output) {print_noise (counter,1.0 );
@@ -876,9 +898,11 @@ static void print_counter(struct perf_evsel *counter) } } -static void print_stat (int argc,const char **argv) +static void print_stat (int argc,const char **argv, +struct perf_record_opts *opts) {struct perf_evsel *counter; +struct perf_target *target = &opts->target;int i;fflush (stdout);
@@ -886,14 +910,14 @@ static void print_stat(int argc, const char **argv)if (!csv_output) {fprintf (output,"\n" );fprintf (output," Performance counter stats for " ); -if (!perf_target__has_task (&target)) { +if (!perf_target__has_task (target)) {fprintf (output,"\'%s" , argv[0 ]);for (i =1 ; i < argc; i++)fprintf (output," %s" , argv[i]); - }else if (target.pid) -fprintf (output,"process id \'%s" , target.pid); + }else if (target->pid) +fprintf (output,"process id \'%s" , target->pid);else -fprintf (output,"thread id \'%s" , target.tid); +fprintf (output,"thread id \'%s" , target->tid);fprintf (output,"\'" );if (run_count >1 )
@@ -903,10 +927,10 @@ static void print_stat(int argc, const char **argv)if (no_aggr) {list_for_each_entry (counter, &evsel_list->entries, node) -print_counter (counter); +print_counter (counter, opts); }else {list_for_each_entry (counter, &evsel_list->entries, node) -print_counter_aggr (counter); +print_counter_aggr (counter, opts); }if (!csv_output) {
@@ -1102,21 +1126,31 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)bool append_file = false;int output_fd =0 ;const char *output_name =NULL ; + +struct perf_record_opts opts = { + .target = { + .uid =UINT_MAX , + }, + .no_inherit = false, + .group = false, + }; +struct perf_target *target = &opts.target; +const struct option options[] = {OPT_CALLBACK ('e' ,"event" , &evsel_list,"event" ,"event selector. use 'perf list' to list available events" , parse_events_option),OPT_CALLBACK (0 ,"filter" , &evsel_list,"filter" ,"event filter" , parse_filter), -OPT_BOOLEAN ('i' ,"no-inherit" , &no_inherit, +OPT_BOOLEAN ('i' ,"no-inherit" , &opts.no_inherit,"child tasks do not inherit counters" ), -OPT_STRING ('p' ,"pid" , &target.pid,"pid" , +OPT_STRING ('p' ,"pid" , &target->pid,"pid" ,"stat events on existing process id" ), -OPT_STRING ('t' ,"tid" , &target.tid,"tid" , +OPT_STRING ('t' ,"tid" , &target->tid,"tid" ,"stat events on existing thread id" ), -OPT_BOOLEAN ('a' ,"all-cpus" , &target.system_wide, +OPT_BOOLEAN ('a' ,"all-cpus" , &target->system_wide,"system-wide collection from all CPUs" ), -OPT_BOOLEAN ('g' ,"group" , &group, +OPT_BOOLEAN ('g' ,"group" , &opts.group,"put the counters into a counter group" ),OPT_BOOLEAN ('c' ,"scale" , &scale,"scale/normalize counters" ), OPT_INCR('v', "verbose", &verbose,
@@ -1132,7 +1166,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)OPT_CALLBACK_NOOPT ('B' ,"big-num" ,NULL ,NULL ,"print large numbers with thousands\' separators" , stat__set_big_num), -OPT_STRING ('C' ,"cpu" , &target.cpu_list,"cpu" , +OPT_STRING ('C' ,"cpu" , &target->cpu_list,"cpu" ,"list of cpus to monitor in system-wide" ),OPT_BOOLEAN ('A' ,"no-aggr" , &no_aggr,"disable CPU count aggregation" ), OPT_STRING('x', "field-separator", &csv_sep, "separator",
@@ -1220,13 +1254,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) }else if (big_num_opt ==0 )/* User passed --no-big-num */ big_num = false; -if (!argc && !perf_target__has_task (&target)) +if (!argc && !perf_target__has_task (target))usage_with_options (stat_usage, options);if (run_count <=0 )usage_with_options (stat_usage, options);/* no_aggr, cgroup are for system-wide only */ -if ((no_aggr || nr_cgroups) && !perf_target__has_cpu (&target)) { +if ((no_aggr || nr_cgroups) && !perf_target__has_cpu (target)) {fprintf (stderr,"both cgroup and no-aggregation " "modes only available in system-wide mode\n" );
@@ -1236,12 +1270,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)if (add_default_attributes ()) goto out; -perf_target__validate (&target); +perf_target__validate (target); -if (perf_evlist__create_maps (evsel_list, &target) <0 ) { -if (perf_target__has_task (&target)) +if (perf_evlist__create_maps (evsel_list, target) <0 ) { +if (perf_target__has_task (target))pr_err ("Problems finding threads of monitor\n" ); -if (perf_target__has_cpu (&target)) +if (perf_target__has_cpu (target))perror ("failed to parse CPUs map" );usage_with_options (stat_usage, options);
@@ -1249,8 +1283,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) }list_for_each_entry (pos, &evsel_list->entries, node) { +struct cpu_map *cmap =perf_evsel__cpus (pos, target);if (perf_evsel__alloc_stat_priv (pos) <0 || -perf_evsel__alloc_counts (pos,perf_evsel__nr_cpus (pos)) <0 ) +perf_evsel__alloc_counts (pos, cmap->nr) <0 ) goto out_free_fd; }
@@ -1271,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)fprintf (output,"[ perf stat: executing run #%d ... ]\n" , run_idx +1 ); - status =run_perf_stat (argc, argv); + status =run_perf_stat (argc, argv, &opts); }if (status !=-1 ) -print_stat (argc, argv); +print_stat (argc, argv, &opts); out_free_fd:list_for_each_entry (pos, &evsel_list->entries, node)perf_evsel__free_stat_priv (pos);
Signature · 1 line
1.7.10.1
PATCH v2 7/9 perf evlist: add stat unique code to open_counters method
In reply to David Ahernperf-stat continues on some open failures. top and record opt out to maintain existing behavior.
--- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/evlist.c | 16 ++++++++++++++-- tools/perf/util/evlist.h | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-)
tools/perf/builtin-record.c +1 -1
@@ -234,7 +234,7 @@ static int perf_record__open(struct perf_record *rec)if (opts->group)perf_evlist__set_leader (evlist); - rc =perf_evlist__open_counters (evlist, opts); + rc =perf_evlist__open_counters (evlist, opts, false);if (rc !=0 ) goto out;
tools/perf/builtin-top.c +1 -1
@@ -921,7 +921,7 @@ static void perf_top__start_counters(struct perf_top *top) attr->inherit = !top->opts.no_inherit; } -if (perf_evlist__open_counters (evlist, &top->opts) !=0 ) +if (perf_evlist__open_counters (evlist, &top->opts, false) !=0 ) goto out_err;if (perf_evlist__mmap (evlist, top->opts.mmap_pages, false) <0 ) {
tools/perf/util/evlist.c +14 -2
@@ -840,7 +840,8 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) }int perf_evlist__open_counters (struct perf_evlist *evlist, -struct perf_record_opts *opts) +struct perf_record_opts *opts, +bool continue_on_fail) {struct perf_evsel *pos;int rc =0 ;
@@ -872,6 +873,16 @@ try_again:if (perf_evsel__open (pos, evlist->cpus, evlist->threads) <0 ) {int err = errno; +if (continue_on_fail && + (err ==EINVAL || err ==ENOSYS || err ==ENXIO || + err ==ENOENT || err ==EOPNOTSUPP )) { +if (verbose) +ui__warning ("%s event is not supported by the kernel.\n" , +perf_evsel__name (pos)); + pos->supported = false; +continue ; + } +if (err ==EPERM || err ==EACCES ) {ui__error_paranoid (); rc = -err;
@@ -962,7 +973,8 @@ try_again:pr_err ("No CONFIG_PERF_EVENTS=y kernel support configured?\n" ); rc = -err; goto out; - } + }else + pos->supported = true; } out:return rc;
tools/perf/util/evlist.h +2 -1
@@ -137,5 +137,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)size_t perf_evlist__fprintf (struct perf_evlist *evlist,FILE *fp);int perf_evlist__open_counters (struct perf_evlist *evlist, -struct perf_record_opts *opts); +struct perf_record_opts *opts, +bool continue_on_fail);#endif /* __PERF_EVLIST_H */
Signature · 1 line
1.7.10.1
PATCH v2 8/9 perf stat: move to perf_evlist__open_counters
In reply to David AhernRemoves a lot of duplicated code moving to the common open method.
--- tools/perf/builtin-stat.c | 103 ++++++++++----------------------------------- 1 file changed, 22 insertions(+), 81 deletions(-)
tools/perf/builtin-stat.c +22 -81
@@ -126,55 +126,6 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS ];static struct stats walltime_nsecs_stats; -static int create_perf_stat_counter (struct perf_evsel *evsel, -struct perf_evsel *first, -struct perf_record_opts *opts) -{ -struct perf_target *target = &opts->target; -struct perf_event_attr *attr = &evsel->attr; -bool exclude_guest_missing = false; -int ret; - -if (scale) - attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED | -PERF_FORMAT_TOTAL_TIME_RUNNING ; - - attr->inherit = !opts->no_inherit; - -retry: -if (exclude_guest_missing) - evsel->attr.exclude_guest = evsel->attr.exclude_host =0 ; - -if (perf_target__has_cpu (target)) { - ret =perf_evsel__open_per_cpu (evsel, -perf_evsel__cpus (evsel, target)); -if (ret) - goto check_ret; -return 0 ; - } - -if (!perf_target__has_task (target) && - (!opts->group || evsel == first)) { - attr->disabled =1 ; - attr->enable_on_exec =1 ; - } - - ret =perf_evsel__open_per_thread (evsel, evsel_list->threads); -if (!ret) -return 0 ; -/* fall through */ -check_ret: -if (ret && errno ==EINVAL ) { -if (!exclude_guest_missing && - (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { -pr_debug ("Old kernel, cannot exclude " -"guest or host samples.\n" ); - exclude_guest_missing = true; - goto retry; - } - } -return ret; -}/* * Does the counter have nsecs as a unit?
@@ -281,6 +232,7 @@ static int __run_perf_stat(int argc __maybe_unused,unsigned long long t0, t1;struct perf_evsel *counter, *first;struct cpu_map *cmap; +struct perf_target *target = &opts->target;int status =0 ;int child_ready_pipe[2 ], go_pipe[2 ];const bool forks = (argc >0 );
@@ -324,7 +276,7 @@ static int __run_perf_stat(int argc __maybe_unused,exit (-1 ); } -if (perf_target__none (&opts->target)) +if (perf_target__none (target)) evsel_list->threads->map[0 ] = child_pid;/*
@@ -343,38 +295,27 @@ static int __run_perf_stat(int argc __maybe_unused, first =perf_evlist__first (evsel_list);list_for_each_entry (counter, &evsel_list->entries, node) { -if (create_perf_stat_counter (counter, first, opts) <0 ) { -/* -* PPC returns ENXIO for HW counters until 2.6.37 -* (behavior changed with commit b0a873e). -*/ -if (errno ==EINVAL || errno ==ENOSYS || - errno ==ENOENT || errno ==EOPNOTSUPP || - errno ==ENXIO ) { -if (verbose) -ui__warning ("%s event is not supported by the kernel.\n" , -perf_evsel__name (counter)); - counter->supported = false; -continue ; - } - -if (errno ==EPERM || errno ==EACCES ) { -error ("You may not have permission to collect %sstats.\n" -"\t Consider tweaking" -" /proc/sys/kernel/perf_event_paranoid or running as root." , - opts->target.system_wide ?"system-wide " :"" ); - }else { -error ("open_counter returned with %d (%s). " -"/bin/dmesg may provide additional information.\n" , - errno,strerror (errno)); - } -if (child_pid !=-1 ) -kill (child_pid,SIGTERM ); - -pr_err ("Not all events could be opened.\n" ); -return -1 ; +struct perf_event_attr *attr = &counter->attr; + +if (scale) + attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED | +PERF_FORMAT_TOTAL_TIME_RUNNING ; + + attr->inherit = !opts->no_inherit; + +if (perf_target__none (target) && + (!opts->group || counter == first)) { + attr->disabled =1 ; + attr->enable_on_exec =1 ; } - counter->supported = true; + } + +if (perf_evlist__open_counters (evsel_list, opts, true) !=0 ) { +if (child_pid !=-1 ) +kill (child_pid,SIGTERM ); + +pr_err ("Not all events could be opened.\n" ); +return -1 ; }if (perf_evlist__apply_filters (evsel_list)) {
Signature · 1 line
1.7.10.1
PATCH v2 9/9 perf evsel: remove perf_evsel__open_per_cpu
In reply to David AhernNo longer needed with perf-stat converted to perf_evlist__open_counters.
--- tools/perf/util/evsel.c | 6 ------ tools/perf/util/evsel.h | 2 -- 2 files changed, 8 deletions(-)
tools/perf/util/evsel.c +0 -6
@@ -774,12 +774,6 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,return __perf_evsel__open (evsel, cpus, threads); } -int perf_evsel__open_per_cpu (struct perf_evsel *evsel, -struct cpu_map *cpus) -{ -return __perf_evsel__open (evsel, cpus, &empty_thread_map.map); -} -int perf_evsel__open_per_thread (struct perf_evsel *evsel,struct thread_map *threads) {
tools/perf/util/evsel.h +0 -2
@@ -121,8 +121,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);int perf_evsel__set_filter (struct perf_evsel *evsel,int ncpus,int nthreads,const char *filter); -int perf_evsel__open_per_cpu (struct perf_evsel *evsel, -struct cpu_map *cpus);int perf_evsel__open_per_thread (struct perf_evsel *evsel,struct thread_map *threads); int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
Signature · 1 line
1.7.10.1