All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] perf: consolidate all the open counters loops
@ 2012-10-11  4:25 David Ahern
  2012-10-11  4:25 ` [PATCH 1/9] perf python: add ui stubs file David Ahern
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

ACME was a litle slow today (ACME Component Mgmt Env that is) so managed
to add perf-stat to the list and do a decent amount of testing. This
consolidates all of the open counters loops into a single common one.

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        |  109 +---------------
 tools/perf/builtin-stat.c          |  240 ++++++++++++++++--------------------
 tools/perf/builtin-top.c           |  142 ++++++---------------
 tools/perf/util/evlist.c           |  139 ++++++++++++++++++++-
 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/top.c              |   20 +--
 tools/perf/util/top.h              |    9 +-
 10 files changed, 303 insertions(+), 369 deletions(-)

-- 
1.7.10.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/9] perf python: add ui stubs file
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 2/9] perf top: make use of perf_record_opts David Ahern
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

stderr based implementations of ui_xxxx functions for the python
library. Needed for patch 3 - consolidating open counters method.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/python-ext-sources |    1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 2133628..8a45370 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -19,3 +19,4 @@ util/debugfs.c
 util/rblist.c
 util/strlist.c
 ../../lib/rbtree.c
+util/ui_stubs.c
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/9] perf top: make use of perf_record_opts
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
  2012-10-11  4:25 ` [PATCH 1/9] perf python: add ui stubs file David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 3/9] perf evlist: introduce open counters method David Ahern
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Changes top code to use the perf_record_opts struct. Stepping stone to
consolidating the open counters code.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 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(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fb9da71..33c3825 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -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;
 				}
 			}
@@ -988,7 +988,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;
@@ -1034,7 +1034,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);
@@ -1168,11 +1168,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";
@@ -1180,21 +1182,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,
@@ -1203,15 +1205,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"),
@@ -1243,7 +1245,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[] = {
@@ -1273,27 +1275,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 &&
@@ -1310,10 +1312,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);
@@ -1324,7 +1326,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);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 884dde9..deea8fd 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -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)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 86ff1b1..9728740 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 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;
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/9] perf evlist: introduce open counters method
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
  2012-10-11  4:25 ` [PATCH 1/9] perf python: add ui stubs file David Ahern
  2012-10-11  4:25 ` [PATCH 2/9] perf top: make use of perf_record_opts David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 4/9] perf top: use the new perf_evlist__open_counters method David Ahern
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Superset of the open counters code in perf-top and perf-record -
combining retry handling and error handling. Should be functionally
equivalent.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evlist.c |  127 +++++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/evlist.h |    3 ++
 2 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a41dc4a..bce2f58 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -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,128 @@ 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;
+			}
+
+			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;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 56003f7..270e546 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -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 */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/9] perf top: use the new perf_evlist__open_counters method
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (2 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 3/9] perf evlist: introduce open counters method David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 5/9] perf record: " David Ahern
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Remove 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.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/builtin-top.c |   70 ++--------------------------------------------
 1 file changed, 3 insertions(+), 67 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 33c3825..2ffc32e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -919,75 +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;
-			}
-
-			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));
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/9] perf record: use the new perf_evlist__open_counters method
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (3 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 4/9] perf top: use the new perf_evlist__open_counters method David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 6/9] perf stat: move user options to perf_record_opts David Ahern
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Remove 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.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/builtin-record.c |  109 +------------------------------------------
 1 file changed, 2 insertions(+), 107 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 73b5d7f..b9dcc01 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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,113 +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;
-			}
-
-			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;
+	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,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/9] perf stat: move user options to perf_record_opts
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (4 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 5/9] perf record: " David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 7/9] perf evlist: add stat unique code to open_counters method David Ahern
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

This is required for perf-stat to use perf_evlist__open_counters.
And move opts to a stack variable.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/builtin-stat.c |  161 +++++++++++++++++++++++++++------------------
 1 file changed, 97 insertions(+), 64 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 93b9011..9727d217 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -66,12 +66,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;
@@ -81,7 +77,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 volatile int done = 0;
@@ -102,14 +97,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];
@@ -126,8 +123,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;
@@ -136,20 +135,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;
 	}
@@ -218,13 +219,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;
 
@@ -248,12 +251,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;
 
