xref: /openbmc/linux/tools/perf/builtin-stat.c (revision 1fc570ad)
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		},
681fc570adSIngo Molnar   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES		},
69f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
7012133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
7112133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
72f4dbfa8fSPeter Zijlstra 
7386470930SIngo Molnar };
7486470930SIngo Molnar 
75361c99a6SArnaldo Carvalho de Melo struct perf_evlist		*evsel_list;
76361c99a6SArnaldo Carvalho de Melo 
77c0555642SIan Munsie static bool			system_wide			=  false;
7842202dd5SIngo Molnar static int			run_idx				=  0;
7942202dd5SIngo Molnar 
803d632595SJaswinder Singh Rajput static int			run_count			=  1;
812e6cdf99SStephane Eranian static bool			no_inherit			= false;
82c0555642SIan Munsie static bool			scale				=  true;
83f5b4a9c3SStephane Eranian static bool			no_aggr				= false;
84933da83aSChris Wilson static pid_t			target_pid			= -1;
85d6d901c2SZhang, Yanmin static pid_t			target_tid			= -1;
86933da83aSChris Wilson static pid_t			child_pid			= -1;
87c0555642SIan Munsie static bool			null_run			=  false;
88201e0b06SArnaldo Carvalho de Melo static bool			big_num				=  true;
89d7470b6aSStephane Eranian static int			big_num_opt			=  -1;
90c45c6ea2SStephane Eranian static const char		*cpu_list;
91d7470b6aSStephane Eranian static const char		*csv_sep			= NULL;
92d7470b6aSStephane Eranian static bool			csv_output			= false;
935af52b51SStephane Eranian 
9460666c63SLiming Wang static volatile int done = 0;
9560666c63SLiming Wang 
96506d4bc8SPeter Zijlstra struct stats
97506d4bc8SPeter Zijlstra {
988a02631aSPeter Zijlstra 	double n, mean, M2;
99506d4bc8SPeter Zijlstra };
10042202dd5SIngo Molnar 
10169aad6f1SArnaldo Carvalho de Melo struct perf_stat {
10269aad6f1SArnaldo Carvalho de Melo 	struct stats	  res_stats[3];
10369aad6f1SArnaldo Carvalho de Melo };
10469aad6f1SArnaldo Carvalho de Melo 
105c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
10669aad6f1SArnaldo Carvalho de Melo {
107c52b12edSArnaldo Carvalho de Melo 	evsel->priv = zalloc(sizeof(struct perf_stat));
10869aad6f1SArnaldo Carvalho de Melo 	return evsel->priv == NULL ? -ENOMEM : 0;
10969aad6f1SArnaldo Carvalho de Melo }
11069aad6f1SArnaldo Carvalho de Melo 
11169aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
11269aad6f1SArnaldo Carvalho de Melo {
11369aad6f1SArnaldo Carvalho de Melo 	free(evsel->priv);
11469aad6f1SArnaldo Carvalho de Melo 	evsel->priv = NULL;
11569aad6f1SArnaldo Carvalho de Melo }
11669aad6f1SArnaldo Carvalho de Melo 
1179e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val)
1189e9772c4SPeter Zijlstra {
1198a02631aSPeter Zijlstra 	double delta;
1209e9772c4SPeter Zijlstra 
1218a02631aSPeter Zijlstra 	stats->n++;
1228a02631aSPeter Zijlstra 	delta = val - stats->mean;
1238a02631aSPeter Zijlstra 	stats->mean += delta / stats->n;
1248a02631aSPeter Zijlstra 	stats->M2 += delta*(val - stats->mean);
1259e9772c4SPeter Zijlstra }
1269e9772c4SPeter Zijlstra 
127506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats)
128506d4bc8SPeter Zijlstra {
1298a02631aSPeter Zijlstra 	return stats->mean;
130506d4bc8SPeter Zijlstra }
13142202dd5SIngo Molnar 
132506d4bc8SPeter Zijlstra /*
13363d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
13463d40debSPeter Zijlstra  *
13563d40debSPeter Zijlstra  *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
1368a02631aSPeter Zijlstra  * s^2 = -------------------------------
13763d40debSPeter Zijlstra  *                  n - 1
13863d40debSPeter Zijlstra  *
13963d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Stddev
14063d40debSPeter Zijlstra  *
14163d40debSPeter Zijlstra  * The std dev of the mean is related to the std dev by:
14263d40debSPeter Zijlstra  *
14363d40debSPeter Zijlstra  *             s
14463d40debSPeter Zijlstra  * s_mean = -------
14563d40debSPeter Zijlstra  *          sqrt(n)
14663d40debSPeter Zijlstra  *
147506d4bc8SPeter Zijlstra  */
148506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats)
149506d4bc8SPeter Zijlstra {
1508a02631aSPeter Zijlstra 	double variance = stats->M2 / (stats->n - 1);
1518a02631aSPeter Zijlstra 	double variance_mean = variance / stats->n;
15242202dd5SIngo Molnar 
15363d40debSPeter Zijlstra 	return sqrt(variance_mean);
154506d4bc8SPeter Zijlstra }
15542202dd5SIngo Molnar 
156f5b4a9c3SStephane Eranian struct stats			runtime_nsecs_stats[MAX_NR_CPUS];
157f5b4a9c3SStephane Eranian struct stats			runtime_cycles_stats[MAX_NR_CPUS];
158481f988aSIngo Molnar struct stats			runtime_stalled_cycles_stats[MAX_NR_CPUS];
159f5b4a9c3SStephane Eranian struct stats			runtime_branches_stats[MAX_NR_CPUS];
160d58f4c82SIngo Molnar struct stats			runtime_cacherefs_stats[MAX_NR_CPUS];
161506d4bc8SPeter Zijlstra struct stats			walltime_nsecs_stats;
16286470930SIngo Molnar 
16348290609SArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel)
16486470930SIngo Molnar {
16569aad6f1SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
16686470930SIngo Molnar 
16786470930SIngo Molnar 	if (scale)
16886470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
16986470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
17086470930SIngo Molnar 
1712e6cdf99SStephane Eranian 	attr->inherit = !no_inherit;
1725d2cd909SArnaldo Carvalho de Melo 
1735d2cd909SArnaldo Carvalho de Melo 	if (system_wide)
1745d2cd909SArnaldo Carvalho de Melo 		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
1755d2cd909SArnaldo Carvalho de Melo 
1762e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1) {
17786470930SIngo Molnar 		attr->disabled = 1;
17857e7986eSPaul Mackerras 		attr->enable_on_exec = 1;
1796be2850eSZhang, Yanmin 	}
180084ab9f8SArnaldo Carvalho de Melo 
1815d2cd909SArnaldo Carvalho de Melo 	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
18286470930SIngo Molnar }
18386470930SIngo Molnar 
18486470930SIngo Molnar /*
18586470930SIngo Molnar  * Does the counter have nsecs as a unit?
18686470930SIngo Molnar  */
187daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel)
18886470930SIngo Molnar {
189daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
190daec78a0SArnaldo Carvalho de Melo 	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
19186470930SIngo Molnar 		return 1;
19286470930SIngo Molnar 
19386470930SIngo Molnar 	return 0;
19486470930SIngo Molnar }
19586470930SIngo Molnar 
19686470930SIngo Molnar /*
197dcd9936aSIngo Molnar  * Update various tracking values we maintain to print
198dcd9936aSIngo Molnar  * more semantic information such as miss/hit ratios,
199dcd9936aSIngo Molnar  * instruction rates, etc:
200dcd9936aSIngo Molnar  */
201dcd9936aSIngo Molnar static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
202dcd9936aSIngo Molnar {
203dcd9936aSIngo Molnar 	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
204dcd9936aSIngo Molnar 		update_stats(&runtime_nsecs_stats[0], count[0]);
205dcd9936aSIngo Molnar 	else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
206dcd9936aSIngo Molnar 		update_stats(&runtime_cycles_stats[0], count[0]);
207481f988aSIngo Molnar 	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES))
208481f988aSIngo Molnar 		update_stats(&runtime_stalled_cycles_stats[0], count[0]);
209dcd9936aSIngo Molnar 	else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
210dcd9936aSIngo Molnar 		update_stats(&runtime_branches_stats[0], count[0]);
211dcd9936aSIngo Molnar 	else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
212dcd9936aSIngo Molnar 		update_stats(&runtime_cacherefs_stats[0], count[0]);
213dcd9936aSIngo Molnar }
214dcd9936aSIngo Molnar 
215dcd9936aSIngo Molnar /*
21686470930SIngo Molnar  * Read out the results of a single counter:
217f5b4a9c3SStephane Eranian  * aggregate counts across CPUs in system-wide mode
21886470930SIngo Molnar  */
219c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter)
22086470930SIngo Molnar {
22169aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
222c52b12edSArnaldo Carvalho de Melo 	u64 *count = counter->counts->aggr.values;
223c52b12edSArnaldo Carvalho de Melo 	int i;
22486470930SIngo Molnar 
2257e2ed097SArnaldo Carvalho de Melo 	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
2267e2ed097SArnaldo Carvalho de Melo 			       evsel_list->threads->nr, scale) < 0)
227c52b12edSArnaldo Carvalho de Melo 		return -1;
2289e9772c4SPeter Zijlstra 
2299e9772c4SPeter Zijlstra 	for (i = 0; i < 3; i++)
23069aad6f1SArnaldo Carvalho de Melo 		update_stats(&ps->res_stats[i], count[i]);
2319e9772c4SPeter Zijlstra 
2329e9772c4SPeter Zijlstra 	if (verbose) {
2339486aa38SArnaldo Carvalho de Melo 		fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
2349486aa38SArnaldo Carvalho de Melo 			event_name(counter), count[0], count[1], count[2]);
2359e9772c4SPeter Zijlstra 	}
2369e9772c4SPeter Zijlstra 
23786470930SIngo Molnar 	/*
23886470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
23986470930SIngo Molnar 	 */
240dcd9936aSIngo Molnar 	update_shadow_stats(counter, count);
241c52b12edSArnaldo Carvalho de Melo 
242c52b12edSArnaldo Carvalho de Melo 	return 0;
243f5b4a9c3SStephane Eranian }
244f5b4a9c3SStephane Eranian 
245f5b4a9c3SStephane Eranian /*
246f5b4a9c3SStephane Eranian  * Read out the results of a single counter:
247f5b4a9c3SStephane Eranian  * do not aggregate counts across CPUs in system-wide mode
248f5b4a9c3SStephane Eranian  */
249c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter)
250f5b4a9c3SStephane Eranian {
251c52b12edSArnaldo Carvalho de Melo 	u64 *count;
252f5b4a9c3SStephane Eranian 	int cpu;
253f5b4a9c3SStephane Eranian 
2547e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
255c52b12edSArnaldo Carvalho de Melo 		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
256c52b12edSArnaldo Carvalho de Melo 			return -1;
257f5b4a9c3SStephane Eranian 
258c52b12edSArnaldo Carvalho de Melo 		count = counter->counts->cpu[cpu].values;
259f5b4a9c3SStephane Eranian 
260dcd9936aSIngo Molnar 		update_shadow_stats(counter, count);
261f5b4a9c3SStephane Eranian 	}
262c52b12edSArnaldo Carvalho de Melo 
263c52b12edSArnaldo Carvalho de Melo 	return 0;
26486470930SIngo Molnar }
26586470930SIngo Molnar 
266f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv)
26786470930SIngo Molnar {
26886470930SIngo Molnar 	unsigned long long t0, t1;
26969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
27042202dd5SIngo Molnar 	int status = 0;
271051ae7f7SPaul Mackerras 	int child_ready_pipe[2], go_pipe[2];
2726be2850eSZhang, Yanmin 	const bool forks = (argc > 0);
273051ae7f7SPaul Mackerras 	char buf;
27486470930SIngo Molnar 
27560666c63SLiming Wang 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
276051ae7f7SPaul Mackerras 		perror("failed to create pipes");
277051ae7f7SPaul Mackerras 		exit(1);
278051ae7f7SPaul Mackerras 	}
279051ae7f7SPaul Mackerras 
28060666c63SLiming Wang 	if (forks) {
2816be2850eSZhang, Yanmin 		if ((child_pid = fork()) < 0)
282051ae7f7SPaul Mackerras 			perror("failed to fork");
283051ae7f7SPaul Mackerras 
2846be2850eSZhang, Yanmin 		if (!child_pid) {
285051ae7f7SPaul Mackerras 			close(child_ready_pipe[0]);
286051ae7f7SPaul Mackerras 			close(go_pipe[1]);
287051ae7f7SPaul Mackerras 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
288051ae7f7SPaul Mackerras 
289051ae7f7SPaul Mackerras 			/*
290051ae7f7SPaul Mackerras 			 * Do a dummy execvp to get the PLT entry resolved,
291051ae7f7SPaul Mackerras 			 * so we avoid the resolver overhead on the real
292051ae7f7SPaul Mackerras 			 * execvp call.
293051ae7f7SPaul Mackerras 			 */
294051ae7f7SPaul Mackerras 			execvp("", (char **)argv);
295051ae7f7SPaul Mackerras 
296051ae7f7SPaul Mackerras 			/*
297051ae7f7SPaul Mackerras 			 * Tell the parent we're ready to go
298051ae7f7SPaul Mackerras 			 */
299051ae7f7SPaul Mackerras 			close(child_ready_pipe[1]);
300051ae7f7SPaul Mackerras 
301051ae7f7SPaul Mackerras 			/*
302051ae7f7SPaul Mackerras 			 * Wait until the parent tells us to go.
303051ae7f7SPaul Mackerras 			 */
304a92bef0fSFrederic Weisbecker 			if (read(go_pipe[0], &buf, 1) == -1)
305a92bef0fSFrederic Weisbecker 				perror("unable to read pipe");
306051ae7f7SPaul Mackerras 
307051ae7f7SPaul Mackerras 			execvp(argv[0], (char **)argv);
308051ae7f7SPaul Mackerras 
309051ae7f7SPaul Mackerras 			perror(argv[0]);
310051ae7f7SPaul Mackerras 			exit(-1);
311051ae7f7SPaul Mackerras 		}
312051ae7f7SPaul Mackerras 
313d6d901c2SZhang, Yanmin 		if (target_tid == -1 && target_pid == -1 && !system_wide)
3147e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
315d6d901c2SZhang, Yanmin 
316051ae7f7SPaul Mackerras 		/*
317051ae7f7SPaul Mackerras 		 * Wait for the child to be ready to exec.
318051ae7f7SPaul Mackerras 		 */
319051ae7f7SPaul Mackerras 		close(child_ready_pipe[1]);
320051ae7f7SPaul Mackerras 		close(go_pipe[0]);
321a92bef0fSFrederic Weisbecker 		if (read(child_ready_pipe[0], &buf, 1) == -1)
322a92bef0fSFrederic Weisbecker 			perror("unable to read pipe");
323051ae7f7SPaul Mackerras 		close(child_ready_pipe[0]);
32460666c63SLiming Wang 	}
325051ae7f7SPaul Mackerras 
326361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(counter, &evsel_list->entries, node) {
32748290609SArnaldo Carvalho de Melo 		if (create_perf_stat_counter(counter) < 0) {
32848290609SArnaldo Carvalho de Melo 			if (errno == -EPERM || errno == -EACCES) {
329d9cf837eSCorey Ashford 				error("You may not have permission to collect %sstats.\n"
330d9cf837eSCorey Ashford 				      "\t Consider tweaking"
331d9cf837eSCorey Ashford 				      " /proc/sys/kernel/perf_event_paranoid or running as root.",
332084ab9f8SArnaldo Carvalho de Melo 				      system_wide ? "system-wide " : "");
3335a3446bcSDavid Ahern 			} else if (errno == ENOENT) {
3345a3446bcSDavid Ahern 				error("%s event is not supported. ", event_name(counter));
33548290609SArnaldo Carvalho de Melo 			} else {
33648290609SArnaldo Carvalho de Melo 				error("open_counter returned with %d (%s). "
33748290609SArnaldo Carvalho de Melo 				      "/bin/dmesg may provide additional information.\n",
33848290609SArnaldo Carvalho de Melo 				       errno, strerror(errno));
33948290609SArnaldo Carvalho de Melo 			}
340084ab9f8SArnaldo Carvalho de Melo 			if (child_pid != -1)
341084ab9f8SArnaldo Carvalho de Melo 				kill(child_pid, SIGTERM);
34248290609SArnaldo Carvalho de Melo 			die("Not all events could be opened.\n");
343084ab9f8SArnaldo Carvalho de Melo 			return -1;
344084ab9f8SArnaldo Carvalho de Melo 		}
34548290609SArnaldo Carvalho de Melo 	}
34686470930SIngo Molnar 
347cfd748aeSFrederic Weisbecker 	if (perf_evlist__set_filters(evsel_list)) {
348cfd748aeSFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
349cfd748aeSFrederic Weisbecker 			strerror(errno));
350cfd748aeSFrederic Weisbecker 		return -1;
351cfd748aeSFrederic Weisbecker 	}
352cfd748aeSFrederic Weisbecker 
35386470930SIngo Molnar 	/*
35486470930SIngo Molnar 	 * Enable counters and exec the command:
35586470930SIngo Molnar 	 */
35686470930SIngo Molnar 	t0 = rdclock();
35786470930SIngo Molnar 
35860666c63SLiming Wang 	if (forks) {
359051ae7f7SPaul Mackerras 		close(go_pipe[1]);
36042202dd5SIngo Molnar 		wait(&status);
36160666c63SLiming Wang 	} else {
3626be2850eSZhang, Yanmin 		while(!done) sleep(1);
36360666c63SLiming Wang 	}
36486470930SIngo Molnar 
36586470930SIngo Molnar 	t1 = rdclock();
36686470930SIngo Molnar 
3679e9772c4SPeter Zijlstra 	update_stats(&walltime_nsecs_stats, t1 - t0);
36842202dd5SIngo Molnar 
369f5b4a9c3SStephane Eranian 	if (no_aggr) {
370361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
37142202dd5SIngo Molnar 			read_counter(counter);
3727e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
373f5b4a9c3SStephane Eranian 		}
374c52b12edSArnaldo Carvalho de Melo 	} else {
375361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
376c52b12edSArnaldo Carvalho de Melo 			read_counter_aggr(counter);
3777e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
3787e2ed097SArnaldo Carvalho de Melo 					     evsel_list->threads->nr);
379c52b12edSArnaldo Carvalho de Melo 		}
380c52b12edSArnaldo Carvalho de Melo 	}
381c52b12edSArnaldo Carvalho de Melo 
38242202dd5SIngo Molnar 	return WEXITSTATUS(status);
38342202dd5SIngo Molnar }
38442202dd5SIngo Molnar 
38569aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg)
38642202dd5SIngo Molnar {
38769aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps;
38869aad6f1SArnaldo Carvalho de Melo 
389849abde9SPeter Zijlstra 	if (run_count == 1)
390849abde9SPeter Zijlstra 		return;
391849abde9SPeter Zijlstra 
39269aad6f1SArnaldo Carvalho de Melo 	ps = evsel->priv;
393849abde9SPeter Zijlstra 	fprintf(stderr, "   ( +- %7.3f%% )",
39469aad6f1SArnaldo Carvalho de Melo 			100 * stddev_stats(&ps->res_stats[0]) / avg);
39542202dd5SIngo Molnar }
39642202dd5SIngo Molnar 
397daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
39842202dd5SIngo Molnar {
399506d4bc8SPeter Zijlstra 	double msecs = avg / 1e6;
400d7470b6aSStephane Eranian 	char cpustr[16] = { '\0', };
401d7470b6aSStephane Eranian 	const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
40242202dd5SIngo Molnar 
403f5b4a9c3SStephane Eranian 	if (no_aggr)
404d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
405d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
4067e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
407d7470b6aSStephane Eranian 
408daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
409d7470b6aSStephane Eranian 
410023695d9SStephane Eranian 	if (evsel->cgrp)
411023695d9SStephane Eranian 		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
412023695d9SStephane Eranian 
413d7470b6aSStephane Eranian 	if (csv_output)
414d7470b6aSStephane Eranian 		return;
41542202dd5SIngo Molnar 
416daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
417481f988aSIngo Molnar 		fprintf(stderr, " # %8.3f CPUs utilized          ", avg / avg_stats(&walltime_nsecs_stats));
41842202dd5SIngo Molnar }
41942202dd5SIngo Molnar 
420daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
42142202dd5SIngo Molnar {
422c7f7fea3SIngo Molnar 	double total, ratio = 0.0;
423f5b4a9c3SStephane Eranian 	char cpustr[16] = { '\0', };
424d7470b6aSStephane Eranian 	const char *fmt;
425d7470b6aSStephane Eranian 
426d7470b6aSStephane Eranian 	if (csv_output)
427d7470b6aSStephane Eranian 		fmt = "%s%.0f%s%s";
428d7470b6aSStephane Eranian 	else if (big_num)
429d7470b6aSStephane Eranian 		fmt = "%s%'18.0f%s%-24s";
430d7470b6aSStephane Eranian 	else
431d7470b6aSStephane Eranian 		fmt = "%s%18.0f%s%-24s";
432f5b4a9c3SStephane Eranian 
433f5b4a9c3SStephane Eranian 	if (no_aggr)
434d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
435d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
4367e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
437f5b4a9c3SStephane Eranian 	else
438f5b4a9c3SStephane Eranian 		cpu = 0;
439c7f7fea3SIngo Molnar 
440daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
441d7470b6aSStephane Eranian 
442023695d9SStephane Eranian 	if (evsel->cgrp)
443023695d9SStephane Eranian 		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
444023695d9SStephane Eranian 
445d7470b6aSStephane Eranian 	if (csv_output)
446d7470b6aSStephane Eranian 		return;
44742202dd5SIngo Molnar 
448daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
449f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_cycles_stats[cpu]);
450c7f7fea3SIngo Molnar 
451c7f7fea3SIngo Molnar 		if (total)
452c7f7fea3SIngo Molnar 			ratio = avg / total;
453c7f7fea3SIngo Molnar 
454481f988aSIngo Molnar 		fprintf(stderr, " #    %4.2f  insns per cycle", ratio);
455481f988aSIngo Molnar 
456481f988aSIngo Molnar 		total = avg_stats(&runtime_stalled_cycles_stats[cpu]);
457481f988aSIngo Molnar 
458481f988aSIngo Molnar 		if (total && avg) {
459481f988aSIngo Molnar 			ratio = total / avg;
460481f988aSIngo Molnar 			fprintf(stderr, "\n                                            #    %4.2f  stalled cycles per insn", ratio);
461481f988aSIngo Molnar 		}
462481f988aSIngo Molnar 
463daec78a0SArnaldo Carvalho de Melo 	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
464f5b4a9c3SStephane Eranian 			runtime_branches_stats[cpu].n != 0) {
465f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_branches_stats[cpu]);
46611018201SAnton Blanchard 
46711018201SAnton Blanchard 		if (total)
46811018201SAnton Blanchard 			ratio = avg * 100 / total;
46911018201SAnton Blanchard 
4701fc570adSIngo Molnar 		fprintf(stderr, " #   %5.2f  %% of all branches      ", ratio);
47111018201SAnton Blanchard 
472d58f4c82SIngo Molnar 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
473d58f4c82SIngo Molnar 			runtime_cacherefs_stats[cpu].n != 0) {
474d58f4c82SIngo Molnar 		total = avg_stats(&runtime_cacherefs_stats[cpu]);
475d58f4c82SIngo Molnar 
476d58f4c82SIngo Molnar 		if (total)
477d58f4c82SIngo Molnar 			ratio = avg * 100 / total;
478d58f4c82SIngo Molnar 
479481f988aSIngo Molnar 		fprintf(stderr, " # %8.3f %% of all cache refs    ", ratio);
480d58f4c82SIngo Molnar 
48111ba2b85SIngo Molnar 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES)) {
48211ba2b85SIngo Molnar 		total = avg_stats(&runtime_cycles_stats[cpu]);
48311ba2b85SIngo Molnar 
48411ba2b85SIngo Molnar 		if (total)
48511ba2b85SIngo Molnar 			ratio = avg / total * 100.0;
48611ba2b85SIngo Molnar 
487481f988aSIngo Molnar 		fprintf(stderr, " #   %5.2f%% of all cycles are idle ", ratio);
488481f988aSIngo Molnar 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
489481f988aSIngo Molnar 		total = avg_stats(&runtime_nsecs_stats[cpu]);
490481f988aSIngo Molnar 
491481f988aSIngo Molnar 		if (total)
492481f988aSIngo Molnar 			ratio = 1.0 * avg / total;
493481f988aSIngo Molnar 
494481f988aSIngo Molnar 		fprintf(stderr, " # %8.3f GHz                    ", ratio);
495481f988aSIngo Molnar 	} else if (runtime_nsecs_stats[cpu].n != 0) {
496481f988aSIngo Molnar 		total = avg_stats(&runtime_nsecs_stats[cpu]);
497481f988aSIngo Molnar 
498481f988aSIngo Molnar 		if (total)
499481f988aSIngo Molnar 			ratio = 1000.0 * avg / total;
500481f988aSIngo Molnar 
501481f988aSIngo Molnar 		fprintf(stderr, " # %8.3f M/sec                  ", ratio);
50242202dd5SIngo Molnar 	}
50342202dd5SIngo Molnar }
50442202dd5SIngo Molnar 
50542202dd5SIngo Molnar /*
50642202dd5SIngo Molnar  * Print out the results of a single counter:
507f5b4a9c3SStephane Eranian  * aggregated counts in system-wide mode
50842202dd5SIngo Molnar  */
50969aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter)
51042202dd5SIngo Molnar {
51169aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
51269aad6f1SArnaldo Carvalho de Melo 	double avg = avg_stats(&ps->res_stats[0]);
513c52b12edSArnaldo Carvalho de Melo 	int scaled = counter->counts->scaled;
51442202dd5SIngo Molnar 
51542202dd5SIngo Molnar 	if (scaled == -1) {
516023695d9SStephane Eranian 		fprintf(stderr, "%*s%s%*s",
517d7470b6aSStephane Eranian 			csv_output ? 0 : 18,
518023695d9SStephane Eranian 			"<not counted>",
519023695d9SStephane Eranian 			csv_sep,
520023695d9SStephane Eranian 			csv_output ? 0 : -24,
521023695d9SStephane Eranian 			event_name(counter));
522023695d9SStephane Eranian 
523023695d9SStephane Eranian 		if (counter->cgrp)
524023695d9SStephane Eranian 			fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
525023695d9SStephane Eranian 
526023695d9SStephane Eranian 		fputc('\n', stderr);
52742202dd5SIngo Molnar 		return;
52842202dd5SIngo Molnar 	}
52942202dd5SIngo Molnar 
53042202dd5SIngo Molnar 	if (nsec_counter(counter))
531f5b4a9c3SStephane Eranian 		nsec_printout(-1, counter, avg);
53242202dd5SIngo Molnar 	else
533f5b4a9c3SStephane Eranian 		abs_printout(-1, counter, avg);
534849abde9SPeter Zijlstra 
535d7470b6aSStephane Eranian 	if (csv_output) {
536d7470b6aSStephane Eranian 		fputc('\n', stderr);
537d7470b6aSStephane Eranian 		return;
538d7470b6aSStephane Eranian 	}
539d7470b6aSStephane Eranian 
540849abde9SPeter Zijlstra 	print_noise(counter, avg);
54142202dd5SIngo Molnar 
542506d4bc8SPeter Zijlstra 	if (scaled) {
543506d4bc8SPeter Zijlstra 		double avg_enabled, avg_running;
544506d4bc8SPeter Zijlstra 
54569aad6f1SArnaldo Carvalho de Melo 		avg_enabled = avg_stats(&ps->res_stats[1]);
54669aad6f1SArnaldo Carvalho de Melo 		avg_running = avg_stats(&ps->res_stats[2]);
547506d4bc8SPeter Zijlstra 
548210ad39fSIngo Molnar 		fprintf(stderr, "  (scaled from %.2f%%)",
549506d4bc8SPeter Zijlstra 				100 * avg_running / avg_enabled);
550506d4bc8SPeter Zijlstra 	}
55142202dd5SIngo Molnar 	fprintf(stderr, "\n");
55242202dd5SIngo Molnar }
55342202dd5SIngo Molnar 
554f5b4a9c3SStephane Eranian /*
555f5b4a9c3SStephane Eranian  * Print out the results of a single counter:
556f5b4a9c3SStephane Eranian  * does not use aggregated count in system-wide
557f5b4a9c3SStephane Eranian  */
55869aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter)
559f5b4a9c3SStephane Eranian {
560f5b4a9c3SStephane Eranian 	u64 ena, run, val;
561f5b4a9c3SStephane Eranian 	int cpu;
562f5b4a9c3SStephane Eranian 
5637e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
564c52b12edSArnaldo Carvalho de Melo 		val = counter->counts->cpu[cpu].val;
565c52b12edSArnaldo Carvalho de Melo 		ena = counter->counts->cpu[cpu].ena;
566c52b12edSArnaldo Carvalho de Melo 		run = counter->counts->cpu[cpu].run;
567f5b4a9c3SStephane Eranian 		if (run == 0 || ena == 0) {
568023695d9SStephane Eranian 			fprintf(stderr, "CPU%*d%s%*s%s%*s",
569d7470b6aSStephane Eranian 				csv_output ? 0 : -4,
5707e2ed097SArnaldo Carvalho de Melo 				evsel_list->cpus->map[cpu], csv_sep,
571d7470b6aSStephane Eranian 				csv_output ? 0 : 18,
572d7470b6aSStephane Eranian 				"<not counted>", csv_sep,
573023695d9SStephane Eranian 				csv_output ? 0 : -24,
574d7470b6aSStephane Eranian 				event_name(counter));
575f5b4a9c3SStephane Eranian 
576023695d9SStephane Eranian 			if (counter->cgrp)
577023695d9SStephane Eranian 				fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
578023695d9SStephane Eranian 
579023695d9SStephane Eranian 			fputc('\n', stderr);
580f5b4a9c3SStephane Eranian 			continue;
581f5b4a9c3SStephane Eranian 		}
582f5b4a9c3SStephane Eranian 
583f5b4a9c3SStephane Eranian 		if (nsec_counter(counter))
584f5b4a9c3SStephane Eranian 			nsec_printout(cpu, counter, val);
585f5b4a9c3SStephane Eranian 		else
586f5b4a9c3SStephane Eranian 			abs_printout(cpu, counter, val);
587f5b4a9c3SStephane Eranian 
588d7470b6aSStephane Eranian 		if (!csv_output) {
589f5b4a9c3SStephane Eranian 			print_noise(counter, 1.0);
590f5b4a9c3SStephane Eranian 
591f5b4a9c3SStephane Eranian 			if (run != ena) {
592f5b4a9c3SStephane Eranian 				fprintf(stderr, "  (scaled from %.2f%%)",
593f5b4a9c3SStephane Eranian 					100.0 * run / ena);
594f5b4a9c3SStephane Eranian 			}
595d7470b6aSStephane Eranian 		}
596023695d9SStephane Eranian 		fputc('\n', stderr);
597f5b4a9c3SStephane Eranian 	}
598f5b4a9c3SStephane Eranian }
599f5b4a9c3SStephane Eranian 
60042202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
60142202dd5SIngo Molnar {
60269aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
60369aad6f1SArnaldo Carvalho de Melo 	int i;
60442202dd5SIngo Molnar 
60586470930SIngo Molnar 	fflush(stdout);
60686470930SIngo Molnar 
607d7470b6aSStephane Eranian 	if (!csv_output) {
60886470930SIngo Molnar 		fprintf(stderr, "\n");
60960666c63SLiming Wang 		fprintf(stderr, " Performance counter stats for ");
610d6d901c2SZhang, Yanmin 		if(target_pid == -1 && target_tid == -1) {
61160666c63SLiming Wang 			fprintf(stderr, "\'%s", argv[0]);
61286470930SIngo Molnar 			for (i = 1; i < argc; i++)
61386470930SIngo Molnar 				fprintf(stderr, " %s", argv[i]);
614d6d901c2SZhang, Yanmin 		} else if (target_pid != -1)
615d6d901c2SZhang, Yanmin 			fprintf(stderr, "process id \'%d", target_pid);
616d6d901c2SZhang, Yanmin 		else
617d6d901c2SZhang, Yanmin 			fprintf(stderr, "thread id \'%d", target_tid);
61886470930SIngo Molnar 
61942202dd5SIngo Molnar 		fprintf(stderr, "\'");
62042202dd5SIngo Molnar 		if (run_count > 1)
62142202dd5SIngo Molnar 			fprintf(stderr, " (%d runs)", run_count);
62242202dd5SIngo Molnar 		fprintf(stderr, ":\n\n");
623d7470b6aSStephane Eranian 	}
62486470930SIngo Molnar 
625f5b4a9c3SStephane Eranian 	if (no_aggr) {
626361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
62786470930SIngo Molnar 			print_counter(counter);
628f5b4a9c3SStephane Eranian 	} else {
629361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
630f5b4a9c3SStephane Eranian 			print_counter_aggr(counter);
631f5b4a9c3SStephane Eranian 	}
63286470930SIngo Molnar 
633d7470b6aSStephane Eranian 	if (!csv_output) {
63486470930SIngo Molnar 		fprintf(stderr, "\n");
6355af52b51SStephane Eranian 		fprintf(stderr, " %18.9f  seconds time elapsed",
636506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats)/1e9);
637566747e6SIngo Molnar 		if (run_count > 1) {
638481f988aSIngo Molnar 			fprintf(stderr, "   ( +-%5.2f%% )",
639506d4bc8SPeter Zijlstra 				100*stddev_stats(&walltime_nsecs_stats) /
640506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats));
641566747e6SIngo Molnar 		}
642566747e6SIngo Molnar 		fprintf(stderr, "\n\n");
64386470930SIngo Molnar 	}
644d7470b6aSStephane Eranian }
64586470930SIngo Molnar 
646f7b7c26eSPeter Zijlstra static volatile int signr = -1;
647f7b7c26eSPeter Zijlstra 
64886470930SIngo Molnar static void skip_signal(int signo)
64986470930SIngo Molnar {
6506be2850eSZhang, Yanmin 	if(child_pid == -1)
65160666c63SLiming Wang 		done = 1;
65260666c63SLiming Wang 
653f7b7c26eSPeter Zijlstra 	signr = signo;
654f7b7c26eSPeter Zijlstra }
655f7b7c26eSPeter Zijlstra 
656f7b7c26eSPeter Zijlstra static void sig_atexit(void)
657f7b7c26eSPeter Zijlstra {
658933da83aSChris Wilson 	if (child_pid != -1)
659933da83aSChris Wilson 		kill(child_pid, SIGTERM);
660933da83aSChris Wilson 
661f7b7c26eSPeter Zijlstra 	if (signr == -1)
662f7b7c26eSPeter Zijlstra 		return;
663f7b7c26eSPeter Zijlstra 
664f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
665f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
66686470930SIngo Molnar }
66786470930SIngo Molnar 
66886470930SIngo Molnar static const char * const stat_usage[] = {
66960666c63SLiming Wang 	"perf stat [<options>] [<command>]",
67086470930SIngo Molnar 	NULL
67186470930SIngo Molnar };
67286470930SIngo Molnar 
673d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used,
674d7470b6aSStephane Eranian 			     const char *s __used, int unset)
675d7470b6aSStephane Eranian {
676d7470b6aSStephane Eranian 	big_num_opt = unset ? 0 : 1;
677d7470b6aSStephane Eranian 	return 0;
678d7470b6aSStephane Eranian }
679d7470b6aSStephane Eranian 
68086470930SIngo Molnar static const struct option options[] = {
681361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
68286470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
68386470930SIngo Molnar 		     parse_events),
684cfd748aeSFrederic Weisbecker 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
685cfd748aeSFrederic Weisbecker 		     "event filter", parse_filter),
6862e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
6872e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
68886470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
689d6d901c2SZhang, Yanmin 		    "stat events on existing process id"),
690d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
691d6d901c2SZhang, Yanmin 		    "stat events on existing thread id"),
69286470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
69386470930SIngo Molnar 		    "system-wide collection from all CPUs"),
694b26bc5a7SBrice Goglin 	OPT_BOOLEAN('c', "scale", &scale,
69586470930SIngo Molnar 		    "scale/normalize counters"),
696c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
697743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
69842202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
69942202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
7000cfb7a13SIngo Molnar 	OPT_BOOLEAN('n', "null", &null_run,
7010cfb7a13SIngo Molnar 		    "null run - dont start any counters"),
702d7470b6aSStephane Eranian 	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
703d7470b6aSStephane Eranian 			   "print large numbers with thousands\' separators",
704d7470b6aSStephane Eranian 			   stat__set_big_num),
705c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
706c45c6ea2SStephane Eranian 		    "list of cpus to monitor in system-wide"),
707f5b4a9c3SStephane Eranian 	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
708f5b4a9c3SStephane Eranian 		    "disable CPU count aggregation"),
709d7470b6aSStephane Eranian 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
710d7470b6aSStephane Eranian 		   "print counts with custom separator"),
711023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
712023695d9SStephane Eranian 		     "monitor event in cgroup name only",
713023695d9SStephane Eranian 		     parse_cgroups),
71486470930SIngo Molnar 	OPT_END()
71586470930SIngo Molnar };
71686470930SIngo Molnar 
717f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used)
71886470930SIngo Molnar {
71969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
72069aad6f1SArnaldo Carvalho de Melo 	int status = -ENOMEM;
72142202dd5SIngo Molnar 
7225af52b51SStephane Eranian 	setlocale(LC_ALL, "");
7235af52b51SStephane Eranian 
7247e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
725361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
726361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
727361c99a6SArnaldo Carvalho de Melo 
728a0541234SAnton Blanchard 	argc = parse_options(argc, argv, options, stat_usage,
729a0541234SAnton Blanchard 		PARSE_OPT_STOP_AT_NON_OPTION);
730d7470b6aSStephane Eranian 
731d7470b6aSStephane Eranian 	if (csv_sep)
732d7470b6aSStephane Eranian 		csv_output = true;
733d7470b6aSStephane Eranian 	else
734d7470b6aSStephane Eranian 		csv_sep = DEFAULT_SEPARATOR;
735d7470b6aSStephane Eranian 
736d7470b6aSStephane Eranian 	/*
737d7470b6aSStephane Eranian 	 * let the spreadsheet do the pretty-printing
738d7470b6aSStephane Eranian 	 */
739d7470b6aSStephane Eranian 	if (csv_output) {
740d7470b6aSStephane Eranian 		/* User explicitely passed -B? */
741d7470b6aSStephane Eranian 		if (big_num_opt == 1) {
742d7470b6aSStephane Eranian 			fprintf(stderr, "-B option not supported with -x\n");
743d7470b6aSStephane Eranian 			usage_with_options(stat_usage, options);
744d7470b6aSStephane Eranian 		} else /* Nope, so disable big number formatting */
745d7470b6aSStephane Eranian 			big_num = false;
746d7470b6aSStephane Eranian 	} else if (big_num_opt == 0) /* User passed --no-big-num */
747d7470b6aSStephane Eranian 		big_num = false;
748d7470b6aSStephane Eranian 
749d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1)
75086470930SIngo Molnar 		usage_with_options(stat_usage, options);
7519e9772c4SPeter Zijlstra 	if (run_count <= 0)
75242202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
75386470930SIngo Molnar 
754023695d9SStephane Eranian 	/* no_aggr, cgroup are for system-wide only */
755023695d9SStephane Eranian 	if ((no_aggr || nr_cgroups) && !system_wide) {
756023695d9SStephane Eranian 		fprintf(stderr, "both cgroup and no-aggregation "
757023695d9SStephane Eranian 			"modes only available in system-wide mode\n");
758023695d9SStephane Eranian 
759f5b4a9c3SStephane Eranian 		usage_with_options(stat_usage, options);
760023695d9SStephane Eranian 	}
761f5b4a9c3SStephane Eranian 
762c3043569SJaswinder Singh Rajput 	/* Set attrs and nr_counters if no event is selected and !null_run */
763361c99a6SArnaldo Carvalho de Melo 	if (!null_run && !evsel_list->nr_entries) {
76469aad6f1SArnaldo Carvalho de Melo 		size_t c;
76569aad6f1SArnaldo Carvalho de Melo 
76669aad6f1SArnaldo Carvalho de Melo 		for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
767361c99a6SArnaldo Carvalho de Melo 			pos = perf_evsel__new(&default_attrs[c], c);
76869aad6f1SArnaldo Carvalho de Melo 			if (pos == NULL)
76969aad6f1SArnaldo Carvalho de Melo 				goto out;
770361c99a6SArnaldo Carvalho de Melo 			perf_evlist__add(evsel_list, pos);
77169aad6f1SArnaldo Carvalho de Melo 		}
772c3043569SJaswinder Singh Rajput 	}
77386470930SIngo Molnar 
7745c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
7755c98d466SArnaldo Carvalho de Melo 		target_tid = target_pid;
7765c98d466SArnaldo Carvalho de Melo 
7777e2ed097SArnaldo Carvalho de Melo 	evsel_list->threads = thread_map__new(target_pid, target_tid);
7787e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->threads == NULL) {
7795c98d466SArnaldo Carvalho de Melo 		pr_err("Problems finding threads of monitor\n");
7805c98d466SArnaldo Carvalho de Melo 		usage_with_options(stat_usage, options);
7815c98d466SArnaldo Carvalho de Melo 	}
7825c98d466SArnaldo Carvalho de Melo 
783a12b51c4SPaul Mackerras 	if (system_wide)
7847e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__new(cpu_list);
785a12b51c4SPaul Mackerras 	else
7867e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__dummy_new();
78786470930SIngo Molnar 
7887e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->cpus == NULL) {
78960d567e2SArnaldo Carvalho de Melo 		perror("failed to parse CPUs map");
790c45c6ea2SStephane Eranian 		usage_with_options(stat_usage, options);
79160d567e2SArnaldo Carvalho de Melo 		return -1;
79260d567e2SArnaldo Carvalho de Melo 	}
793c45c6ea2SStephane Eranian 
794361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
795c52b12edSArnaldo Carvalho de Melo 		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
7967e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
7977e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
79869aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
799d6d901c2SZhang, Yanmin 	}
800d6d901c2SZhang, Yanmin 
80186470930SIngo Molnar 	/*
80286470930SIngo Molnar 	 * We dont want to block the signals - that would cause
80386470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
80486470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
80586470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
80686470930SIngo Molnar 	 */
807f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
80886470930SIngo Molnar 	signal(SIGINT,  skip_signal);
80986470930SIngo Molnar 	signal(SIGALRM, skip_signal);
81086470930SIngo Molnar 	signal(SIGABRT, skip_signal);
81186470930SIngo Molnar 
81242202dd5SIngo Molnar 	status = 0;
81342202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
81442202dd5SIngo Molnar 		if (run_count != 1 && verbose)
81542202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
81642202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
81742202dd5SIngo Molnar 	}
81842202dd5SIngo Molnar 
819084ab9f8SArnaldo Carvalho de Melo 	if (status != -1)
82042202dd5SIngo Molnar 		print_stat(argc, argv);
82169aad6f1SArnaldo Carvalho de Melo out_free_fd:
822361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node)
82369aad6f1SArnaldo Carvalho de Melo 		perf_evsel__free_stat_priv(pos);
8247e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
8250015e2e1SArnaldo Carvalho de Melo out:
8260015e2e1SArnaldo Carvalho de Melo 	perf_evlist__delete(evsel_list);
82742202dd5SIngo Molnar 	return status;
82886470930SIngo Molnar }
829