xref: /openbmc/linux/tools/perf/builtin-stat.c (revision d9cf837e)
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"
468f28827aSFrederic Weisbecker #include "util/debug.h"
4760666c63SLiming Wang #include "util/header.h"
48a12b51c4SPaul Mackerras #include "util/cpumap.h"
49d6d901c2SZhang, Yanmin #include "util/thread.h"
5086470930SIngo Molnar 
5186470930SIngo Molnar #include <sys/prctl.h>
5242202dd5SIngo Molnar #include <math.h>
535af52b51SStephane Eranian #include <locale.h>
5486470930SIngo Molnar 
55cdd6c482SIngo Molnar static struct perf_event_attr default_attrs[] = {
5686470930SIngo Molnar 
57f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
58f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
59f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
60f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},
6186470930SIngo Molnar 
62f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
63f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
6412133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
6512133affSTim Blechmann   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
66dd86e72aSIngo Molnar   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES	},
67dd86e72aSIngo Molnar   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES		},
68f4dbfa8fSPeter Zijlstra 
6986470930SIngo Molnar };
7086470930SIngo Molnar 
71c0555642SIan Munsie static bool			system_wide			=  false;
72c45c6ea2SStephane Eranian static int			nr_cpus				=  0;
7342202dd5SIngo Molnar static int			run_idx				=  0;
7442202dd5SIngo Molnar 
753d632595SJaswinder Singh Rajput static int			run_count			=  1;
762e6cdf99SStephane Eranian static bool			no_inherit			= false;
77c0555642SIan Munsie static bool			scale				=  true;
78f5b4a9c3SStephane Eranian static bool			no_aggr				= false;
79933da83aSChris Wilson static pid_t			target_pid			= -1;
80d6d901c2SZhang, Yanmin static pid_t			target_tid			= -1;
81d6d901c2SZhang, Yanmin static pid_t			*all_tids			=  NULL;
82d6d901c2SZhang, Yanmin static int			thread_num			=  0;
83933da83aSChris Wilson static pid_t			child_pid			= -1;
84c0555642SIan Munsie static bool			null_run			=  false;
855af52b51SStephane Eranian static bool			big_num				=  false;
86c45c6ea2SStephane Eranian static const char		*cpu_list;
875af52b51SStephane Eranian 
8842202dd5SIngo Molnar 
89d6d901c2SZhang, Yanmin static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
9042202dd5SIngo Molnar 
9163d40debSPeter Zijlstra static int			event_scaled[MAX_COUNTERS];
923d632595SJaswinder Singh Rajput 
93f5b4a9c3SStephane Eranian static struct {
94f5b4a9c3SStephane Eranian 	u64 val;
95f5b4a9c3SStephane Eranian 	u64 ena;
96f5b4a9c3SStephane Eranian 	u64 run;
97f5b4a9c3SStephane Eranian } cpu_counts[MAX_NR_CPUS][MAX_COUNTERS];
98f5b4a9c3SStephane Eranian 
9960666c63SLiming Wang static volatile int done = 0;
10060666c63SLiming Wang 
101506d4bc8SPeter Zijlstra struct stats
102506d4bc8SPeter Zijlstra {
1038a02631aSPeter Zijlstra 	double n, mean, M2;
104506d4bc8SPeter Zijlstra };
10542202dd5SIngo Molnar 
1069e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val)
1079e9772c4SPeter Zijlstra {
1088a02631aSPeter Zijlstra 	double delta;
1099e9772c4SPeter Zijlstra 
1108a02631aSPeter Zijlstra 	stats->n++;
1118a02631aSPeter Zijlstra 	delta = val - stats->mean;
1128a02631aSPeter Zijlstra 	stats->mean += delta / stats->n;
1138a02631aSPeter Zijlstra 	stats->M2 += delta*(val - stats->mean);
1149e9772c4SPeter Zijlstra }
1159e9772c4SPeter Zijlstra 
116506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats)
117506d4bc8SPeter Zijlstra {
1188a02631aSPeter Zijlstra 	return stats->mean;
119506d4bc8SPeter Zijlstra }
12042202dd5SIngo Molnar 
121506d4bc8SPeter Zijlstra /*
12263d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
12363d40debSPeter Zijlstra  *
12463d40debSPeter Zijlstra  *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
1258a02631aSPeter Zijlstra  * s^2 = -------------------------------
12663d40debSPeter Zijlstra  *                  n - 1
12763d40debSPeter Zijlstra  *
12863d40debSPeter Zijlstra  * http://en.wikipedia.org/wiki/Stddev
12963d40debSPeter Zijlstra  *
13063d40debSPeter Zijlstra  * The std dev of the mean is related to the std dev by:
13163d40debSPeter Zijlstra  *
13263d40debSPeter Zijlstra  *             s
13363d40debSPeter Zijlstra  * s_mean = -------
13463d40debSPeter Zijlstra  *          sqrt(n)
13563d40debSPeter Zijlstra  *
136506d4bc8SPeter Zijlstra  */
137506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats)
138506d4bc8SPeter Zijlstra {
1398a02631aSPeter Zijlstra 	double variance = stats->M2 / (stats->n - 1);
1408a02631aSPeter Zijlstra 	double variance_mean = variance / stats->n;
14142202dd5SIngo Molnar 
14263d40debSPeter Zijlstra 	return sqrt(variance_mean);
143506d4bc8SPeter Zijlstra }
14442202dd5SIngo Molnar 
145506d4bc8SPeter Zijlstra struct stats			event_res_stats[MAX_COUNTERS][3];
146f5b4a9c3SStephane Eranian struct stats			runtime_nsecs_stats[MAX_NR_CPUS];
147f5b4a9c3SStephane Eranian struct stats			runtime_cycles_stats[MAX_NR_CPUS];
148f5b4a9c3SStephane Eranian struct stats			runtime_branches_stats[MAX_NR_CPUS];
149506d4bc8SPeter Zijlstra struct stats			walltime_nsecs_stats;
15086470930SIngo Molnar 
151b9ebdcc0SJaswinder Singh Rajput #define MATCH_EVENT(t, c, counter)			\
152b9ebdcc0SJaswinder Singh Rajput 	(attrs[counter].type == PERF_TYPE_##t &&	\
153b9ebdcc0SJaswinder Singh Rajput 	 attrs[counter].config == PERF_COUNT_##c)
154b9ebdcc0SJaswinder Singh Rajput 
155cca03c0aSJaswinder Singh Rajput #define ERR_PERF_OPEN \
156d9cf837eSCorey Ashford "counter %d, sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information."
157cca03c0aSJaswinder Singh Rajput 
158d9cf837eSCorey Ashford static int create_perf_stat_counter(int counter, bool *perm_err)
15986470930SIngo Molnar {
160cdd6c482SIngo Molnar 	struct perf_event_attr *attr = attrs + counter;
161d6d901c2SZhang, Yanmin 	int thread;
162084ab9f8SArnaldo Carvalho de Melo 	int ncreated = 0;
16386470930SIngo Molnar 
16486470930SIngo Molnar 	if (scale)
16586470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
16686470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
16786470930SIngo Molnar 
16886470930SIngo Molnar 	if (system_wide) {
169c45c6ea2SStephane Eranian 		int cpu;
170f37a291cSIngo Molnar 
17186470930SIngo Molnar 		for (cpu = 0; cpu < nr_cpus; cpu++) {
172d6d901c2SZhang, Yanmin 			fd[cpu][counter][0] = sys_perf_event_open(attr,
173d6d901c2SZhang, Yanmin 					-1, cpumap[cpu], -1, 0);
174d9cf837eSCorey Ashford 			if (fd[cpu][counter][0] < 0) {
175d9cf837eSCorey Ashford 				if (errno == EPERM || errno == EACCES)
176d9cf837eSCorey Ashford 					*perm_err = true;
177d9cf837eSCorey Ashford 				error(ERR_PERF_OPEN, counter,
178d6d901c2SZhang, Yanmin 					 fd[cpu][counter][0], strerror(errno));
179d9cf837eSCorey Ashford 			} else {
180084ab9f8SArnaldo Carvalho de Melo 				++ncreated;
18186470930SIngo Molnar 			}
182d9cf837eSCorey Ashford 		}
18386470930SIngo Molnar 	} else {
1842e6cdf99SStephane Eranian 		attr->inherit = !no_inherit;
1852e6cdf99SStephane Eranian 		if (target_pid == -1 && target_tid == -1) {
18686470930SIngo Molnar 			attr->disabled = 1;
18757e7986eSPaul Mackerras 			attr->enable_on_exec = 1;
1886be2850eSZhang, Yanmin 		}
189d6d901c2SZhang, Yanmin 		for (thread = 0; thread < thread_num; thread++) {
190d6d901c2SZhang, Yanmin 			fd[0][counter][thread] = sys_perf_event_open(attr,
191d6d901c2SZhang, Yanmin 				all_tids[thread], -1, -1, 0);
192d9cf837eSCorey Ashford 			if (fd[0][counter][thread] < 0) {
193d9cf837eSCorey Ashford 				if (errno == EPERM || errno == EACCES)
194d9cf837eSCorey Ashford 					*perm_err = true;
195d9cf837eSCorey Ashford 				error(ERR_PERF_OPEN, counter,
196d6d901c2SZhang, Yanmin 					 fd[0][counter][thread],
197d6d901c2SZhang, Yanmin 					 strerror(errno));
198d9cf837eSCorey Ashford 			} else {
199084ab9f8SArnaldo Carvalho de Melo 				++ncreated;
200d6d901c2SZhang, Yanmin 			}
20186470930SIngo Molnar 		}
202d9cf837eSCorey Ashford 	}
203084ab9f8SArnaldo Carvalho de Melo 
204084ab9f8SArnaldo Carvalho de Melo 	return ncreated;
20586470930SIngo Molnar }
20686470930SIngo Molnar 
20786470930SIngo Molnar /*
20886470930SIngo Molnar  * Does the counter have nsecs as a unit?
20986470930SIngo Molnar  */
21086470930SIngo Molnar static inline int nsec_counter(int counter)
21186470930SIngo Molnar {
212b9ebdcc0SJaswinder Singh Rajput 	if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
213b9ebdcc0SJaswinder Singh Rajput 	    MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
21486470930SIngo Molnar 		return 1;
21586470930SIngo Molnar 
21686470930SIngo Molnar 	return 0;
21786470930SIngo Molnar }
21886470930SIngo Molnar 
21986470930SIngo Molnar /*
22086470930SIngo Molnar  * Read out the results of a single counter:
221f5b4a9c3SStephane Eranian  * aggregate counts across CPUs in system-wide mode
22286470930SIngo Molnar  */
223f5b4a9c3SStephane Eranian static void read_counter_aggr(int counter)
22486470930SIngo Molnar {
225849abde9SPeter Zijlstra 	u64 count[3], single_count[3];
226c45c6ea2SStephane Eranian 	int cpu;
227f37a291cSIngo Molnar 	size_t res, nv;
22886470930SIngo Molnar 	int scaled;
229d6d901c2SZhang, Yanmin 	int i, thread;
23086470930SIngo Molnar 
23186470930SIngo Molnar 	count[0] = count[1] = count[2] = 0;
23286470930SIngo Molnar 
23386470930SIngo Molnar 	nv = scale ? 3 : 1;
23486470930SIngo Molnar 	for (cpu = 0; cpu < nr_cpus; cpu++) {
235d6d901c2SZhang, Yanmin 		for (thread = 0; thread < thread_num; thread++) {
236d6d901c2SZhang, Yanmin 			if (fd[cpu][counter][thread] < 0)
237743ee1f8SIngo Molnar 				continue;
238743ee1f8SIngo Molnar 
239d6d901c2SZhang, Yanmin 			res = read(fd[cpu][counter][thread],
240d6d901c2SZhang, Yanmin 					single_count, nv * sizeof(u64));
2419cffa8d5SPaul Mackerras 			assert(res == nv * sizeof(u64));
242f37a291cSIngo Molnar 
243d6d901c2SZhang, Yanmin 			close(fd[cpu][counter][thread]);
244d6d901c2SZhang, Yanmin 			fd[cpu][counter][thread] = -1;
24586470930SIngo Molnar 
24686470930SIngo Molnar 			count[0] += single_count[0];
24786470930SIngo Molnar 			if (scale) {
24886470930SIngo Molnar 				count[1] += single_count[1];
24986470930SIngo Molnar 				count[2] += single_count[2];
25086470930SIngo Molnar 			}
25186470930SIngo Molnar 		}
252d6d901c2SZhang, Yanmin 	}
25386470930SIngo Molnar 
25486470930SIngo Molnar 	scaled = 0;
25586470930SIngo Molnar 	if (scale) {
25686470930SIngo Molnar 		if (count[2] == 0) {
2579e9772c4SPeter Zijlstra 			event_scaled[counter] = -1;
25886470930SIngo Molnar 			count[0] = 0;
25986470930SIngo Molnar 			return;
26086470930SIngo Molnar 		}
26186470930SIngo Molnar 
26286470930SIngo Molnar 		if (count[2] < count[1]) {
2639e9772c4SPeter Zijlstra 			event_scaled[counter] = 1;
26486470930SIngo Molnar 			count[0] = (unsigned long long)
26586470930SIngo Molnar 				((double)count[0] * count[1] / count[2] + 0.5);
26686470930SIngo Molnar 		}
26786470930SIngo Molnar 	}
2689e9772c4SPeter Zijlstra 
2699e9772c4SPeter Zijlstra 	for (i = 0; i < 3; i++)
2709e9772c4SPeter Zijlstra 		update_stats(&event_res_stats[counter][i], count[i]);
2719e9772c4SPeter Zijlstra 
2729e9772c4SPeter Zijlstra 	if (verbose) {
2739e9772c4SPeter Zijlstra 		fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter),
2749e9772c4SPeter Zijlstra 				count[0], count[1], count[2]);
2759e9772c4SPeter Zijlstra 	}
2769e9772c4SPeter Zijlstra 
27786470930SIngo Molnar 	/*
27886470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
27986470930SIngo Molnar 	 */
280b9ebdcc0SJaswinder Singh Rajput 	if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
281f5b4a9c3SStephane Eranian 		update_stats(&runtime_nsecs_stats[0], count[0]);
282b9ebdcc0SJaswinder Singh Rajput 	if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
283f5b4a9c3SStephane Eranian 		update_stats(&runtime_cycles_stats[0], count[0]);
28411018201SAnton Blanchard 	if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
285f5b4a9c3SStephane Eranian 		update_stats(&runtime_branches_stats[0], count[0]);
286f5b4a9c3SStephane Eranian }
287f5b4a9c3SStephane Eranian 
288f5b4a9c3SStephane Eranian /*
289f5b4a9c3SStephane Eranian  * Read out the results of a single counter:
290f5b4a9c3SStephane Eranian  * do not aggregate counts across CPUs in system-wide mode
291f5b4a9c3SStephane Eranian  */
292f5b4a9c3SStephane Eranian static void read_counter(int counter)
293f5b4a9c3SStephane Eranian {
294f5b4a9c3SStephane Eranian 	u64 count[3];
295f5b4a9c3SStephane Eranian 	int cpu;
296f5b4a9c3SStephane Eranian 	size_t res, nv;
297f5b4a9c3SStephane Eranian 
298f5b4a9c3SStephane Eranian 	count[0] = count[1] = count[2] = 0;
299f5b4a9c3SStephane Eranian 
300f5b4a9c3SStephane Eranian 	nv = scale ? 3 : 1;
301f5b4a9c3SStephane Eranian 
302f5b4a9c3SStephane Eranian 	for (cpu = 0; cpu < nr_cpus; cpu++) {
303f5b4a9c3SStephane Eranian 
304f5b4a9c3SStephane Eranian 		if (fd[cpu][counter][0] < 0)
305f5b4a9c3SStephane Eranian 			continue;
306f5b4a9c3SStephane Eranian 
307f5b4a9c3SStephane Eranian 		res = read(fd[cpu][counter][0], count, nv * sizeof(u64));
308f5b4a9c3SStephane Eranian 
309f5b4a9c3SStephane Eranian 		assert(res == nv * sizeof(u64));
310f5b4a9c3SStephane Eranian 
311f5b4a9c3SStephane Eranian 		close(fd[cpu][counter][0]);
312f5b4a9c3SStephane Eranian 		fd[cpu][counter][0] = -1;
313f5b4a9c3SStephane Eranian 
314f5b4a9c3SStephane Eranian 		if (scale) {
315f5b4a9c3SStephane Eranian 			if (count[2] == 0) {
316f5b4a9c3SStephane Eranian 				count[0] = 0;
317f5b4a9c3SStephane Eranian 			} else if (count[2] < count[1]) {
318f5b4a9c3SStephane Eranian 				count[0] = (unsigned long long)
319f5b4a9c3SStephane Eranian 				((double)count[0] * count[1] / count[2] + 0.5);
320f5b4a9c3SStephane Eranian 			}
321f5b4a9c3SStephane Eranian 		}
322f5b4a9c3SStephane Eranian 		cpu_counts[cpu][counter].val = count[0]; /* scaled count */
323f5b4a9c3SStephane Eranian 		cpu_counts[cpu][counter].ena = count[1];
324f5b4a9c3SStephane Eranian 		cpu_counts[cpu][counter].run = count[2];
325f5b4a9c3SStephane Eranian 
326f5b4a9c3SStephane Eranian 		if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
327f5b4a9c3SStephane Eranian 			update_stats(&runtime_nsecs_stats[cpu], count[0]);
328f5b4a9c3SStephane Eranian 		if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
329f5b4a9c3SStephane Eranian 			update_stats(&runtime_cycles_stats[cpu], count[0]);
330f5b4a9c3SStephane Eranian 		if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
331f5b4a9c3SStephane Eranian 			update_stats(&runtime_branches_stats[cpu], count[0]);
332f5b4a9c3SStephane Eranian 	}
33386470930SIngo Molnar }
33486470930SIngo Molnar 
335f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv)
33686470930SIngo Molnar {
33786470930SIngo Molnar 	unsigned long long t0, t1;
33842202dd5SIngo Molnar 	int status = 0;
339084ab9f8SArnaldo Carvalho de Melo 	int counter, ncreated = 0;
340051ae7f7SPaul Mackerras 	int child_ready_pipe[2], go_pipe[2];
341d9cf837eSCorey Ashford 	bool perm_err = false;
3426be2850eSZhang, Yanmin 	const bool forks = (argc > 0);
343051ae7f7SPaul Mackerras 	char buf;
34486470930SIngo Molnar 
34586470930SIngo Molnar 	if (!system_wide)
34686470930SIngo Molnar 		nr_cpus = 1;
34786470930SIngo Molnar 
34860666c63SLiming Wang 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
349051ae7f7SPaul Mackerras 		perror("failed to create pipes");
350051ae7f7SPaul Mackerras 		exit(1);
351051ae7f7SPaul Mackerras 	}
352051ae7f7SPaul Mackerras 
35360666c63SLiming Wang 	if (forks) {
3546be2850eSZhang, Yanmin 		if ((child_pid = fork()) < 0)
355051ae7f7SPaul Mackerras 			perror("failed to fork");
356051ae7f7SPaul Mackerras 
3576be2850eSZhang, Yanmin 		if (!child_pid) {
358051ae7f7SPaul Mackerras 			close(child_ready_pipe[0]);
359051ae7f7SPaul Mackerras 			close(go_pipe[1]);
360051ae7f7SPaul Mackerras 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
361051ae7f7SPaul Mackerras 
362051ae7f7SPaul Mackerras 			/*
363051ae7f7SPaul Mackerras 			 * Do a dummy execvp to get the PLT entry resolved,
364051ae7f7SPaul Mackerras 			 * so we avoid the resolver overhead on the real
365051ae7f7SPaul Mackerras 			 * execvp call.
366051ae7f7SPaul Mackerras 			 */
367051ae7f7SPaul Mackerras 			execvp("", (char **)argv);
368051ae7f7SPaul Mackerras 
369051ae7f7SPaul Mackerras 			/*
370051ae7f7SPaul Mackerras 			 * Tell the parent we're ready to go
371051ae7f7SPaul Mackerras 			 */
372051ae7f7SPaul Mackerras 			close(child_ready_pipe[1]);
373051ae7f7SPaul Mackerras 
374051ae7f7SPaul Mackerras 			/*
375051ae7f7SPaul Mackerras 			 * Wait until the parent tells us to go.
376051ae7f7SPaul Mackerras 			 */
377a92bef0fSFrederic Weisbecker 			if (read(go_pipe[0], &buf, 1) == -1)
378a92bef0fSFrederic Weisbecker 				perror("unable to read pipe");
379051ae7f7SPaul Mackerras 
380051ae7f7SPaul Mackerras 			execvp(argv[0], (char **)argv);
381051ae7f7SPaul Mackerras 
382051ae7f7SPaul Mackerras 			perror(argv[0]);
383051ae7f7SPaul Mackerras 			exit(-1);
384051ae7f7SPaul Mackerras 		}
385051ae7f7SPaul Mackerras 
386d6d901c2SZhang, Yanmin 		if (target_tid == -1 && target_pid == -1 && !system_wide)
387d6d901c2SZhang, Yanmin 			all_tids[0] = child_pid;
388d6d901c2SZhang, Yanmin 
389051ae7f7SPaul Mackerras 		/*
390051ae7f7SPaul Mackerras 		 * Wait for the child to be ready to exec.
391051ae7f7SPaul Mackerras 		 */
392051ae7f7SPaul Mackerras 		close(child_ready_pipe[1]);
393051ae7f7SPaul Mackerras 		close(go_pipe[0]);
394a92bef0fSFrederic Weisbecker 		if (read(child_ready_pipe[0], &buf, 1) == -1)
395a92bef0fSFrederic Weisbecker 			perror("unable to read pipe");
396051ae7f7SPaul Mackerras 		close(child_ready_pipe[0]);
39760666c63SLiming Wang 	}
398051ae7f7SPaul Mackerras 
39986470930SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
400d9cf837eSCorey Ashford 		ncreated += create_perf_stat_counter(counter, &perm_err);
401084ab9f8SArnaldo Carvalho de Melo 
402d9cf837eSCorey Ashford 	if (ncreated < nr_counters) {
403d9cf837eSCorey Ashford 		if (perm_err)
404d9cf837eSCorey Ashford 			error("You may not have permission to collect %sstats.\n"
405d9cf837eSCorey Ashford 			      "\t Consider tweaking"
406d9cf837eSCorey Ashford 			      " /proc/sys/kernel/perf_event_paranoid or running as root.",
407084ab9f8SArnaldo Carvalho de Melo 			      system_wide ? "system-wide " : "");
408d9cf837eSCorey Ashford 		die("Not all events could be opened.\n");
409084ab9f8SArnaldo Carvalho de Melo 		if (child_pid != -1)
410084ab9f8SArnaldo Carvalho de Melo 			kill(child_pid, SIGTERM);
411084ab9f8SArnaldo Carvalho de Melo 		return -1;
412084ab9f8SArnaldo Carvalho de Melo 	}
41386470930SIngo Molnar 
41486470930SIngo Molnar 	/*
41586470930SIngo Molnar 	 * Enable counters and exec the command:
41686470930SIngo Molnar 	 */
41786470930SIngo Molnar 	t0 = rdclock();
41886470930SIngo Molnar 
41960666c63SLiming Wang 	if (forks) {
420051ae7f7SPaul Mackerras 		close(go_pipe[1]);
42142202dd5SIngo Molnar 		wait(&status);
42260666c63SLiming Wang 	} else {
4236be2850eSZhang, Yanmin 		while(!done) sleep(1);
42460666c63SLiming Wang 	}
42586470930SIngo Molnar 
42686470930SIngo Molnar 	t1 = rdclock();
42786470930SIngo Molnar 
4289e9772c4SPeter Zijlstra 	update_stats(&walltime_nsecs_stats, t1 - t0);
42942202dd5SIngo Molnar 
430f5b4a9c3SStephane Eranian 	if (no_aggr) {
43142202dd5SIngo Molnar 		for (counter = 0; counter < nr_counters; counter++)
43242202dd5SIngo Molnar 			read_counter(counter);
433f5b4a9c3SStephane Eranian 	} else {
434f5b4a9c3SStephane Eranian 		for (counter = 0; counter < nr_counters; counter++)
435f5b4a9c3SStephane Eranian 			read_counter_aggr(counter);
436f5b4a9c3SStephane Eranian 	}
43742202dd5SIngo Molnar 	return WEXITSTATUS(status);
43842202dd5SIngo Molnar }
43942202dd5SIngo Molnar 
440849abde9SPeter Zijlstra static void print_noise(int counter, double avg)
44142202dd5SIngo Molnar {
442849abde9SPeter Zijlstra 	if (run_count == 1)
443849abde9SPeter Zijlstra 		return;
444849abde9SPeter Zijlstra 
445849abde9SPeter Zijlstra 	fprintf(stderr, "   ( +- %7.3f%% )",
446849abde9SPeter Zijlstra 			100 * stddev_stats(&event_res_stats[counter][0]) / avg);
44742202dd5SIngo Molnar }
44842202dd5SIngo Molnar 
449f5b4a9c3SStephane Eranian static void nsec_printout(int cpu, int counter, double avg)
45042202dd5SIngo Molnar {
451506d4bc8SPeter Zijlstra 	double msecs = avg / 1e6;
45242202dd5SIngo Molnar 
453f5b4a9c3SStephane Eranian 	if (no_aggr)
454f5b4a9c3SStephane Eranian 		fprintf(stderr, "CPU%-4d %18.6f  %-24s",
455f5b4a9c3SStephane Eranian 			cpumap[cpu], msecs, event_name(counter));
456f5b4a9c3SStephane Eranian 	else
4575af52b51SStephane Eranian 		fprintf(stderr, " %18.6f  %-24s", msecs, event_name(counter));
45842202dd5SIngo Molnar 
459b9ebdcc0SJaswinder Singh Rajput 	if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
46042202dd5SIngo Molnar 		fprintf(stderr, " # %10.3f CPUs ",
461506d4bc8SPeter Zijlstra 				avg / avg_stats(&walltime_nsecs_stats));
46242202dd5SIngo Molnar 	}
46342202dd5SIngo Molnar }
46442202dd5SIngo Molnar 
465f5b4a9c3SStephane Eranian static void abs_printout(int cpu, int counter, double avg)
46642202dd5SIngo Molnar {
467c7f7fea3SIngo Molnar 	double total, ratio = 0.0;
468f5b4a9c3SStephane Eranian 	char cpustr[16] = { '\0', };
469f5b4a9c3SStephane Eranian 
470f5b4a9c3SStephane Eranian 	if (no_aggr)
471f5b4a9c3SStephane Eranian 		sprintf(cpustr, "CPU%-4d", cpumap[cpu]);
472f5b4a9c3SStephane Eranian 	else
473f5b4a9c3SStephane Eranian 		cpu = 0;
474c7f7fea3SIngo Molnar 
4755af52b51SStephane Eranian 	if (big_num)
476f5b4a9c3SStephane Eranian 		fprintf(stderr, "%s %'18.0f  %-24s",
477f5b4a9c3SStephane Eranian 			cpustr, avg, event_name(counter));
4785af52b51SStephane Eranian 	else
479f5b4a9c3SStephane Eranian 		fprintf(stderr, "%s %18.0f  %-24s",
480f5b4a9c3SStephane Eranian 			cpustr, avg, event_name(counter));
48142202dd5SIngo Molnar 
482506d4bc8SPeter Zijlstra 	if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
483f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_cycles_stats[cpu]);
484c7f7fea3SIngo Molnar 
485c7f7fea3SIngo Molnar 		if (total)
486c7f7fea3SIngo Molnar 			ratio = avg / total;
487c7f7fea3SIngo Molnar 
488c7f7fea3SIngo Molnar 		fprintf(stderr, " # %10.3f IPC  ", ratio);
4897255fe2aSLucas De Marchi 	} else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter) &&
490f5b4a9c3SStephane Eranian 			runtime_branches_stats[cpu].n != 0) {
491f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_branches_stats[cpu]);
49211018201SAnton Blanchard 
49311018201SAnton Blanchard 		if (total)
49411018201SAnton Blanchard 			ratio = avg * 100 / total;
49511018201SAnton Blanchard 
49611018201SAnton Blanchard 		fprintf(stderr, " # %10.3f %%    ", ratio);
49711018201SAnton Blanchard 
498f5b4a9c3SStephane Eranian 	} else if (runtime_nsecs_stats[cpu].n != 0) {
499f5b4a9c3SStephane Eranian 		total = avg_stats(&runtime_nsecs_stats[cpu]);
500c7f7fea3SIngo Molnar 
501c7f7fea3SIngo Molnar 		if (total)
502c7f7fea3SIngo Molnar 			ratio = 1000.0 * avg / total;
503c7f7fea3SIngo Molnar 
504c7f7fea3SIngo Molnar 		fprintf(stderr, " # %10.3f M/sec", ratio);
50542202dd5SIngo Molnar 	}
50642202dd5SIngo Molnar }
50742202dd5SIngo Molnar 
50842202dd5SIngo Molnar /*
50942202dd5SIngo Molnar  * Print out the results of a single counter:
510f5b4a9c3SStephane Eranian  * aggregated counts in system-wide mode
51142202dd5SIngo Molnar  */
512f5b4a9c3SStephane Eranian static void print_counter_aggr(int counter)
51342202dd5SIngo Molnar {
514849abde9SPeter Zijlstra 	double avg = avg_stats(&event_res_stats[counter][0]);
51563d40debSPeter Zijlstra 	int scaled = event_scaled[counter];
51642202dd5SIngo Molnar 
51742202dd5SIngo Molnar 	if (scaled == -1) {
5185af52b51SStephane Eranian 		fprintf(stderr, " %18s  %-24s\n",
51942202dd5SIngo Molnar 			"<not counted>", event_name(counter));
52042202dd5SIngo Molnar 		return;
52142202dd5SIngo Molnar 	}
52242202dd5SIngo Molnar 
52342202dd5SIngo Molnar 	if (nsec_counter(counter))
524f5b4a9c3SStephane Eranian 		nsec_printout(-1, counter, avg);
52542202dd5SIngo Molnar 	else
526f5b4a9c3SStephane Eranian 		abs_printout(-1, counter, avg);
527849abde9SPeter Zijlstra 
528849abde9SPeter Zijlstra 	print_noise(counter, avg);
52942202dd5SIngo Molnar 
530506d4bc8SPeter Zijlstra 	if (scaled) {
531506d4bc8SPeter Zijlstra 		double avg_enabled, avg_running;
532506d4bc8SPeter Zijlstra 
533506d4bc8SPeter Zijlstra 		avg_enabled = avg_stats(&event_res_stats[counter][1]);
534506d4bc8SPeter Zijlstra 		avg_running = avg_stats(&event_res_stats[counter][2]);
535506d4bc8SPeter Zijlstra 
536210ad39fSIngo Molnar 		fprintf(stderr, "  (scaled from %.2f%%)",
537506d4bc8SPeter Zijlstra 				100 * avg_running / avg_enabled);
538506d4bc8SPeter Zijlstra 	}
53942202dd5SIngo Molnar 
54042202dd5SIngo Molnar 	fprintf(stderr, "\n");
54142202dd5SIngo Molnar }
54242202dd5SIngo Molnar 
543f5b4a9c3SStephane Eranian /*
544f5b4a9c3SStephane Eranian  * Print out the results of a single counter:
545f5b4a9c3SStephane Eranian  * does not use aggregated count in system-wide
546f5b4a9c3SStephane Eranian  */
547f5b4a9c3SStephane Eranian static void print_counter(int counter)
548f5b4a9c3SStephane Eranian {
549f5b4a9c3SStephane Eranian 	u64 ena, run, val;
550f5b4a9c3SStephane Eranian 	int cpu;
551f5b4a9c3SStephane Eranian 
552f5b4a9c3SStephane Eranian 	for (cpu = 0; cpu < nr_cpus; cpu++) {
553f5b4a9c3SStephane Eranian 		val = cpu_counts[cpu][counter].val;
554f5b4a9c3SStephane Eranian 		ena = cpu_counts[cpu][counter].ena;
555f5b4a9c3SStephane Eranian 		run = cpu_counts[cpu][counter].run;
556f5b4a9c3SStephane Eranian 		if (run == 0 || ena == 0) {
557f5b4a9c3SStephane Eranian 			fprintf(stderr, "CPU%-4d %18s  %-24s", cpumap[cpu],
558f5b4a9c3SStephane Eranian 					"<not counted>", event_name(counter));
559f5b4a9c3SStephane Eranian 
560f5b4a9c3SStephane Eranian 			fprintf(stderr, "\n");
561f5b4a9c3SStephane Eranian 			continue;
562f5b4a9c3SStephane Eranian 		}
563f5b4a9c3SStephane Eranian 
564f5b4a9c3SStephane Eranian 		if (nsec_counter(counter))
565f5b4a9c3SStephane Eranian 			nsec_printout(cpu, counter, val);
566f5b4a9c3SStephane Eranian 		else
567f5b4a9c3SStephane Eranian 			abs_printout(cpu, counter, val);
568f5b4a9c3SStephane Eranian 
569f5b4a9c3SStephane Eranian 		print_noise(counter, 1.0);
570f5b4a9c3SStephane Eranian 
571f5b4a9c3SStephane Eranian 		if (run != ena) {
572f5b4a9c3SStephane Eranian 			fprintf(stderr, "  (scaled from %.2f%%)",
573f5b4a9c3SStephane Eranian 					100.0 * run / ena);
574f5b4a9c3SStephane Eranian 		}
575f5b4a9c3SStephane Eranian 		fprintf(stderr, "\n");
576f5b4a9c3SStephane Eranian 	}
577f5b4a9c3SStephane Eranian }
578f5b4a9c3SStephane Eranian 
57942202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
58042202dd5SIngo Molnar {
58142202dd5SIngo Molnar 	int i, counter;
58242202dd5SIngo Molnar 
58386470930SIngo Molnar 	fflush(stdout);
58486470930SIngo Molnar 
58586470930SIngo Molnar 	fprintf(stderr, "\n");
58660666c63SLiming Wang 	fprintf(stderr, " Performance counter stats for ");
587d6d901c2SZhang, Yanmin 	if(target_pid == -1 && target_tid == -1) {
58860666c63SLiming Wang 		fprintf(stderr, "\'%s", argv[0]);
58986470930SIngo Molnar 		for (i = 1; i < argc; i++)
59086470930SIngo Molnar 			fprintf(stderr, " %s", argv[i]);
591d6d901c2SZhang, Yanmin 	} else if (target_pid != -1)
592d6d901c2SZhang, Yanmin 		fprintf(stderr, "process id \'%d", target_pid);
593d6d901c2SZhang, Yanmin 	else
594d6d901c2SZhang, Yanmin 		fprintf(stderr, "thread id \'%d", target_tid);
59586470930SIngo Molnar 
59642202dd5SIngo Molnar 	fprintf(stderr, "\'");
59742202dd5SIngo Molnar 	if (run_count > 1)
59842202dd5SIngo Molnar 		fprintf(stderr, " (%d runs)", run_count);
59942202dd5SIngo Molnar 	fprintf(stderr, ":\n\n");
60086470930SIngo Molnar 
601f5b4a9c3SStephane Eranian 	if (no_aggr) {
60286470930SIngo Molnar 		for (counter = 0; counter < nr_counters; counter++)
60386470930SIngo Molnar 			print_counter(counter);
604f5b4a9c3SStephane Eranian 	} else {
605f5b4a9c3SStephane Eranian 		for (counter = 0; counter < nr_counters; counter++)
606f5b4a9c3SStephane Eranian 			print_counter_aggr(counter);
607f5b4a9c3SStephane Eranian 	}
60886470930SIngo Molnar 
60986470930SIngo Molnar 	fprintf(stderr, "\n");
6105af52b51SStephane Eranian 	fprintf(stderr, " %18.9f  seconds time elapsed",
611506d4bc8SPeter Zijlstra 			avg_stats(&walltime_nsecs_stats)/1e9);
612566747e6SIngo Molnar 	if (run_count > 1) {
613566747e6SIngo Molnar 		fprintf(stderr, "   ( +- %7.3f%% )",
614506d4bc8SPeter Zijlstra 				100*stddev_stats(&walltime_nsecs_stats) /
615506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats));
616566747e6SIngo Molnar 	}
617566747e6SIngo Molnar 	fprintf(stderr, "\n\n");
61886470930SIngo Molnar }
61986470930SIngo Molnar 
620f7b7c26eSPeter Zijlstra static volatile int signr = -1;
621f7b7c26eSPeter Zijlstra 
62286470930SIngo Molnar static void skip_signal(int signo)
62386470930SIngo Molnar {
6246be2850eSZhang, Yanmin 	if(child_pid == -1)
62560666c63SLiming Wang 		done = 1;
62660666c63SLiming Wang 
627f7b7c26eSPeter Zijlstra 	signr = signo;
628f7b7c26eSPeter Zijlstra }
629f7b7c26eSPeter Zijlstra 
630f7b7c26eSPeter Zijlstra static void sig_atexit(void)
631f7b7c26eSPeter Zijlstra {
632933da83aSChris Wilson 	if (child_pid != -1)
633933da83aSChris Wilson 		kill(child_pid, SIGTERM);
634933da83aSChris Wilson 
635f7b7c26eSPeter Zijlstra 	if (signr == -1)
636f7b7c26eSPeter Zijlstra 		return;
637f7b7c26eSPeter Zijlstra 
638f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
639f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
64086470930SIngo Molnar }
64186470930SIngo Molnar 
64286470930SIngo Molnar static const char * const stat_usage[] = {
64360666c63SLiming Wang 	"perf stat [<options>] [<command>]",
64486470930SIngo Molnar 	NULL
64586470930SIngo Molnar };
64686470930SIngo Molnar 
64786470930SIngo Molnar static const struct option options[] = {
64886470930SIngo Molnar 	OPT_CALLBACK('e', "event", NULL, "event",
64986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
65086470930SIngo Molnar 		     parse_events),
6512e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
6522e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
65386470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
654d6d901c2SZhang, Yanmin 		    "stat events on existing process id"),
655d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
656d6d901c2SZhang, Yanmin 		    "stat events on existing thread id"),
65786470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
65886470930SIngo Molnar 		    "system-wide collection from all CPUs"),
659b26bc5a7SBrice Goglin 	OPT_BOOLEAN('c', "scale", &scale,
66086470930SIngo Molnar 		    "scale/normalize counters"),
661c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
662743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
66342202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
66442202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
6650cfb7a13SIngo Molnar 	OPT_BOOLEAN('n', "null", &null_run,
6660cfb7a13SIngo Molnar 		    "null run - dont start any counters"),
6675af52b51SStephane Eranian 	OPT_BOOLEAN('B', "big-num", &big_num,
6685af52b51SStephane Eranian 		    "print large numbers with thousands\' separators"),
669c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
670c45c6ea2SStephane Eranian 		    "list of cpus to monitor in system-wide"),
671f5b4a9c3SStephane Eranian 	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
672f5b4a9c3SStephane Eranian 		    "disable CPU count aggregation"),
67386470930SIngo Molnar 	OPT_END()
67486470930SIngo Molnar };
67586470930SIngo Molnar 
676f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used)
67786470930SIngo Molnar {
67842202dd5SIngo Molnar 	int status;
679d6d901c2SZhang, Yanmin 	int i,j;
68042202dd5SIngo Molnar 
6815af52b51SStephane Eranian 	setlocale(LC_ALL, "");
6825af52b51SStephane Eranian 
683a0541234SAnton Blanchard 	argc = parse_options(argc, argv, options, stat_usage,
684a0541234SAnton Blanchard 		PARSE_OPT_STOP_AT_NON_OPTION);
685d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1)
68686470930SIngo Molnar 		usage_with_options(stat_usage, options);
6879e9772c4SPeter Zijlstra 	if (run_count <= 0)
68842202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
68986470930SIngo Molnar 
690f5b4a9c3SStephane Eranian 	/* no_aggr is for system-wide only */
691f5b4a9c3SStephane Eranian 	if (no_aggr && !system_wide)
692f5b4a9c3SStephane Eranian 		usage_with_options(stat_usage, options);
693f5b4a9c3SStephane Eranian 
694c3043569SJaswinder Singh Rajput 	/* Set attrs and nr_counters if no event is selected and !null_run */
695c3043569SJaswinder Singh Rajput 	if (!null_run && !nr_counters) {
696c3043569SJaswinder Singh Rajput 		memcpy(attrs, default_attrs, sizeof(default_attrs));
697c3043569SJaswinder Singh Rajput 		nr_counters = ARRAY_SIZE(default_attrs);
698c3043569SJaswinder Singh Rajput 	}
69986470930SIngo Molnar 
700a12b51c4SPaul Mackerras 	if (system_wide)
701c45c6ea2SStephane Eranian 		nr_cpus = read_cpu_map(cpu_list);
702a12b51c4SPaul Mackerras 	else
703a12b51c4SPaul Mackerras 		nr_cpus = 1;
70486470930SIngo Molnar 
705c45c6ea2SStephane Eranian 	if (nr_cpus < 1)
706c45c6ea2SStephane Eranian 		usage_with_options(stat_usage, options);
707c45c6ea2SStephane Eranian 
708d6d901c2SZhang, Yanmin 	if (target_pid != -1) {
709d6d901c2SZhang, Yanmin 		target_tid = target_pid;
710d6d901c2SZhang, Yanmin 		thread_num = find_all_tid(target_pid, &all_tids);
711d6d901c2SZhang, Yanmin 		if (thread_num <= 0) {
712d6d901c2SZhang, Yanmin 			fprintf(stderr, "Can't find all threads of pid %d\n",
713d6d901c2SZhang, Yanmin 					target_pid);
714d6d901c2SZhang, Yanmin 			usage_with_options(stat_usage, options);
715d6d901c2SZhang, Yanmin 		}
716d6d901c2SZhang, Yanmin 	} else {
717d6d901c2SZhang, Yanmin 		all_tids=malloc(sizeof(pid_t));
718d6d901c2SZhang, Yanmin 		if (!all_tids)
719d6d901c2SZhang, Yanmin 			return -ENOMEM;
720d6d901c2SZhang, Yanmin 
721d6d901c2SZhang, Yanmin 		all_tids[0] = target_tid;
722d6d901c2SZhang, Yanmin 		thread_num = 1;
723d6d901c2SZhang, Yanmin 	}
724d6d901c2SZhang, Yanmin 
725d6d901c2SZhang, Yanmin 	for (i = 0; i < MAX_NR_CPUS; i++) {
726d6d901c2SZhang, Yanmin 		for (j = 0; j < MAX_COUNTERS; j++) {
727d6d901c2SZhang, Yanmin 			fd[i][j] = malloc(sizeof(int)*thread_num);
728d6d901c2SZhang, Yanmin 			if (!fd[i][j])
729d6d901c2SZhang, Yanmin 				return -ENOMEM;
730d6d901c2SZhang, Yanmin 		}
731d6d901c2SZhang, Yanmin 	}
732d6d901c2SZhang, Yanmin 
73386470930SIngo Molnar 	/*
73486470930SIngo Molnar 	 * We dont want to block the signals - that would cause
73586470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
73686470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
73786470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
73886470930SIngo Molnar 	 */
739f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
74086470930SIngo Molnar 	signal(SIGINT,  skip_signal);
74186470930SIngo Molnar 	signal(SIGALRM, skip_signal);
74286470930SIngo Molnar 	signal(SIGABRT, skip_signal);
74386470930SIngo Molnar 
74442202dd5SIngo Molnar 	status = 0;
74542202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
74642202dd5SIngo Molnar 		if (run_count != 1 && verbose)
74742202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
74842202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
74942202dd5SIngo Molnar 	}
75042202dd5SIngo Molnar 
751084ab9f8SArnaldo Carvalho de Melo 	if (status != -1)
75242202dd5SIngo Molnar 		print_stat(argc, argv);
75342202dd5SIngo Molnar 
75442202dd5SIngo Molnar 	return status;
75586470930SIngo Molnar }
756