xref: /openbmc/linux/tools/perf/builtin-stat.c (revision 11ba2b85)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-stat.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin stat command: Give a precise performance counters summary
586470930SIngo Molnar  * overview about any workload, CPU or specific PID.
686470930SIngo Molnar  *
786470930SIngo Molnar  * Sample output:
886470930SIngo Molnar 
986470930SIngo Molnar    $ perf stat ~/hackbench 10
1086470930SIngo Molnar    Time: 0.104
1186470930SIngo Molnar 
1286470930SIngo Molnar     Performance counter stats for '/home/mingo/hackbench':
1386470930SIngo Molnar 
1486470930SIngo Molnar        1255.538611  task clock ticks     #      10.143 CPU utilization factor
1586470930SIngo Molnar              54011  context switches     #       0.043 M/sec
1686470930SIngo Molnar                385  CPU migrations       #       0.000 M/sec
1786470930SIngo Molnar              17755  pagefaults           #       0.014 M/sec
1886470930SIngo Molnar         3808323185  CPU cycles           #    3033.219 M/sec
1986470930SIngo Molnar         1575111190  instructions         #    1254.530 M/sec
2086470930SIngo Molnar           17367895  cache references     #      13.833 M/sec
2186470930SIngo Molnar            7674421  cache misses         #       6.112 M/sec
2286470930SIngo Molnar 
2386470930SIngo Molnar     Wall-clock time elapsed:   123.786620 msecs
2486470930SIngo Molnar 
2586470930SIngo Molnar  *
2686470930SIngo Molnar  * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
2786470930SIngo Molnar  *
2886470930SIngo Molnar  * Improvements and fixes by:
2986470930SIngo Molnar  *
3086470930SIngo Molnar  *   Arjan van de Ven <arjan@linux.intel.com>
3186470930SIngo Molnar  *   Yanmin Zhang <yanmin.zhang@intel.com>
3286470930SIngo Molnar  *   Wu Fengguang <fengguang.wu@intel.com>
3386470930SIngo Molnar  *   Mike Galbraith <efault@gmx.de>
3486470930SIngo Molnar  *   Paul Mackerras <paulus@samba.org>
356e750a8fSJaswinder Singh Rajput  *   Jaswinder Singh Rajput <jaswinder@kernel.org>
3686470930SIngo Molnar  *
3786470930SIngo Molnar  * Released under the GPL v2. (and only v2, not any later version)
3886470930SIngo Molnar  */
3986470930SIngo Molnar 
4086470930SIngo Molnar #include "perf.h"
4186470930SIngo Molnar #include "builtin.h"
4286470930SIngo Molnar #include "util/util.h"
4386470930SIngo Molnar #include "util/parse-options.h"
4486470930SIngo Molnar #include "util/parse-events.h"
458f28827aSFrederic Weisbecker #include "util/event.h"
46361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
4769aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
488f28827aSFrederic Weisbecker #include "util/debug.h"
4960666c63SLiming Wang #include "util/header.h"
50a12b51c4SPaul Mackerras #include "util/cpumap.h"
51d6d901c2SZhang, Yanmin #include "util/thread.h"
52fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
5386470930SIngo Molnar 
5486470930SIngo Molnar #include <sys/prctl.h>
5542202dd5SIngo Molnar #include <math.h>
565af52b51SStephane Eranian #include <locale.h>
5786470930SIngo Molnar 
58d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR	" "
59d7470b6aSStephane Eranian 
60cdd6c482SIngo Molnar static struct perf_event_attr default_attrs[] = {
6186470930SIngo Molnar 
62f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
63f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
64f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
65f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},
6686470930SIngo Molnar 
67f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
68f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
6912133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
7012133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
71dd86e72aSIngo Molnar   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES	},
72dd86e72aSIngo Molnar   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES		},
73f4dbfa8fSPeter Zijlstra 
7486470930SIngo Molnar };
7586470930SIngo Molnar 
76361c99a6SArnaldo Carvalho de Melo struct perf_evlist		*evsel_list;
77361c99a6SArnaldo Carvalho de Melo 
78c0555642SIan Munsie static bool			system_wide			=  false;
7942202dd5SIngo Molnar static int			run_idx				=  0;
8042202dd5SIngo Molnar 
813d632595SJaswinder Singh Rajput static int			run_count			=  1;
822e6cdf99SStephane Eranian static bool			no_inherit			= false;
83c0555642SIan Munsie static bool			scale				=  true;
84f5b4a9c3SStephane Eranian static bool			no_aggr				= false;
85933da83aSChris Wilson static pid_t			target_pid			= -1;
86d6d901c2SZhang, Yanmin static pid_t			target_tid			= -1;
87933da83aSChris Wilson static pid_t			child_pid			= -1;
88c0555642SIan Munsie static bool			null_run			=  false;
89201e0b06SArnaldo Carvalho de Melo static bool			big_num				=  true;
90d7470b6aSStephane Eranian static int			big_num_opt			=  -1;
91c45c6ea2SStephane Eranian static const char		*cpu_list;
92d7470b6aSStephane Eranian static const char		*csv_sep			= NULL;
93d7470b6aSStephane Eranian static bool			csv_output			= false;
945af52b51SStephane Eranian 
9560666c63SLiming Wang static volatile int done = 0;
9660666c63SLiming Wang 
97506d4bc8SPeter Zijlstra struct stats
98506d4bc8SPeter Zijlstra {
998a02631aSPeter Zijlstra 	double n, mean, M2;
100506d4bc8SPeter Zijlstra };
10142202dd5SIngo Molnar 
10269aad6f1SArnaldo Carvalho de Melo struct perf_stat {
10369aad6f1SArnaldo Carvalho de Melo 	struct stats	  res_stats[3];
10469aad6f1SArnaldo Carvalho de Melo };
10569aad6f1SArnaldo Carvalho de Melo 
106c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
10769aad6f1SArnaldo Carvalho de Melo {
108c52b12edSArnaldo Carvalho de Melo 	evsel->priv = zalloc(sizeof(struct perf_stat));
10969aad6f1SArnaldo Carvalho de Melo 	return evsel->priv == NULL ? -ENOMEM : 0;
11069aad6f1SArnaldo Carvalho de Melo }
11169aad6f1SArnaldo Carvalho de Melo 
11269aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
11369aad6f1SArnaldo Carvalho de Melo {
11469aad6f1SArnaldo Carvalho de Melo 	free(evsel->priv);
11569aad6f1SArnaldo Carvalho de Melo 	evsel->priv = NULL;
11669aad6f1SArnaldo Carvalho de Melo }
11769aad6f1SArnaldo Carvalho de Melo 
1189e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val)
1199e9772c4SPeter Zijlstra {
1208a02631aSPeter Zijlstra 	double delta;
1219e9772c4SPeter Zijlstra 
1228a02631aSPeter Zijlstra 	stats->n++;
1238a02631aSPeter Zijlstra 	delta = val - stats->mean;
1248a02631aSPeter Zijlstra 	stats->mean += delta / stats->n;
1258a02631aSPeter Zijlstra 	stats->M2 += delta*(val - stats->mean);
1269e9772c4SPeter Zijlstra }
1279e9772c4SPeter Zijlstra 
128506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats)
129506d4bc8SPeter Zijlstra {
1308a02631aSPeter Zijlstra 	return stats->mean;
131506d4bc8SPeter Zijlstra }
13242202dd5SIngo Molnar 
133506d4bc8SPeter Zijlstra /*
13463d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
13563d40debSPeter Zijlstra  *
13663d40debSPeter Zijlstra  *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
1378a02631aSPeter Zijlstra  * s^2 = -------------------------------
13863d40debSPeter Zijlstra  *                  n - 1
13963d40debSPeter Zijlstra  *
14063d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Stddev
14163d40debSPeter Zijlstra  *
14263d40debSPeter Zijlstra  * The std dev of the mean is related to the std dev by:
14363d40debSPeter Zijlstra  *
14463d40debSPeter Zijlstra  *             s
14563d40debSPeter Zijlstra  * s_mean = -------
14663d40debSPeter Zijlstra  *          sqrt(n)
14763d40debSPeter Zijlstra  *
148506d4bc8SPeter Zijlstra  */
149506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats)
150506d4bc8SPeter Zijlstra {
1518a02631aSPeter Zijlstra 	double variance = stats->M2 / (stats->n - 1);
1528a02631aSPeter Zijlstra 	double variance_mean = variance / stats->n;
15342202dd5SIngo Molnar 
15463d40debSPeter Zijlstra 	return sqrt(variance_mean);
155506d4bc8SPeter Zijlstra }
15642202dd5SIngo Molnar 
157f5b4a9c3SStephane Eranian struct stats			runtime_nsecs_stats[MAX_NR_CPUS];
158f5b4a9c3SStephane Eranian struct stats			runtime_cycles_stats[MAX_NR_CPUS];
159f5b4a9c3SStephane Eranian struct stats			runtime_branches_stats[MAX_NR_CPUS];
160506d4bc8SPeter Zijlstra struct stats			walltime_nsecs_stats;
16186470930SIngo Molnar 
16248290609SArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel)
16386470930SIngo Molnar {
16469aad6f1SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
16586470930SIngo Molnar 
16686470930SIngo Molnar 	if (scale)
16786470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
16886470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
16986470930SIngo Molnar 
1702e6cdf99SStephane Eranian 	attr->inherit = !no_inherit;
1715d2cd909SArnaldo Carvalho de Melo 
1725d2cd909SArnaldo Carvalho de Melo 	if (system_wide)
1735d2cd909SArnaldo Carvalho de Melo 		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
1745d2cd909SArnaldo Carvalho de Melo 
1752e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1) {
17686470930SIngo Molnar 		attr->disabled = 1;
17757e7986eSPaul Mackerras 		attr->enable_on_exec = 1;
1786be2850eSZhang, Yanmin 	}
179084ab9f8SArnaldo Carvalho de Melo 
1805d2cd909SArnaldo Carvalho de Melo 	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
18186470930SIngo Molnar }
18286470930SIngo Molnar 
18386470930SIngo Molnar /*
18486470930SIngo Molnar  * Does the counter have nsecs as a unit?
18586470930SIngo Molnar  */
186daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel)
18786470930SIngo Molnar {
188daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
189daec78a0SArnaldo Carvalho de Melo 	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
19086470930SIngo Molnar 		return 1;
19186470930SIngo Molnar 
19286470930SIngo Molnar 	return 0;
19386470930SIngo Molnar }
19486470930SIngo Molnar 
19586470930SIngo Molnar /*
19686470930SIngo Molnar  * Read out the results of a single counter:
197f5b4a9c3SStephane Eranian  * aggregate counts across CPUs in system-wide mode
19886470930SIngo Molnar  */
199c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter)
20086470930SIngo Molnar {
20169aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
202c52b12edSArnaldo Carvalho de Melo 	u64 *count = counter->counts->aggr.values;
203c52b12edSArnaldo Carvalho de Melo 	int i;
20486470930SIngo Molnar 
2057e2ed097SArnaldo Carvalho de Melo 	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
2067e2ed097SArnaldo Carvalho de Melo 			       evsel_list->threads->nr, scale) < 0)
207c52b12edSArnaldo Carvalho de Melo 		return -1;
2089e9772c4SPeter Zijlstra 
2099e9772c4SPeter Zijlstra 	for (i = 0; i < 3; i++)
21069aad6f1SArnaldo Carvalho de Melo 		update_stats(&ps->res_stats[i], count[i]);
2119e9772c4SPeter Zijlstra 
2129e9772c4SPeter Zijlstra 	if (verbose) {
2139486aa38SArnaldo Carvalho de Melo 		fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
2149486aa38SArnaldo Carvalho de Melo 			event_name(counter), count[0], count[1], count[2]);
2159e9772c4SPeter Zijlstra 	}
2169e9772c4SPeter Zijlstra 
21786470930SIngo Molnar 	/*
21886470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
21986470930SIngo Molnar 	 */
220daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
221f5b4a9c3SStephane Eranian 		update_stats(&runtime_nsecs_stats[0], count[0]);
222daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
223f5b4a9c3SStephane Eranian 		update_stats(&runtime_cycles_stats[0], count[0]);
224daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
225f5b4a9c3SStephane Eranian 		update_stats(&runtime_branches_stats[0], count[0]);
226c52b12edSArnaldo Carvalho de Melo 
227c52b12edSArnaldo Carvalho de Melo 	return 0;
228f5b4a9c3SStephane Eranian }
229f5b4a9c3SStephane Eranian 
230f5b4a9c3SStephane Eranian /*
231f5b4a9c3SStephane Eranian  * Read out the results of a single counter:
232f5b4a9c3SStephane Eranian  * do not aggregate counts across CPUs in system-wide mode
233f5b4a9c3SStephane Eranian  */
234c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter)
235f5b4a9c3SStephane Eranian {
236c52b12edSArnaldo Carvalho de Melo 	u64 *count;
237f5b4a9c3SStephane Eranian 	int cpu;
238f5b4a9c3SStephane Eranian 
2397e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
240c52b12edSArnaldo Carvalho de Melo 		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
241c52b12edSArnaldo Carvalho de Melo 			return -1;
242f5b4a9c3SStephane Eranian 
243c52b12edSArnaldo Carvalho de Melo 		count = counter->counts->cpu[cpu].values;
244f5b4a9c3SStephane Eranian 
245daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
246f5b4a9c3SStephane Eranian 			update_stats(&runtime_nsecs_stats[cpu], count[0]);
247daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
248f5b4a9c3SStephane Eranian 			update_stats(&runtime_cycles_stats[cpu], count[0]);
249daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
250f5b4a9c3SStephane Eranian 			update_stats(&runtime_branches_stats[cpu], count[0]);
251f5b4a9c3SStephane Eranian 	}
252c52b12edSArnaldo Carvalho de Melo 
253c52b12edSArnaldo Carvalho de Melo 	return 0;
25486470930SIngo Molnar }
25586470930SIngo Molnar 
256f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv)
25786470930SIngo Molnar {
25886470930SIngo Molnar 	unsigned long long t0, t1;
25969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
26042202dd5SIngo Molnar 	int status = 0;
261051ae7f7SPaul Mackerras 	int child_ready_pipe[2], go_pipe[2];
2626be2850eSZhang, Yanmin 	const bool forks = (argc > 0);
263051ae7f7SPaul Mackerras 	char buf;
26486470930SIngo Molnar 
26560666c63SLiming Wang 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
266051ae7f7SPaul Mackerras 		perror("failed to create pipes");
267051ae7f7SPaul Mackerras 		exit(1);
268051ae7f7SPaul Mackerras 	}
269051ae7f7SPaul Mackerras 
27060666c63SLiming Wang 	if (forks) {
2716be2850eSZhang, Yanmin 		if ((child_pid = fork()) < 0)
272051ae7f7SPaul Mackerras 			perror("failed to fork");
273051ae7f7SPaul Mackerras 
2746be2850eSZhang, Yanmin 		if (!child_pid) {
275051ae7f7SPaul Mackerras 			close(child_ready_pipe[0]);
276051ae7f7SPaul Mackerras 			close(go_pipe[1]);
277051ae7f7SPaul Mackerras 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
278051ae7f7SPaul Mackerras 
279051ae7f7SPaul Mackerras 			/*
280051ae7f7SPaul Mackerras 			 * Do a dummy execvp to get the PLT entry resolved,
281051ae7f7SPaul Mackerras 			 * so we avoid the resolver overhead on the real
282051ae7f7SPaul Mackerras 			 * execvp call.
283051ae7f7SPaul Mackerras 			 */
284051ae7f7SPaul Mackerras 			execvp("", (char **)argv);
285051ae7f7SPaul Mackerras 
286051ae7f7SPaul Mackerras 			/*
287051ae7f7SPaul Mackerras 			 * Tell the parent we're ready to go
288051ae7f7SPaul Mackerras 			 */
289051ae7f7SPaul Mackerras 			close(child_ready_pipe[1]);
290051ae7f7SPaul Mackerras 
291051ae7f7SPaul Mackerras 			/*
292051ae7f7SPaul Mackerras 			 * Wait until the parent tells us to go.
293051ae7f7SPaul Mackerras 			 */
294a92bef0fSFrederic Weisbecker 			if (read(go_pipe[0], &buf, 1) == -1)
295a92bef0fSFrederic Weisbecker 				perror("unable to read pipe");
296051ae7f7SPaul Mackerras 
297051ae7f7SPaul Mackerras 			execvp(argv[0], (char **)argv);
298051ae7f7SPaul Mackerras 
299051ae7f7SPaul Mackerras 			perror(argv[0]);
300051ae7f7SPaul Mackerras 			exit(-1);
301051ae7f7SPaul Mackerras 		}
302051ae7f7SPaul Mackerras 
303d6d901c2SZhang, Yanmin 		if (target_tid == -1 && target_pid == -1 && !system_wide)
3047e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
305d6d901c2SZhang, Yanmin 
306051ae7f7SPaul Mackerras 		/*
307051ae7f7SPaul Mackerras 		 * Wait for the child to be ready to exec.
308051ae7f7SPaul Mackerras 		 */
309051ae7f7SPaul Mackerras 		close(child_ready_pipe[1]);
310051ae7f7SPaul Mackerras 		close(go_pipe[0]);
311a92bef0fSFrederic Weisbecker 		if (read(child_ready_pipe[0], &buf, 1) == -1)
312a92bef0fSFrederic Weisbecker 			perror("unable to read pipe");
313051ae7f7SPaul Mackerras 		close(child_ready_pipe[0]);
31460666c63SLiming Wang 	}
315051ae7f7SPaul Mackerras 
316361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(counter, &evsel_list->entries, node) {
31748290609SArnaldo Carvalho de Melo 		if (create_perf_stat_counter(counter) < 0) {
31848290609SArnaldo Carvalho de Melo 			if (errno == -EPERM || errno == -EACCES) {
319d9cf837eSCorey Ashford 				error("You may not have permission to collect %sstats.\n"
320d9cf837eSCorey Ashford 				      "\t Consider tweaking"
321d9cf837eSCorey Ashford 				      " /proc/sys/kernel/perf_event_paranoid or running as root.",
322084ab9f8SArnaldo Carvalho de Melo 				      system_wide ? "system-wide " : "");
3235a3446bcSDavid Ahern 			} else if (errno == ENOENT) {
3245a3446bcSDavid Ahern 				error("%s event is not supported. ", event_name(counter));
32548290609SArnaldo Carvalho de Melo 			} else {
32648290609SArnaldo Carvalho de Melo 				error("open_counter returned with %d (%s). "
32748290609SArnaldo Carvalho de Melo 				      "/bin/dmesg may provide additional information.\n",
32848290609SArnaldo Carvalho de Melo 				       errno, strerror(errno));
32948290609SArnaldo Carvalho de Melo 			}
330084ab9f8SArnaldo Carvalho de Melo 			if (child_pid != -1)
331084ab9f8SArnaldo Carvalho de Melo 				kill(child_pid, SIGTERM);
33248290609SArnaldo Carvalho de Melo 			die("Not all events could be opened.\n");
333084ab9f8SArnaldo Carvalho de Melo 			return -1;
334084ab9f8SArnaldo Carvalho de Melo 		}
33548290609SArnaldo Carvalho de Melo 	}
33686470930SIngo Molnar 
337cfd748aeSFrederic Weisbecker 	if (perf_evlist__set_filters(evsel_list)) {
338cfd748aeSFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
339cfd748aeSFrederic Weisbecker 			strerror(errno));
340cfd748aeSFrederic Weisbecker 		return -1;
341cfd748aeSFrederic Weisbecker 	}
342cfd748aeSFrederic Weisbecker 
34386470930SIngo Molnar 	/*
34486470930SIngo Molnar 	 * Enable counters and exec the command:
34586470930SIngo Molnar 	 */
34686470930SIngo Molnar 	t0 = rdclock();
34786470930SIngo Molnar 
34860666c63SLiming Wang 	if (forks) {
349051ae7f7SPaul Mackerras 		close(go_pipe[1]);
35042202dd5SIngo Molnar 		wait(&status);
35160666c63SLiming Wang 	} else {
3526be2850eSZhang, Yanmin 		while(!done) sleep(1);
35360666c63SLiming Wang 	}
35486470930SIngo Molnar 
35586470930SIngo Molnar 	t1 = rdclock();
35686470930SIngo Molnar 
3579e9772c4SPeter Zijlstra 	update_stats(&walltime_nsecs_stats, t1 - t0);
35842202dd5SIngo Molnar 
359f5b4a9c3SStephane Eranian 	if (no_aggr) {
360361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
36142202dd5SIngo Molnar 			read_counter(counter);
3627e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
363f5b4a9c3SStephane Eranian 		}
364c52b12edSArnaldo Carvalho de Melo 	} else {
365361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
366c52b12edSArnaldo Carvalho de Melo 			read_counter_aggr(counter);
3677e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
3687e2ed097SArnaldo Carvalho de Melo 					     evsel_list->threads->nr);
369c52b12edSArnaldo Carvalho de Melo 		}
370c52b12edSArnaldo Carvalho de Melo 	}
371c52b12edSArnaldo Carvalho de Melo 
37242202dd5SIngo Molnar 	return WEXITSTATUS(status);
37342202dd5SIngo Molnar }
37442202dd5SIngo Molnar 
37569aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg)
37642202dd5SIngo Molnar {
37769aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps;
37869aad6f1SArnaldo Carvalho de Melo 
379849abde9SPeter Zijlstra 	if (run_count == 1)
380849abde9SPeter Zijlstra 		return;
381849abde9SPeter Zijlstra 
38269aad6f1SArnaldo Carvalho de Melo 	ps = evsel->priv;
383849abde9SPeter Zijlstra 	fprintf(stderr, "   ( +- %7.3f%% )",
38469aad6f1SArnaldo Carvalho de Melo 			100 * stddev_stats(&ps->res_stats[0]) / avg);
38542202dd5SIngo Molnar }
38642202dd5SIngo Molnar 
387daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
38842202dd5SIngo Molnar {
389506d4bc8SPeter Zijlstra 	double msecs = avg / 1e6;
390d7470b6aSStephane Eranian 	char cpustr[16] = { '\0', };
391d7470b6aSStephane Eranian 	const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
39242202dd5SIngo Molnar 
393f5b4a9c3SStephane Eranian 	if (no_aggr)
394d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
395d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
3967e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
397d7470b6aSStephane Eranian 
398daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
399d7470b6aSStephane Eranian 
400023695d9SStephane Eranian 	if (evsel->cgrp)
401023695d9SStephane Eranian 		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
402023695d9SStephane Eranian 
403d7470b6aSStephane Eranian 	if (csv_output)
404d7470b6aSStephane Eranian 		return;
40542202dd5SIngo Molnar 
406daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
40742202dd5SIngo Molnar 		fprintf(stderr, " # %10.3f CPUs ",
408506d4bc8SPeter Zijlstra 				avg / avg_stats(&walltime_nsecs_stats));
40942202dd5SIngo Molnar }
41042202dd5SIngo Molnar 
411daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
41242202dd5SIngo Molnar {
413c7f7fea3SIngo Molnar 	double total, ratio = 0.0;
414f5b4a9c3SStephane Eranian 	char cpustr[16] = { '\0', };
415d7470b6aSStephane Eranian 	const char *fmt;
416d7470b6aSStephane Eranian 
417d7470b6aSStephane Eranian 	if (csv_output)
418d7470b6aSStephane Eranian 		fmt = "%s%.0f%s%s";
419d7470b6aSStephane Eranian 	else if (big_num)
420d7470b6aSStephane Eranian 		fmt = "%s%'18.0f%s%-24s";
421d7470b6aSStephane Eranian 	else
422d7470b6aSStephane Eranian 		fmt = "%s%18.0f%s%-24s";
423f5b4a9c3SStephane Eranian 
424f5b4a9c3SStephane Eranian 	if (no_aggr)
425d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
426d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
4277e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
428f5b4a9c3SStephane Eranian 	else
429f5b4a9c3SStephane Eranian 		cpu = 0;
430c7f7fea3SIngo Molnar 
431daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
432d7470b6aSStephane Eranian 
433023695d9SStephane Eranian 	if (evsel->cgrp)
434023695d9SStephane Eranian 		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
435023695d9SStephane Eranian 
436d7470b6aSStephane Eranian 	if (csv_output)
437d7470b6aSStephane Eranian 		return;
43842202dd5SIngo Molnar 
439daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
440f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_cycles_stats[cpu]);
441c7f7fea3SIngo Molnar 
442c7f7fea3SIngo Molnar 		if (total)
443c7f7fea3SIngo Molnar 			ratio = avg / total;
444c7f7fea3SIngo Molnar 
44511ba2b85SIngo Molnar 		fprintf(stderr, " # ( %4.2f instructions per cycle )", ratio);
446daec78a0SArnaldo Carvalho de Melo 	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
447f5b4a9c3SStephane Eranian 			runtime_branches_stats[cpu].n != 0) {
448f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_branches_stats[cpu]);
44911018201SAnton Blanchard 
45011018201SAnton Blanchard 		if (total)
45111018201SAnton Blanchard 			ratio = avg * 100 / total;
45211018201SAnton Blanchard 
45311018201SAnton Blanchard 		fprintf(stderr, " # %10.3f %%", ratio);
45411018201SAnton Blanchard 
455f5b4a9c3SStephane Eranian 	} else if (runtime_nsecs_stats[cpu].n != 0) {
456f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_nsecs_stats[cpu]);
457c7f7fea3SIngo Molnar 
458c7f7fea3SIngo Molnar 		if (total)
459c7f7fea3SIngo Molnar 			ratio = 1000.0 * avg / total;
460c7f7fea3SIngo Molnar 
461c7f7fea3SIngo Molnar 		fprintf(stderr, " # %10.3f M/sec", ratio);
46211ba2b85SIngo Molnar 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES)) {
46311ba2b85SIngo Molnar 		total = avg_stats(&runtime_cycles_stats[cpu]);
46411ba2b85SIngo Molnar 
46511ba2b85SIngo Molnar 		if (total)
46611ba2b85SIngo Molnar 			ratio = avg / total * 100.0;
46711ba2b85SIngo Molnar 
46811ba2b85SIngo Molnar 		fprintf(stderr, " # (%5.2f%% of all cycles )", ratio);
46942202dd5SIngo Molnar 	}
47042202dd5SIngo Molnar }
47142202dd5SIngo Molnar 
47242202dd5SIngo Molnar /*
47342202dd5SIngo Molnar  * Print out the results of a single counter:
474f5b4a9c3SStephane Eranian  * aggregated counts in system-wide mode
47542202dd5SIngo Molnar  */
47669aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter)
47742202dd5SIngo Molnar {
47869aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
47969aad6f1SArnaldo Carvalho de Melo 	double avg = avg_stats(&ps->res_stats[0]);
480c52b12edSArnaldo Carvalho de Melo 	int scaled = counter->counts->scaled;
48142202dd5SIngo Molnar 
48242202dd5SIngo Molnar 	if (scaled == -1) {
483023695d9SStephane Eranian 		fprintf(stderr, "%*s%s%*s",
484d7470b6aSStephane Eranian 			csv_output ? 0 : 18,
485023695d9SStephane Eranian 			"<not counted>",
486023695d9SStephane Eranian 			csv_sep,
487023695d9SStephane Eranian 			csv_output ? 0 : -24,
488023695d9SStephane Eranian 			event_name(counter));
489023695d9SStephane Eranian 
490023695d9SStephane Eranian 		if (counter->cgrp)
491023695d9SStephane Eranian 			fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
492023695d9SStephane Eranian 
493023695d9SStephane Eranian 		fputc('\n', stderr);
49442202dd5SIngo Molnar 		return;
49542202dd5SIngo Molnar 	}
49642202dd5SIngo Molnar 
49742202dd5SIngo Molnar 	if (nsec_counter(counter))
498f5b4a9c3SStephane Eranian 		nsec_printout(-1, counter, avg);
49942202dd5SIngo Molnar 	else
500f5b4a9c3SStephane Eranian 		abs_printout(-1, counter, avg);
501849abde9SPeter Zijlstra 
502d7470b6aSStephane Eranian 	if (csv_output) {
503d7470b6aSStephane Eranian 		fputc('\n', stderr);
504d7470b6aSStephane Eranian 		return;
505d7470b6aSStephane Eranian 	}
506d7470b6aSStephane Eranian 
507849abde9SPeter Zijlstra 	print_noise(counter, avg);
50842202dd5SIngo Molnar 
509506d4bc8SPeter Zijlstra 	if (scaled) {
510506d4bc8SPeter Zijlstra 		double avg_enabled, avg_running;
511506d4bc8SPeter Zijlstra 
51269aad6f1SArnaldo Carvalho de Melo 		avg_enabled = avg_stats(&ps->res_stats[1]);
51369aad6f1SArnaldo Carvalho de Melo 		avg_running = avg_stats(&ps->res_stats[2]);
514506d4bc8SPeter Zijlstra 
515210ad39fSIngo Molnar 		fprintf(stderr, "  (scaled from %.2f%%)",
516506d4bc8SPeter Zijlstra 				100 * avg_running / avg_enabled);
517506d4bc8SPeter Zijlstra 	}
51842202dd5SIngo Molnar 	fprintf(stderr, "\n");
51942202dd5SIngo Molnar }
52042202dd5SIngo Molnar 
521f5b4a9c3SStephane Eranian /*
522f5b4a9c3SStephane Eranian  * Print out the results of a single counter:
523f5b4a9c3SStephane Eranian  * does not use aggregated count in system-wide
524f5b4a9c3SStephane Eranian  */
52569aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter)
526f5b4a9c3SStephane Eranian {
527f5b4a9c3SStephane Eranian 	u64 ena, run, val;
528f5b4a9c3SStephane Eranian 	int cpu;
529f5b4a9c3SStephane Eranian 
5307e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
531c52b12edSArnaldo Carvalho de Melo 		val = counter->counts->cpu[cpu].val;
532c52b12edSArnaldo Carvalho de Melo 		ena = counter->counts->cpu[cpu].ena;
533c52b12edSArnaldo Carvalho de Melo 		run = counter->counts->cpu[cpu].run;
534f5b4a9c3SStephane Eranian 		if (run == 0 || ena == 0) {
535023695d9SStephane Eranian 			fprintf(stderr, "CPU%*d%s%*s%s%*s",
536d7470b6aSStephane Eranian 				csv_output ? 0 : -4,
5377e2ed097SArnaldo Carvalho de Melo 				evsel_list->cpus->map[cpu], csv_sep,
538d7470b6aSStephane Eranian 				csv_output ? 0 : 18,
539d7470b6aSStephane Eranian 				"<not counted>", csv_sep,
540023695d9SStephane Eranian 				csv_output ? 0 : -24,
541d7470b6aSStephane Eranian 				event_name(counter));
542f5b4a9c3SStephane Eranian 
543023695d9SStephane Eranian 			if (counter->cgrp)
544023695d9SStephane Eranian 				fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
545023695d9SStephane Eranian 
546023695d9SStephane Eranian 			fputc('\n', stderr);
547f5b4a9c3SStephane Eranian 			continue;
548f5b4a9c3SStephane Eranian 		}
549f5b4a9c3SStephane Eranian 
550f5b4a9c3SStephane Eranian 		if (nsec_counter(counter))
551f5b4a9c3SStephane Eranian 			nsec_printout(cpu, counter, val);
552f5b4a9c3SStephane Eranian 		else
553f5b4a9c3SStephane Eranian 			abs_printout(cpu, counter, val);
554f5b4a9c3SStephane Eranian 
555d7470b6aSStephane Eranian 		if (!csv_output) {
556f5b4a9c3SStephane Eranian 			print_noise(counter, 1.0);
557f5b4a9c3SStephane Eranian 
558f5b4a9c3SStephane Eranian 			if (run != ena) {
559f5b4a9c3SStephane Eranian 				fprintf(stderr, "  (scaled from %.2f%%)",
560f5b4a9c3SStephane Eranian 					100.0 * run / ena);
561f5b4a9c3SStephane Eranian 			}
562d7470b6aSStephane Eranian 		}
563023695d9SStephane Eranian 		fputc('\n', stderr);
564f5b4a9c3SStephane Eranian 	}
565f5b4a9c3SStephane Eranian }
566f5b4a9c3SStephane Eranian 
56742202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
56842202dd5SIngo Molnar {
56969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
57069aad6f1SArnaldo Carvalho de Melo 	int i;
57142202dd5SIngo Molnar 
57286470930SIngo Molnar 	fflush(stdout);
57386470930SIngo Molnar 
574d7470b6aSStephane Eranian 	if (!csv_output) {
57586470930SIngo Molnar 		fprintf(stderr, "\n");
57660666c63SLiming Wang 		fprintf(stderr, " Performance counter stats for ");
577d6d901c2SZhang, Yanmin 		if(target_pid == -1 && target_tid == -1) {
57860666c63SLiming Wang 			fprintf(stderr, "\'%s", argv[0]);
57986470930SIngo Molnar 			for (i = 1; i < argc; i++)
58086470930SIngo Molnar 				fprintf(stderr, " %s", argv[i]);
581d6d901c2SZhang, Yanmin 		} else if (target_pid != -1)
582d6d901c2SZhang, Yanmin 			fprintf(stderr, "process id \'%d", target_pid);
583d6d901c2SZhang, Yanmin 		else
584d6d901c2SZhang, Yanmin 			fprintf(stderr, "thread id \'%d", target_tid);
58586470930SIngo Molnar 
58642202dd5SIngo Molnar 		fprintf(stderr, "\'");
58742202dd5SIngo Molnar 		if (run_count > 1)
58842202dd5SIngo Molnar 			fprintf(stderr, " (%d runs)", run_count);
58942202dd5SIngo Molnar 		fprintf(stderr, ":\n\n");
590d7470b6aSStephane Eranian 	}
59186470930SIngo Molnar 
592f5b4a9c3SStephane Eranian 	if (no_aggr) {
593361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
59486470930SIngo Molnar 			print_counter(counter);
595f5b4a9c3SStephane Eranian 	} else {
596361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
597f5b4a9c3SStephane Eranian 			print_counter_aggr(counter);
598f5b4a9c3SStephane Eranian 	}
59986470930SIngo Molnar 
600d7470b6aSStephane Eranian 	if (!csv_output) {
60186470930SIngo Molnar 		fprintf(stderr, "\n");
6025af52b51SStephane Eranian 		fprintf(stderr, " %18.9f  seconds time elapsed",
603506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats)/1e9);
604566747e6SIngo Molnar 		if (run_count > 1) {
605566747e6SIngo Molnar 			fprintf(stderr, "   ( +- %7.3f%% )",
606506d4bc8SPeter Zijlstra 				100*stddev_stats(&walltime_nsecs_stats) /
607506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats));
608566747e6SIngo Molnar 		}
609566747e6SIngo Molnar 		fprintf(stderr, "\n\n");
61086470930SIngo Molnar 	}
611d7470b6aSStephane Eranian }
61286470930SIngo Molnar 
613f7b7c26eSPeter Zijlstra static volatile int signr = -1;
614f7b7c26eSPeter Zijlstra 
61586470930SIngo Molnar static void skip_signal(int signo)
61686470930SIngo Molnar {
6176be2850eSZhang, Yanmin 	if(child_pid == -1)
61860666c63SLiming Wang 		done = 1;
61960666c63SLiming Wang 
620f7b7c26eSPeter Zijlstra 	signr = signo;
621f7b7c26eSPeter Zijlstra }
622f7b7c26eSPeter Zijlstra 
623f7b7c26eSPeter Zijlstra static void sig_atexit(void)
624f7b7c26eSPeter Zijlstra {
625933da83aSChris Wilson 	if (child_pid != -1)
626933da83aSChris Wilson 		kill(child_pid, SIGTERM);
627933da83aSChris Wilson 
628f7b7c26eSPeter Zijlstra 	if (signr == -1)
629f7b7c26eSPeter Zijlstra 		return;
630f7b7c26eSPeter Zijlstra 
631f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
632f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
63386470930SIngo Molnar }
63486470930SIngo Molnar 
63586470930SIngo Molnar static const char * const stat_usage[] = {
63660666c63SLiming Wang 	"perf stat [<options>] [<command>]",
63786470930SIngo Molnar 	NULL
63886470930SIngo Molnar };
63986470930SIngo Molnar 
640d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used,
641d7470b6aSStephane Eranian 			     const char *s __used, int unset)
642d7470b6aSStephane Eranian {
643d7470b6aSStephane Eranian 	big_num_opt = unset ? 0 : 1;
644d7470b6aSStephane Eranian 	return 0;
645d7470b6aSStephane Eranian }
646d7470b6aSStephane Eranian 
64786470930SIngo Molnar static const struct option options[] = {
648361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
64986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
65086470930SIngo Molnar 		     parse_events),
651cfd748aeSFrederic Weisbecker 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
652cfd748aeSFrederic Weisbecker 		     "event filter", parse_filter),
6532e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
6542e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
65586470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
656d6d901c2SZhang, Yanmin 		    "stat events on existing process id"),
657d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
658d6d901c2SZhang, Yanmin 		    "stat events on existing thread id"),
65986470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
66086470930SIngo Molnar 		    "system-wide collection from all CPUs"),
661b26bc5a7SBrice Goglin 	OPT_BOOLEAN('c', "scale", &scale,
66286470930SIngo Molnar 		    "scale/normalize counters"),
663c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
664743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
66542202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
66642202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
6670cfb7a13SIngo Molnar 	OPT_BOOLEAN('n', "null", &null_run,
6680cfb7a13SIngo Molnar 		    "null run - dont start any counters"),
669d7470b6aSStephane Eranian 	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
670d7470b6aSStephane Eranian 			   "print large numbers with thousands\' separators",
671d7470b6aSStephane Eranian 			   stat__set_big_num),
672c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
673c45c6ea2SStephane Eranian 		    "list of cpus to monitor in system-wide"),
674f5b4a9c3SStephane Eranian 	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
675f5b4a9c3SStephane Eranian 		    "disable CPU count aggregation"),
676d7470b6aSStephane Eranian 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
677d7470b6aSStephane Eranian 		   "print counts with custom separator"),
678023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
679023695d9SStephane Eranian 		     "monitor event in cgroup name only",
680023695d9SStephane Eranian 		     parse_cgroups),
68186470930SIngo Molnar 	OPT_END()
68286470930SIngo Molnar };
68386470930SIngo Molnar 
684f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used)
68586470930SIngo Molnar {
68669aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
68769aad6f1SArnaldo Carvalho de Melo 	int status = -ENOMEM;
68842202dd5SIngo Molnar 
6895af52b51SStephane Eranian 	setlocale(LC_ALL, "");
6905af52b51SStephane Eranian 
6917e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
692361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
693361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
694361c99a6SArnaldo Carvalho de Melo 
695a0541234SAnton Blanchard 	argc = parse_options(argc, argv, options, stat_usage,
696a0541234SAnton Blanchard 		PARSE_OPT_STOP_AT_NON_OPTION);
697d7470b6aSStephane Eranian 
698d7470b6aSStephane Eranian 	if (csv_sep)
699d7470b6aSStephane Eranian 		csv_output = true;
700d7470b6aSStephane Eranian 	else
701d7470b6aSStephane Eranian 		csv_sep = DEFAULT_SEPARATOR;
702d7470b6aSStephane Eranian 
703d7470b6aSStephane Eranian 	/*
704d7470b6aSStephane Eranian 	 * let the spreadsheet do the pretty-printing
705d7470b6aSStephane Eranian 	 */
706d7470b6aSStephane Eranian 	if (csv_output) {
707d7470b6aSStephane Eranian 		/* User explicitely passed -B? */
708d7470b6aSStephane Eranian 		if (big_num_opt == 1) {
709d7470b6aSStephane Eranian 			fprintf(stderr, "-B option not supported with -x\n");
710d7470b6aSStephane Eranian 			usage_with_options(stat_usage, options);
711d7470b6aSStephane Eranian 		} else /* Nope, so disable big number formatting */
712d7470b6aSStephane Eranian 			big_num = false;
713d7470b6aSStephane Eranian 	} else if (big_num_opt == 0) /* User passed --no-big-num */
714d7470b6aSStephane Eranian 		big_num = false;
715d7470b6aSStephane Eranian 
716d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1)
71786470930SIngo Molnar 		usage_with_options(stat_usage, options);
7189e9772c4SPeter Zijlstra 	if (run_count <= 0)
71942202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
72086470930SIngo Molnar 
721023695d9SStephane Eranian 	/* no_aggr, cgroup are for system-wide only */
722023695d9SStephane Eranian 	if ((no_aggr || nr_cgroups) && !system_wide) {
723023695d9SStephane Eranian 		fprintf(stderr, "both cgroup and no-aggregation "
724023695d9SStephane Eranian 			"modes only available in system-wide mode\n");
725023695d9SStephane Eranian 
726f5b4a9c3SStephane Eranian 		usage_with_options(stat_usage, options);
727023695d9SStephane Eranian 	}
728f5b4a9c3SStephane Eranian 
729c3043569SJaswinder Singh Rajput 	/* Set attrs and nr_counters if no event is selected and !null_run */
730361c99a6SArnaldo Carvalho de Melo 	if (!null_run && !evsel_list->nr_entries) {
73169aad6f1SArnaldo Carvalho de Melo 		size_t c;
73269aad6f1SArnaldo Carvalho de Melo 
73369aad6f1SArnaldo Carvalho de Melo 		for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
734361c99a6SArnaldo Carvalho de Melo 			pos = perf_evsel__new(&default_attrs[c], c);
73569aad6f1SArnaldo Carvalho de Melo 			if (pos == NULL)
73669aad6f1SArnaldo Carvalho de Melo 				goto out;
737361c99a6SArnaldo Carvalho de Melo 			perf_evlist__add(evsel_list, pos);
73869aad6f1SArnaldo Carvalho de Melo 		}
739c3043569SJaswinder Singh Rajput 	}
74086470930SIngo Molnar 
7415c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
7425c98d466SArnaldo Carvalho de Melo 		target_tid = target_pid;
7435c98d466SArnaldo Carvalho de Melo 
7447e2ed097SArnaldo Carvalho de Melo 	evsel_list->threads = thread_map__new(target_pid, target_tid);
7457e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->threads == NULL) {
7465c98d466SArnaldo Carvalho de Melo 		pr_err("Problems finding threads of monitor\n");
7475c98d466SArnaldo Carvalho de Melo 		usage_with_options(stat_usage, options);
7485c98d466SArnaldo Carvalho de Melo 	}
7495c98d466SArnaldo Carvalho de Melo 
750a12b51c4SPaul Mackerras 	if (system_wide)
7517e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__new(cpu_list);
752a12b51c4SPaul Mackerras 	else
7537e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__dummy_new();
75486470930SIngo Molnar 
7557e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->cpus == NULL) {
75660d567e2SArnaldo Carvalho de Melo 		perror("failed to parse CPUs map");
757c45c6ea2SStephane Eranian 		usage_with_options(stat_usage, options);
75860d567e2SArnaldo Carvalho de Melo 		return -1;
75960d567e2SArnaldo Carvalho de Melo 	}
760c45c6ea2SStephane Eranian 
761361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
762c52b12edSArnaldo Carvalho de Melo 		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
7637e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
7647e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
76569aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
766d6d901c2SZhang, Yanmin 	}
767d6d901c2SZhang, Yanmin 
76886470930SIngo Molnar 	/*
76986470930SIngo Molnar 	 * We dont want to block the signals - that would cause
77086470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
77186470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
77286470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
77386470930SIngo Molnar 	 */
774f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
77586470930SIngo Molnar 	signal(SIGINT,  skip_signal);
77686470930SIngo Molnar 	signal(SIGALRM, skip_signal);
77786470930SIngo Molnar 	signal(SIGABRT, skip_signal);
77886470930SIngo Molnar 
77942202dd5SIngo Molnar 	status = 0;
78042202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
78142202dd5SIngo Molnar 		if (run_count != 1 && verbose)
78242202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
78342202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
78442202dd5SIngo Molnar 	}
78542202dd5SIngo Molnar 
786084ab9f8SArnaldo Carvalho de Melo 	if (status != -1)
78742202dd5SIngo Molnar 		print_stat(argc, argv);
78869aad6f1SArnaldo Carvalho de Melo out_free_fd:
789361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node)
79069aad6f1SArnaldo Carvalho de Melo 		perf_evsel__free_stat_priv(pos);
7917e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
7920015e2e1SArnaldo Carvalho de Melo out:
7930015e2e1SArnaldo Carvalho de Melo 	perf_evlist__delete(evsel_list);
79442202dd5SIngo Molnar 	return status;
79586470930SIngo Molnar }
796