@@ -265,10 +270,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);
@@ -312,7 +320,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;
 
 		/*
@@ -325,13 +333,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).
@@ -350,7 +358,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",
@@ -391,13 +399,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);
 		}
 	}
@@ -426,16 +436,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));
 
@@ -631,11 +645,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";
@@ -644,11 +660,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));
@@ -755,7 +772,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]);
@@ -777,9 +795,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);
 
@@ -803,19 +821,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,
@@ -831,9 +851,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);
@@ -846,9 +866,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);
@@ -856,14 +878,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)
@@ -873,10 +895,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) {
@@ -1073,21 +1095,31 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	     sync_run = 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,
@@ -1103,7 +1135,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",
@@ -1187,13 +1219,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");
 
@@ -1203,12 +1235,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);
@@ -1216,8 +1248,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;
 	}
 
@@ -1241,11 +1274,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		if (sync_run)
 			sync();
 
-		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);
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/9] perf evlist: add stat unique code to open_counters method
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (5 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 6/9] perf stat: move user options to perf_record_opts David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 8/9] perf stat: move to perf_evlist__open_counters David Ahern
  2012-10-11  4:25 ` [PATCH 9/9] perf evsel: remove perf_evsel__open_per_cpu David Ahern
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Mainly the addition is an argument to keep going for some open
failures.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 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(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b9dcc01..663ccc8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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;
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 2ffc32e..2c3b3c7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -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) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bce2f58..fa0daac 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -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;
@@ -958,7 +969,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;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 270e546..0747b6f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -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 */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 8/9] perf stat: move to perf_evlist__open_counters
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (6 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 7/9] perf evlist: add stat unique code to open_counters method David Ahern
@ 2012-10-11  4:25 ` David Ahern
  2012-10-11  4:25 ` [PATCH 9/9] perf evsel: remove perf_evsel__open_per_cpu David Ahern
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Removes a lot of duplicated code moving to the common
open method.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/builtin-stat.c |  103 ++++++++++-----------------------------------
 1 file changed, 22 insertions(+), 81 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 9727d217..affbada 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -122,55 +122,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?
@@ -277,6 +228,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);
@@ -320,7 +272,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;
 
 		/*
@@ -339,38 +291,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)) {
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 9/9] perf evsel: remove perf_evsel__open_per_cpu
  2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
                   ` (7 preceding siblings ...)
  2012-10-11  4:25 ` [PATCH 8/9] perf stat: move to perf_evlist__open_counters David Ahern
@ 2012-10-11  4:25 ` David Ahern
  8 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-11  4:25 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

No longer needed with perf-stat converted to perf_evlist__open_counters.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evsel.c |    6 ------
 tools/perf/util/evsel.h |    2 --
 2 files changed, 8 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ffdd94e..ab3d1c8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -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)
 {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3ead0d5..bf32de4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -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,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/9] perf evlist: introduce open counters method
  2012-10-29 16:31 [PATCH 0/9 v2] perf: consolidate all the open counters loops David Ahern
@ 2012-10-29 16:31 ` David Ahern
  0 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2012-10-29 16:31 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Superset of the open counters code in perf-top and perf-record -
combining retry handling and error handling. Should be functionally
equivalent.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evlist.c |  131 +++++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/evlist.h |    3 ++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a41dc4a..b24ebc1 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -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;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 56003f7..270e546 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -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 */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2012-10-29 16:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-11  4:25 [PATCH 0/9] perf: consolidate all the open counters loops David Ahern
2012-10-11  4:25 ` [PATCH 1/9] perf python: add ui stubs file David Ahern
2012-10-11  4:25 ` [PATCH 2/9] perf top: make use of perf_record_opts David Ahern
2012-10-11  4:25 ` [PATCH 3/9] perf evlist: introduce open counters method David Ahern
2012-10-11  4:25 ` [PATCH 4/9] perf top: use the new perf_evlist__open_counters method David Ahern
2012-10-11  4:25 ` [PATCH 5/9] perf record: " David Ahern
2012-10-11  4:25 ` [PATCH 6/9] perf stat: move user options to perf_record_opts David Ahern
2012-10-11  4:25 ` [PATCH 7/9] perf evlist: add stat unique code to open_counters method David Ahern
2012-10-11  4:25 ` [PATCH 8/9] perf stat: move to perf_evlist__open_counters David Ahern
2012-10-11  4:25 ` [PATCH 9/9] perf evsel: remove perf_evsel__open_per_cpu David Ahern
  -- strict thread matches above, loose matches on Subject: below --
2012-10-29 16:31 [PATCH 0/9 v2] perf: consolidate all the open counters loops David Ahern
2012-10-29 16:31 ` [PATCH 3/9] perf evlist: introduce open counters method David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.