xref: /openbmc/linux/tools/perf/builtin-stat.c (revision 7e2ed097)
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 
17048290609SArnaldo Carvalho de Melo 	if (system_wide)
1717e2ed097SArnaldo Carvalho de Melo 		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
172f37a291cSIngo Molnar 
1732e6cdf99SStephane Eranian 	attr->inherit = !no_inherit;
1742e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1) {
17586470930SIngo Molnar 		attr->disabled = 1;
17657e7986eSPaul Mackerras 		attr->enable_on_exec = 1;
1776be2850eSZhang, Yanmin 	}
178084ab9f8SArnaldo Carvalho de Melo 
1797e2ed097SArnaldo Carvalho de Melo 	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
18086470930SIngo Molnar }
18186470930SIngo Molnar 
18286470930SIngo Molnar /*
18386470930SIngo Molnar  * Does the counter have nsecs as a unit?
18486470930SIngo Molnar  */
185daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel)
18686470930SIngo Molnar {
187daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
188daec78a0SArnaldo Carvalho de Melo 	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
18986470930SIngo Molnar 		return 1;
19086470930SIngo Molnar 
19186470930SIngo Molnar 	return 0;
19286470930SIngo Molnar }
19386470930SIngo Molnar 
19486470930SIngo Molnar /*
19586470930SIngo Molnar  * Read out the results of a single counter:
196f5b4a9c3SStephane Eranian  * aggregate counts across CPUs in system-wide mode
19786470930SIngo Molnar  */
198c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter)
19986470930SIngo Molnar {
20069aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
201c52b12edSArnaldo Carvalho de Melo 	u64 *count = counter->counts->aggr.values;
202c52b12edSArnaldo Carvalho de Melo 	int i;
20386470930SIngo Molnar 
2047e2ed097SArnaldo Carvalho de Melo 	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
2057e2ed097SArnaldo Carvalho de Melo 			       evsel_list->threads->nr, scale) < 0)
206c52b12edSArnaldo Carvalho de Melo 		return -1;
2079e9772c4SPeter Zijlstra 
2089e9772c4SPeter Zijlstra 	for (i = 0; i < 3; i++)
20969aad6f1SArnaldo Carvalho de Melo 		update_stats(&ps->res_stats[i], count[i]);
2109e9772c4SPeter Zijlstra 
2119e9772c4SPeter Zijlstra 	if (verbose) {
2129486aa38SArnaldo Carvalho de Melo 		fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
2139486aa38SArnaldo Carvalho de Melo 			event_name(counter), count[0], count[1], count[2]);
2149e9772c4SPeter Zijlstra 	}
2159e9772c4SPeter Zijlstra 
21686470930SIngo Molnar 	/*
21786470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
21886470930SIngo Molnar 	 */
219daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
220f5b4a9c3SStephane Eranian 		update_stats(&runtime_nsecs_stats[0], count[0]);
221daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
222f5b4a9c3SStephane Eranian 		update_stats(&runtime_cycles_stats[0], count[0]);
223daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
224f5b4a9c3SStephane Eranian 		update_stats(&runtime_branches_stats[0], count[0]);
225c52b12edSArnaldo Carvalho de Melo 
226c52b12edSArnaldo Carvalho de Melo 	return 0;
227f5b4a9c3SStephane Eranian }
228f5b4a9c3SStephane Eranian 
229f5b4a9c3SStephane Eranian /*
230f5b4a9c3SStephane Eranian  * Read out the results of a single counter:
231f5b4a9c3SStephane Eranian  * do not aggregate counts across CPUs in system-wide mode
232f5b4a9c3SStephane Eranian  */
233c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter)
234f5b4a9c3SStephane Eranian {
235c52b12edSArnaldo Carvalho de Melo 	u64 *count;
236f5b4a9c3SStephane Eranian 	int cpu;
237f5b4a9c3SStephane Eranian 
2387e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
239c52b12edSArnaldo Carvalho de Melo 		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
240c52b12edSArnaldo Carvalho de Melo 			return -1;
241f5b4a9c3SStephane Eranian 
242c52b12edSArnaldo Carvalho de Melo 		count = counter->counts->cpu[cpu].values;
243f5b4a9c3SStephane Eranian 
244daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
245f5b4a9c3SStephane Eranian 			update_stats(&runtime_nsecs_stats[cpu], count[0]);
246daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
247f5b4a9c3SStephane Eranian 			update_stats(&runtime_cycles_stats[cpu], count[0]);
248daec78a0SArnaldo Carvalho de Melo 		if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
249f5b4a9c3SStephane Eranian 			update_stats(&runtime_branches_stats[cpu], count[0]);
250f5b4a9c3SStephane Eranian 	}
251c52b12edSArnaldo Carvalho de Melo 
252c52b12edSArnaldo Carvalho de Melo 	return 0;
25386470930SIngo Molnar }
25486470930SIngo Molnar 
255f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv)
25686470930SIngo Molnar {
25786470930SIngo Molnar 	unsigned long long t0, t1;
25869aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
25942202dd5SIngo Molnar 	int status = 0;
260051ae7f7SPaul Mackerras 	int child_ready_pipe[2], go_pipe[2];
2616be2850eSZhang, Yanmin 	const bool forks = (argc > 0);
262051ae7f7SPaul Mackerras 	char buf;
26386470930SIngo Molnar 
26460666c63SLiming Wang 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
265051ae7f7SPaul Mackerras 		perror("failed to create pipes");
266051ae7f7SPaul Mackerras 		exit(1);
267051ae7f7SPaul Mackerras 	}
268051ae7f7SPaul Mackerras 
26960666c63SLiming Wang 	if (forks) {
2706be2850eSZhang, Yanmin 		if ((child_pid = fork()) < 0)
271051ae7f7SPaul Mackerras 			perror("failed to fork");
272051ae7f7SPaul Mackerras 
2736be2850eSZhang, Yanmin 		if (!child_pid) {
274051ae7f7SPaul Mackerras 			close(child_ready_pipe[0]);
275051ae7f7SPaul Mackerras 			close(go_pipe[1]);
276051ae7f7SPaul Mackerras 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
277051ae7f7SPaul Mackerras 
278051ae7f7SPaul Mackerras 			/*
279051ae7f7SPaul Mackerras 			 * Do a dummy execvp to get the PLT entry resolved,
280051ae7f7SPaul Mackerras 			 * so we avoid the resolver overhead on the real
281051ae7f7SPaul Mackerras 			 * execvp call.
282051ae7f7SPaul Mackerras 			 */
283051ae7f7SPaul Mackerras 			execvp("", (char **)argv);
284051ae7f7SPaul Mackerras 
285051ae7f7SPaul Mackerras 			/*
286051ae7f7SPaul Mackerras 			 * Tell the parent we're ready to go
287051ae7f7SPaul Mackerras 			 */
288051ae7f7SPaul Mackerras 			close(child_ready_pipe[1]);
289051ae7f7SPaul Mackerras 
290051ae7f7SPaul Mackerras 			/*
291051ae7f7SPaul Mackerras 			 * Wait until the parent tells us to go.
292051ae7f7SPaul Mackerras 			 */
293a92bef0fSFrederic Weisbecker 			if (read(go_pipe[0], &buf, 1) == -1)
294a92bef0fSFrederic Weisbecker 				perror("unable to read pipe");
295051ae7f7SPaul Mackerras 
296051ae7f7SPaul Mackerras 			execvp(argv[0], (char **)argv);
297051ae7f7SPaul Mackerras 
298051ae7f7SPaul Mackerras 			perror(argv[0]);
299051ae7f7SPaul Mackerras 			exit(-1);
300051ae7f7SPaul Mackerras 		}
301051ae7f7SPaul Mackerras 
302d6d901c2SZhang, Yanmin 		if (target_tid == -1 && target_pid == -1 && !system_wide)
3037e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
304d6d901c2SZhang, Yanmin 
305051ae7f7SPaul Mackerras 		/*
306051ae7f7SPaul Mackerras 		 * Wait for the child to be ready to exec.
307051ae7f7SPaul Mackerras 		 */
308051ae7f7SPaul Mackerras 		close(child_ready_pipe[1]);
309051ae7f7SPaul Mackerras 		close(go_pipe[0]);
310a92bef0fSFrederic Weisbecker 		if (read(child_ready_pipe[0], &buf, 1) == -1)
311a92bef0fSFrederic Weisbecker 			perror("unable to read pipe");
312051ae7f7SPaul Mackerras 		close(child_ready_pipe[0]);
31360666c63SLiming Wang 	}
314051ae7f7SPaul Mackerras 
315361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(counter, &evsel_list->entries, node) {
31648290609SArnaldo Carvalho de Melo 		if (create_perf_stat_counter(counter) < 0) {
31748290609SArnaldo Carvalho de Melo 			if (errno == -EPERM || errno == -EACCES) {
318d9cf837eSCorey Ashford 				error("You may not have permission to collect %sstats.\n"
319d9cf837eSCorey Ashford 				      "\t Consider tweaking"
320d9cf837eSCorey Ashford 				      " /proc/sys/kernel/perf_event_paranoid or running as root.",
321084ab9f8SArnaldo Carvalho de Melo 				      system_wide ? "system-wide " : "");
3225a3446bcSDavid Ahern 			} else if (errno == ENOENT) {
3235a3446bcSDavid Ahern 				error("%s event is not supported. ", event_name(counter));
32448290609SArnaldo Carvalho de Melo 			} else {
32548290609SArnaldo Carvalho de Melo 				error("open_counter returned with %d (%s). "
32648290609SArnaldo Carvalho de Melo 				      "/bin/dmesg may provide additional information.\n",
32748290609SArnaldo Carvalho de Melo 				       errno, strerror(errno));
32848290609SArnaldo Carvalho de Melo 			}
329084ab9f8SArnaldo Carvalho de Melo 			if (child_pid != -1)
330084ab9f8SArnaldo Carvalho de Melo 				kill(child_pid, SIGTERM);
33148290609SArnaldo Carvalho de Melo 			die("Not all events could be opened.\n");
332084ab9f8SArnaldo Carvalho de Melo 			return -1;
333084ab9f8SArnaldo Carvalho de Melo 		}
33448290609SArnaldo Carvalho de Melo 	}
33586470930SIngo Molnar 
33686470930SIngo Molnar 	/*
33786470930SIngo Molnar 	 * Enable counters and exec the command:
33886470930SIngo Molnar 	 */
33986470930SIngo Molnar 	t0 = rdclock();
34086470930SIngo Molnar 
34160666c63SLiming Wang 	if (forks) {
342051ae7f7SPaul Mackerras 		close(go_pipe[1]);
34342202dd5SIngo Molnar 		wait(&status);
34460666c63SLiming Wang 	} else {
3456be2850eSZhang, Yanmin 		while(!done) sleep(1);
34660666c63SLiming Wang 	}
34786470930SIngo Molnar 
34886470930SIngo Molnar 	t1 = rdclock();
34986470930SIngo Molnar 
3509e9772c4SPeter Zijlstra 	update_stats(&walltime_nsecs_stats, t1 - t0);
35142202dd5SIngo Molnar 
352f5b4a9c3SStephane Eranian 	if (no_aggr) {
353361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
35442202dd5SIngo Molnar 			read_counter(counter);
3557e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
356f5b4a9c3SStephane Eranian 		}
357c52b12edSArnaldo Carvalho de Melo 	} else {
358361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node) {
359c52b12edSArnaldo Carvalho de Melo 			read_counter_aggr(counter);
3607e2ed097SArnaldo Carvalho de Melo 			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
3617e2ed097SArnaldo Carvalho de Melo 					     evsel_list->threads->nr);
362c52b12edSArnaldo Carvalho de Melo 		}
363c52b12edSArnaldo Carvalho de Melo 	}
364c52b12edSArnaldo Carvalho de Melo 
36542202dd5SIngo Molnar 	return WEXITSTATUS(status);
36642202dd5SIngo Molnar }
36742202dd5SIngo Molnar 
36869aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg)
36942202dd5SIngo Molnar {
37069aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps;
37169aad6f1SArnaldo Carvalho de Melo 
372849abde9SPeter Zijlstra 	if (run_count == 1)
373849abde9SPeter Zijlstra 		return;
374849abde9SPeter Zijlstra 
37569aad6f1SArnaldo Carvalho de Melo 	ps = evsel->priv;
376849abde9SPeter Zijlstra 	fprintf(stderr, "   ( +- %7.3f%% )",
37769aad6f1SArnaldo Carvalho de Melo 			100 * stddev_stats(&ps->res_stats[0]) / avg);
37842202dd5SIngo Molnar }
37942202dd5SIngo Molnar 
380daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
38142202dd5SIngo Molnar {
382506d4bc8SPeter Zijlstra 	double msecs = avg / 1e6;
383d7470b6aSStephane Eranian 	char cpustr[16] = { '\0', };
384d7470b6aSStephane Eranian 	const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
38542202dd5SIngo Molnar 
386f5b4a9c3SStephane Eranian 	if (no_aggr)
387d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
388d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
3897e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
390d7470b6aSStephane Eranian 
391daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
392d7470b6aSStephane Eranian 
393d7470b6aSStephane Eranian 	if (csv_output)
394d7470b6aSStephane Eranian 		return;
39542202dd5SIngo Molnar 
396daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
39742202dd5SIngo Molnar 		fprintf(stderr, " # %10.3f CPUs ",
398506d4bc8SPeter Zijlstra 				avg / avg_stats(&walltime_nsecs_stats));
39942202dd5SIngo Molnar }
40042202dd5SIngo Molnar 
401daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
40242202dd5SIngo Molnar {
403c7f7fea3SIngo Molnar 	double total, ratio = 0.0;
404f5b4a9c3SStephane Eranian 	char cpustr[16] = { '\0', };
405d7470b6aSStephane Eranian 	const char *fmt;
406d7470b6aSStephane Eranian 
407d7470b6aSStephane Eranian 	if (csv_output)
408d7470b6aSStephane Eranian 		fmt = "%s%.0f%s%s";
409d7470b6aSStephane Eranian 	else if (big_num)
410d7470b6aSStephane Eranian 		fmt = "%s%'18.0f%s%-24s";
411d7470b6aSStephane Eranian 	else
412d7470b6aSStephane Eranian 		fmt = "%s%18.0f%s%-24s";
413f5b4a9c3SStephane Eranian 
414f5b4a9c3SStephane Eranian 	if (no_aggr)
415d7470b6aSStephane Eranian 		sprintf(cpustr, "CPU%*d%s",
416d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
4177e2ed097SArnaldo Carvalho de Melo 			evsel_list->cpus->map[cpu], csv_sep);
418f5b4a9c3SStephane Eranian 	else
419f5b4a9c3SStephane Eranian 		cpu = 0;
420c7f7fea3SIngo Molnar 
421daec78a0SArnaldo Carvalho de Melo 	fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
422d7470b6aSStephane Eranian 
423d7470b6aSStephane Eranian 	if (csv_output)
424d7470b6aSStephane Eranian 		return;
42542202dd5SIngo Molnar 
426daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
427f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_cycles_stats[cpu]);
428c7f7fea3SIngo Molnar 
429c7f7fea3SIngo Molnar 		if (total)
430c7f7fea3SIngo Molnar 			ratio = avg / total;
431c7f7fea3SIngo Molnar 
432c7f7fea3SIngo Molnar 		fprintf(stderr, " # %10.3f IPC  ", ratio);
433daec78a0SArnaldo Carvalho de Melo 	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
434f5b4a9c3SStephane Eranian 			runtime_branches_stats[cpu].n != 0) {
435f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_branches_stats[cpu]);
43611018201SAnton Blanchard 
43711018201SAnton Blanchard 		if (total)
43811018201SAnton Blanchard 			ratio = avg * 100 / total;
43911018201SAnton Blanchard 
44011018201SAnton Blanchard 		fprintf(stderr, " # %10.3f %%    ", ratio);
44111018201SAnton Blanchard 
442f5b4a9c3SStephane Eranian 	} else if (runtime_nsecs_stats[cpu].n != 0) {
443f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_nsecs_stats[cpu]);
444c7f7fea3SIngo Molnar 
445c7f7fea3SIngo Molnar 		if (total)
446c7f7fea3SIngo Molnar 			ratio = 1000.0 * avg / total;
447c7f7fea3SIngo Molnar 
448c7f7fea3SIngo Molnar 		fprintf(stderr, " # %10.3f M/sec", ratio);
44942202dd5SIngo Molnar 	}
45042202dd5SIngo Molnar }
45142202dd5SIngo Molnar 
45242202dd5SIngo Molnar /*
45342202dd5SIngo Molnar  * Print out the results of a single counter:
454f5b4a9c3SStephane Eranian  * aggregated counts in system-wide mode
45542202dd5SIngo Molnar  */
45669aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter)
45742202dd5SIngo Molnar {
45869aad6f1SArnaldo Carvalho de Melo 	struct perf_stat *ps = counter->priv;
45969aad6f1SArnaldo Carvalho de Melo 	double avg = avg_stats(&ps->res_stats[0]);
460c52b12edSArnaldo Carvalho de Melo 	int scaled = counter->counts->scaled;
46142202dd5SIngo Molnar 
46242202dd5SIngo Molnar 	if (scaled == -1) {
463d7470b6aSStephane Eranian 		fprintf(stderr, "%*s%s%-24s\n",
464d7470b6aSStephane Eranian 			csv_output ? 0 : 18,
465d7470b6aSStephane Eranian 			"<not counted>", csv_sep, event_name(counter));
46642202dd5SIngo Molnar 		return;
46742202dd5SIngo Molnar 	}
46842202dd5SIngo Molnar 
46942202dd5SIngo Molnar 	if (nsec_counter(counter))
470f5b4a9c3SStephane Eranian 		nsec_printout(-1, counter, avg);
47142202dd5SIngo Molnar 	else
472f5b4a9c3SStephane Eranian 		abs_printout(-1, counter, avg);
473849abde9SPeter Zijlstra 
474d7470b6aSStephane Eranian 	if (csv_output) {
475d7470b6aSStephane Eranian 		fputc('\n', stderr);
476d7470b6aSStephane Eranian 		return;
477d7470b6aSStephane Eranian 	}
478d7470b6aSStephane Eranian 
479849abde9SPeter Zijlstra 	print_noise(counter, avg);
48042202dd5SIngo Molnar 
481506d4bc8SPeter Zijlstra 	if (scaled) {
482506d4bc8SPeter Zijlstra 		double avg_enabled, avg_running;
483506d4bc8SPeter Zijlstra 
48469aad6f1SArnaldo Carvalho de Melo 		avg_enabled = avg_stats(&ps->res_stats[1]);
48569aad6f1SArnaldo Carvalho de Melo 		avg_running = avg_stats(&ps->res_stats[2]);
486506d4bc8SPeter Zijlstra 
487210ad39fSIngo Molnar 		fprintf(stderr, "  (scaled from %.2f%%)",
488506d4bc8SPeter Zijlstra 				100 * avg_running / avg_enabled);
489506d4bc8SPeter Zijlstra 	}
49042202dd5SIngo Molnar 
49142202dd5SIngo Molnar 	fprintf(stderr, "\n");
49242202dd5SIngo Molnar }
49342202dd5SIngo Molnar 
494f5b4a9c3SStephane Eranian /*
495f5b4a9c3SStephane Eranian  * Print out the results of a single counter:
496f5b4a9c3SStephane Eranian  * does not use aggregated count in system-wide
497f5b4a9c3SStephane Eranian  */
49869aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter)
499f5b4a9c3SStephane Eranian {
500f5b4a9c3SStephane Eranian 	u64 ena, run, val;
501f5b4a9c3SStephane Eranian 	int cpu;
502f5b4a9c3SStephane Eranian 
5037e2ed097SArnaldo Carvalho de Melo 	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
504c52b12edSArnaldo Carvalho de Melo 		val = counter->counts->cpu[cpu].val;
505c52b12edSArnaldo Carvalho de Melo 		ena = counter->counts->cpu[cpu].ena;
506c52b12edSArnaldo Carvalho de Melo 		run = counter->counts->cpu[cpu].run;
507f5b4a9c3SStephane Eranian 		if (run == 0 || ena == 0) {
508d7470b6aSStephane Eranian 			fprintf(stderr, "CPU%*d%s%*s%s%-24s",
509d7470b6aSStephane Eranian 				csv_output ? 0 : -4,
5107e2ed097SArnaldo Carvalho de Melo 				evsel_list->cpus->map[cpu], csv_sep,
511d7470b6aSStephane Eranian 				csv_output ? 0 : 18,
512d7470b6aSStephane Eranian 				"<not counted>", csv_sep,
513d7470b6aSStephane Eranian 				event_name(counter));
514f5b4a9c3SStephane Eranian 
515f5b4a9c3SStephane Eranian 			fprintf(stderr, "\n");
516f5b4a9c3SStephane Eranian 			continue;
517f5b4a9c3SStephane Eranian 		}
518f5b4a9c3SStephane Eranian 
519f5b4a9c3SStephane Eranian 		if (nsec_counter(counter))
520f5b4a9c3SStephane Eranian 			nsec_printout(cpu, counter, val);
521f5b4a9c3SStephane Eranian 		else
522f5b4a9c3SStephane Eranian 			abs_printout(cpu, counter, val);
523f5b4a9c3SStephane Eranian 
524d7470b6aSStephane Eranian 		if (!csv_output) {
525f5b4a9c3SStephane Eranian 			print_noise(counter, 1.0);
526f5b4a9c3SStephane Eranian 
527f5b4a9c3SStephane Eranian 			if (run != ena) {
528f5b4a9c3SStephane Eranian 				fprintf(stderr, "  (scaled from %.2f%%)",
529f5b4a9c3SStephane Eranian 					100.0 * run / ena);
530f5b4a9c3SStephane Eranian 			}
531d7470b6aSStephane Eranian 		}
532f5b4a9c3SStephane Eranian 		fprintf(stderr, "\n");
533f5b4a9c3SStephane Eranian 	}
534f5b4a9c3SStephane Eranian }
535f5b4a9c3SStephane Eranian 
53642202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
53742202dd5SIngo Molnar {
53869aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *counter;
53969aad6f1SArnaldo Carvalho de Melo 	int i;
54042202dd5SIngo Molnar 
54186470930SIngo Molnar 	fflush(stdout);
54286470930SIngo Molnar 
543d7470b6aSStephane Eranian 	if (!csv_output) {
54486470930SIngo Molnar 		fprintf(stderr, "\n");
54560666c63SLiming Wang 		fprintf(stderr, " Performance counter stats for ");
546d6d901c2SZhang, Yanmin 		if(target_pid == -1 && target_tid == -1) {
54760666c63SLiming Wang 			fprintf(stderr, "\'%s", argv[0]);
54886470930SIngo Molnar 			for (i = 1; i < argc; i++)
54986470930SIngo Molnar 				fprintf(stderr, " %s", argv[i]);
550d6d901c2SZhang, Yanmin 		} else if (target_pid != -1)
551d6d901c2SZhang, Yanmin 			fprintf(stderr, "process id \'%d", target_pid);
552d6d901c2SZhang, Yanmin 		else
553d6d901c2SZhang, Yanmin 			fprintf(stderr, "thread id \'%d", target_tid);
55486470930SIngo Molnar 
55542202dd5SIngo Molnar 		fprintf(stderr, "\'");
55642202dd5SIngo Molnar 		if (run_count > 1)
55742202dd5SIngo Molnar 			fprintf(stderr, " (%d runs)", run_count);
55842202dd5SIngo Molnar 		fprintf(stderr, ":\n\n");
559d7470b6aSStephane Eranian 	}
56086470930SIngo Molnar 
561f5b4a9c3SStephane Eranian 	if (no_aggr) {
562361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
56386470930SIngo Molnar 			print_counter(counter);
564f5b4a9c3SStephane Eranian 	} else {
565361c99a6SArnaldo Carvalho de Melo 		list_for_each_entry(counter, &evsel_list->entries, node)
566f5b4a9c3SStephane Eranian 			print_counter_aggr(counter);
567f5b4a9c3SStephane Eranian 	}
56886470930SIngo Molnar 
569d7470b6aSStephane Eranian 	if (!csv_output) {
57086470930SIngo Molnar 		fprintf(stderr, "\n");
5715af52b51SStephane Eranian 		fprintf(stderr, " %18.9f  seconds time elapsed",
572506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats)/1e9);
573566747e6SIngo Molnar 		if (run_count > 1) {
574566747e6SIngo Molnar 			fprintf(stderr, "   ( +- %7.3f%% )",
575506d4bc8SPeter Zijlstra 				100*stddev_stats(&walltime_nsecs_stats) /
576506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats));
577566747e6SIngo Molnar 		}
578566747e6SIngo Molnar 		fprintf(stderr, "\n\n");
57986470930SIngo Molnar 	}
580d7470b6aSStephane Eranian }
58186470930SIngo Molnar 
582f7b7c26eSPeter Zijlstra static volatile int signr = -1;
583f7b7c26eSPeter Zijlstra 
58486470930SIngo Molnar static void skip_signal(int signo)
58586470930SIngo Molnar {
5866be2850eSZhang, Yanmin 	if(child_pid == -1)
58760666c63SLiming Wang 		done = 1;
58860666c63SLiming Wang 
589f7b7c26eSPeter Zijlstra 	signr = signo;
590f7b7c26eSPeter Zijlstra }
591f7b7c26eSPeter Zijlstra 
592f7b7c26eSPeter Zijlstra static void sig_atexit(void)
593f7b7c26eSPeter Zijlstra {
594933da83aSChris Wilson 	if (child_pid != -1)
595933da83aSChris Wilson 		kill(child_pid, SIGTERM);
596933da83aSChris Wilson 
597f7b7c26eSPeter Zijlstra 	if (signr == -1)
598f7b7c26eSPeter Zijlstra 		return;
599f7b7c26eSPeter Zijlstra 
600f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
601f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
60286470930SIngo Molnar }
60386470930SIngo Molnar 
60486470930SIngo Molnar static const char * const stat_usage[] = {
60560666c63SLiming Wang 	"perf stat [<options>] [<command>]",
60686470930SIngo Molnar 	NULL
60786470930SIngo Molnar };
60886470930SIngo Molnar 
609d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used,
610d7470b6aSStephane Eranian 			     const char *s __used, int unset)
611d7470b6aSStephane Eranian {
612d7470b6aSStephane Eranian 	big_num_opt = unset ? 0 : 1;
613d7470b6aSStephane Eranian 	return 0;
614d7470b6aSStephane Eranian }
615d7470b6aSStephane Eranian 
61686470930SIngo Molnar static const struct option options[] = {
617361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
61886470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
61986470930SIngo Molnar 		     parse_events),
6202e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
6212e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
62286470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
623d6d901c2SZhang, Yanmin 		    "stat events on existing process id"),
624d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
625d6d901c2SZhang, Yanmin 		    "stat events on existing thread id"),
62686470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
62786470930SIngo Molnar 		    "system-wide collection from all CPUs"),
628b26bc5a7SBrice Goglin 	OPT_BOOLEAN('c', "scale", &scale,
62986470930SIngo Molnar 		    "scale/normalize counters"),
630c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
631743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
63242202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
63342202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
6340cfb7a13SIngo Molnar 	OPT_BOOLEAN('n', "null", &null_run,
6350cfb7a13SIngo Molnar 		    "null run - dont start any counters"),
636d7470b6aSStephane Eranian 	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
637d7470b6aSStephane Eranian 			   "print large numbers with thousands\' separators",
638d7470b6aSStephane Eranian 			   stat__set_big_num),
639c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
640c45c6ea2SStephane Eranian 		    "list of cpus to monitor in system-wide"),
641f5b4a9c3SStephane Eranian 	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
642f5b4a9c3SStephane Eranian 		    "disable CPU count aggregation"),
643d7470b6aSStephane Eranian 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
644d7470b6aSStephane Eranian 		   "print counts with custom separator"),
64586470930SIngo Molnar 	OPT_END()
64686470930SIngo Molnar };
64786470930SIngo Molnar 
648f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used)
64986470930SIngo Molnar {
65069aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
65169aad6f1SArnaldo Carvalho de Melo 	int status = -ENOMEM;
65242202dd5SIngo Molnar 
6535af52b51SStephane Eranian 	setlocale(LC_ALL, "");
6545af52b51SStephane Eranian 
6557e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
656361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
657361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
658361c99a6SArnaldo Carvalho de Melo 
659a0541234SAnton Blanchard 	argc = parse_options(argc, argv, options, stat_usage,
660a0541234SAnton Blanchard 		PARSE_OPT_STOP_AT_NON_OPTION);
661d7470b6aSStephane Eranian 
662d7470b6aSStephane Eranian 	if (csv_sep)
663d7470b6aSStephane Eranian 		csv_output = true;
664d7470b6aSStephane Eranian 	else
665d7470b6aSStephane Eranian 		csv_sep = DEFAULT_SEPARATOR;
666d7470b6aSStephane Eranian 
667d7470b6aSStephane Eranian 	/*
668d7470b6aSStephane Eranian 	 * let the spreadsheet do the pretty-printing
669d7470b6aSStephane Eranian 	 */
670d7470b6aSStephane Eranian 	if (csv_output) {
671d7470b6aSStephane Eranian 		/* User explicitely passed -B? */
672d7470b6aSStephane Eranian 		if (big_num_opt == 1) {
673d7470b6aSStephane Eranian 			fprintf(stderr, "-B option not supported with -x\n");
674d7470b6aSStephane Eranian 			usage_with_options(stat_usage, options);
675d7470b6aSStephane Eranian 		} else /* Nope, so disable big number formatting */
676d7470b6aSStephane Eranian 			big_num = false;
677d7470b6aSStephane Eranian 	} else if (big_num_opt == 0) /* User passed --no-big-num */
678d7470b6aSStephane Eranian 		big_num = false;
679d7470b6aSStephane Eranian 
680d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1)
68186470930SIngo Molnar 		usage_with_options(stat_usage, options);
6829e9772c4SPeter Zijlstra 	if (run_count <= 0)
68342202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
68486470930SIngo Molnar 
685f5b4a9c3SStephane Eranian 	/* no_aggr is for system-wide only */
686f5b4a9c3SStephane Eranian 	if (no_aggr && !system_wide)
687f5b4a9c3SStephane Eranian 		usage_with_options(stat_usage, options);
688f5b4a9c3SStephane Eranian 
689c3043569SJaswinder Singh Rajput 	/* Set attrs and nr_counters if no event is selected and !null_run */
690361c99a6SArnaldo Carvalho de Melo 	if (!null_run && !evsel_list->nr_entries) {
69169aad6f1SArnaldo Carvalho de Melo 		size_t c;
69269aad6f1SArnaldo Carvalho de Melo 
69369aad6f1SArnaldo Carvalho de Melo 		for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
694361c99a6SArnaldo Carvalho de Melo 			pos = perf_evsel__new(&default_attrs[c], c);
69569aad6f1SArnaldo Carvalho de Melo 			if (pos == NULL)
69669aad6f1SArnaldo Carvalho de Melo 				goto out;
697361c99a6SArnaldo Carvalho de Melo 			perf_evlist__add(evsel_list, pos);
69869aad6f1SArnaldo Carvalho de Melo 		}
699c3043569SJaswinder Singh Rajput 	}
70086470930SIngo Molnar 
7015c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
7025c98d466SArnaldo Carvalho de Melo 		target_tid = target_pid;
7035c98d466SArnaldo Carvalho de Melo 
7047e2ed097SArnaldo Carvalho de Melo 	evsel_list->threads = thread_map__new(target_pid, target_tid);
7057e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->threads == NULL) {
7065c98d466SArnaldo Carvalho de Melo 		pr_err("Problems finding threads of monitor\n");
7075c98d466SArnaldo Carvalho de Melo 		usage_with_options(stat_usage, options);
7085c98d466SArnaldo Carvalho de Melo 	}
7095c98d466SArnaldo Carvalho de Melo 
710a12b51c4SPaul Mackerras 	if (system_wide)
7117e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__new(cpu_list);
712a12b51c4SPaul Mackerras 	else
7137e2ed097SArnaldo Carvalho de Melo 		evsel_list->cpus = cpu_map__dummy_new();
71486470930SIngo Molnar 
7157e2ed097SArnaldo Carvalho de Melo 	if (evsel_list->cpus == NULL) {
71660d567e2SArnaldo Carvalho de Melo 		perror("failed to parse CPUs map");
717c45c6ea2SStephane Eranian 		usage_with_options(stat_usage, options);
71860d567e2SArnaldo Carvalho de Melo 		return -1;
71960d567e2SArnaldo Carvalho de Melo 	}
720c45c6ea2SStephane Eranian 
721361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
722c52b12edSArnaldo Carvalho de Melo 		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
7237e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
7247e2ed097SArnaldo Carvalho de Melo 		    perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
72569aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
726d6d901c2SZhang, Yanmin 	}
727d6d901c2SZhang, Yanmin 
72886470930SIngo Molnar 	/*
72986470930SIngo Molnar 	 * We dont want to block the signals - that would cause
73086470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
73186470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
73286470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
73386470930SIngo Molnar 	 */
734f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
73586470930SIngo Molnar 	signal(SIGINT,  skip_signal);
73686470930SIngo Molnar 	signal(SIGALRM, skip_signal);
73786470930SIngo Molnar 	signal(SIGABRT, skip_signal);
73886470930SIngo Molnar 
73942202dd5SIngo Molnar 	status = 0;
74042202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
74142202dd5SIngo Molnar 		if (run_count != 1 && verbose)
74242202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
74342202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
74442202dd5SIngo Molnar 	}
74542202dd5SIngo Molnar 
746084ab9f8SArnaldo Carvalho de Melo 	if (status != -1)
74742202dd5SIngo Molnar 		print_stat(argc, argv);
74869aad6f1SArnaldo Carvalho de Melo out_free_fd:
749361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node)
75069aad6f1SArnaldo Carvalho de Melo 		perf_evsel__free_stat_priv(pos);
751361c99a6SArnaldo Carvalho de Melo 	perf_evlist__delete(evsel_list);
75269aad6f1SArnaldo Carvalho de Melo out:
7537e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
75442202dd5SIngo Molnar 	return status;
75586470930SIngo Molnar }
756