xref: /openbmc/linux/tools/perf/builtin-stat.c (revision 7b60a7e3)
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 
92cba3ffbSIngo Molnar    $ perf stat ./hackbench 10
1086470930SIngo Molnar 
112cba3ffbSIngo Molnar   Time: 0.118
1286470930SIngo Molnar 
132cba3ffbSIngo Molnar   Performance counter stats for './hackbench 10':
1486470930SIngo Molnar 
152cba3ffbSIngo Molnar        1708.761321 task-clock                #   11.037 CPUs utilized
162cba3ffbSIngo Molnar             41,190 context-switches          #    0.024 M/sec
172cba3ffbSIngo Molnar              6,735 CPU-migrations            #    0.004 M/sec
182cba3ffbSIngo Molnar             17,318 page-faults               #    0.010 M/sec
192cba3ffbSIngo Molnar      5,205,202,243 cycles                    #    3.046 GHz
202cba3ffbSIngo Molnar      3,856,436,920 stalled-cycles-frontend   #   74.09% frontend cycles idle
212cba3ffbSIngo Molnar      1,600,790,871 stalled-cycles-backend    #   30.75% backend  cycles idle
222cba3ffbSIngo Molnar      2,603,501,247 instructions              #    0.50  insns per cycle
232cba3ffbSIngo Molnar                                              #    1.48  stalled cycles per insn
242cba3ffbSIngo Molnar        484,357,498 branches                  #  283.455 M/sec
252cba3ffbSIngo Molnar          6,388,934 branch-misses             #    1.32% of all branches
262cba3ffbSIngo Molnar 
272cba3ffbSIngo Molnar         0.154822978  seconds time elapsed
2886470930SIngo Molnar 
2986470930SIngo Molnar  *
302cba3ffbSIngo Molnar  * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
3186470930SIngo Molnar  *
3286470930SIngo Molnar  * Improvements and fixes by:
3386470930SIngo Molnar  *
3486470930SIngo Molnar  *   Arjan van de Ven <arjan@linux.intel.com>
3586470930SIngo Molnar  *   Yanmin Zhang <yanmin.zhang@intel.com>
3686470930SIngo Molnar  *   Wu Fengguang <fengguang.wu@intel.com>
3786470930SIngo Molnar  *   Mike Galbraith <efault@gmx.de>
3886470930SIngo Molnar  *   Paul Mackerras <paulus@samba.org>
396e750a8fSJaswinder Singh Rajput  *   Jaswinder Singh Rajput <jaswinder@kernel.org>
4086470930SIngo Molnar  *
4186470930SIngo Molnar  * Released under the GPL v2. (and only v2, not any later version)
4286470930SIngo Molnar  */
4386470930SIngo Molnar 
4486470930SIngo Molnar #include "perf.h"
4586470930SIngo Molnar #include "builtin.h"
46f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
4786470930SIngo Molnar #include "util/util.h"
484b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
4986470930SIngo Molnar #include "util/parse-events.h"
504cabc3d1SAndi Kleen #include "util/pmu.h"
518f28827aSFrederic Weisbecker #include "util/event.h"
52361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
5369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
548f28827aSFrederic Weisbecker #include "util/debug.h"
55a5d243d0SIngo Molnar #include "util/color.h"
560007eceaSXiao Guangrong #include "util/stat.h"
5760666c63SLiming Wang #include "util/header.h"
58a12b51c4SPaul Mackerras #include "util/cpumap.h"
59d6d901c2SZhang, Yanmin #include "util/thread.h"
60fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
61d809560bSJiri Olsa #include "util/counts.h"
624979d0c7SJiri Olsa #include "util/session.h"
6386470930SIngo Molnar 
641f16c575SPeter Zijlstra #include <stdlib.h>
6586470930SIngo Molnar #include <sys/prctl.h>
665af52b51SStephane Eranian #include <locale.h>
6786470930SIngo Molnar 
68d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR	" "
692cee77c4SDavid Ahern #define CNTR_NOT_SUPPORTED	"<not supported>"
702cee77c4SDavid Ahern #define CNTR_NOT_COUNTED	"<not counted>"
71d7470b6aSStephane Eranian 
72d4f63a47SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv);
7313370a9bSStephane Eranian 
744cabc3d1SAndi Kleen /* Default events used for perf stat -T */
75a454742cSJiri Olsa static const char *transaction_attrs = {
76a454742cSJiri Olsa 	"task-clock,"
774cabc3d1SAndi Kleen 	"{"
784cabc3d1SAndi Kleen 	"instructions,"
794cabc3d1SAndi Kleen 	"cycles,"
804cabc3d1SAndi Kleen 	"cpu/cycles-t/,"
814cabc3d1SAndi Kleen 	"cpu/tx-start/,"
824cabc3d1SAndi Kleen 	"cpu/el-start/,"
834cabc3d1SAndi Kleen 	"cpu/cycles-ct/"
844cabc3d1SAndi Kleen 	"}"
854cabc3d1SAndi Kleen };
864cabc3d1SAndi Kleen 
874cabc3d1SAndi Kleen /* More limited version when the CPU does not have all events. */
88a454742cSJiri Olsa static const char * transaction_limited_attrs = {
89a454742cSJiri Olsa 	"task-clock,"
904cabc3d1SAndi Kleen 	"{"
914cabc3d1SAndi Kleen 	"instructions,"
924cabc3d1SAndi Kleen 	"cycles,"
934cabc3d1SAndi Kleen 	"cpu/cycles-t/,"
944cabc3d1SAndi Kleen 	"cpu/tx-start/"
954cabc3d1SAndi Kleen 	"}"
964cabc3d1SAndi Kleen };
974cabc3d1SAndi Kleen 
98666e6d48SRobert Richter static struct perf_evlist	*evsel_list;
99361c99a6SArnaldo Carvalho de Melo 
100602ad878SArnaldo Carvalho de Melo static struct target target = {
10177a6f014SNamhyung Kim 	.uid	= UINT_MAX,
10277a6f014SNamhyung Kim };
10342202dd5SIngo Molnar 
1041e5a2931SJiri Olsa typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
1051e5a2931SJiri Olsa 
1063d632595SJaswinder Singh Rajput static int			run_count			=  1;
1072e6cdf99SStephane Eranian static bool			no_inherit			= false;
108d07f0b12SStephane Eranian static volatile pid_t		child_pid			= -1;
109c0555642SIan Munsie static bool			null_run			=  false;
1102cba3ffbSIngo Molnar static int			detailed_run			=  0;
1114cabc3d1SAndi Kleen static bool			transaction_run;
112201e0b06SArnaldo Carvalho de Melo static bool			big_num				=  true;
113d7470b6aSStephane Eranian static int			big_num_opt			=  -1;
114d7470b6aSStephane Eranian static const char		*csv_sep			= NULL;
115d7470b6aSStephane Eranian static bool			csv_output			= false;
11643bece79SLin Ming static bool			group				= false;
1171f16c575SPeter Zijlstra static const char		*pre_cmd			= NULL;
1181f16c575SPeter Zijlstra static const char		*post_cmd			= NULL;
1191f16c575SPeter Zijlstra static bool			sync_run			= false;
12041191688SAndi Kleen static unsigned int		initial_delay			= 0;
121410136f5SStephane Eranian static unsigned int		unit_width			= 4; /* strlen("unit") */
122a7e191c3SFrederik Deweerdt static bool			forever				= false;
12313370a9bSStephane Eranian static struct timespec		ref_time;
12486ee6e18SStephane Eranian static struct cpu_map		*aggr_map;
1251e5a2931SJiri Olsa static aggr_get_id_t		aggr_get_id;
126e0547311SJiri Olsa static bool			append_file;
127e0547311SJiri Olsa static const char		*output_name;
128e0547311SJiri Olsa static int			output_fd;
1295af52b51SStephane Eranian 
1304979d0c7SJiri Olsa struct perf_stat {
1314979d0c7SJiri Olsa 	bool			 record;
1324979d0c7SJiri Olsa 	struct perf_data_file	 file;
1334979d0c7SJiri Olsa 	struct perf_session	*session;
1344979d0c7SJiri Olsa 	u64			 bytes_written;
1354979d0c7SJiri Olsa };
1364979d0c7SJiri Olsa 
1374979d0c7SJiri Olsa static struct perf_stat		perf_stat;
1384979d0c7SJiri Olsa #define STAT_RECORD		perf_stat.record
1394979d0c7SJiri Olsa 
14060666c63SLiming Wang static volatile int done = 0;
14160666c63SLiming Wang 
142421a50f3SJiri Olsa static struct perf_stat_config stat_config = {
143421a50f3SJiri Olsa 	.aggr_mode	= AGGR_GLOBAL,
144711a572eSJiri Olsa 	.scale		= true,
145421a50f3SJiri Olsa };
146421a50f3SJiri Olsa 
14713370a9bSStephane Eranian static inline void diff_timespec(struct timespec *r, struct timespec *a,
14813370a9bSStephane Eranian 				 struct timespec *b)
14913370a9bSStephane Eranian {
15013370a9bSStephane Eranian 	r->tv_sec = a->tv_sec - b->tv_sec;
15113370a9bSStephane Eranian 	if (a->tv_nsec < b->tv_nsec) {
15213370a9bSStephane Eranian 		r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec;
15313370a9bSStephane Eranian 		r->tv_sec--;
15413370a9bSStephane Eranian 	} else {
15513370a9bSStephane Eranian 		r->tv_nsec = a->tv_nsec - b->tv_nsec ;
15613370a9bSStephane Eranian 	}
15713370a9bSStephane Eranian }
15813370a9bSStephane Eranian 
159254ecbc7SJiri Olsa static void perf_stat__reset_stats(void)
160254ecbc7SJiri Olsa {
161254ecbc7SJiri Olsa 	perf_evlist__reset_stats(evsel_list);
162f87027b9SJiri Olsa 	perf_stat__reset_shadow_stats();
1631eda3b21SJiri Olsa }
1641eda3b21SJiri Olsa 
165cac21425SJiri Olsa static int create_perf_stat_counter(struct perf_evsel *evsel)
16686470930SIngo Molnar {
16769aad6f1SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
168727ab04eSArnaldo Carvalho de Melo 
169711a572eSJiri Olsa 	if (stat_config.scale)
17086470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
17186470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
17286470930SIngo Molnar 
1732e6cdf99SStephane Eranian 	attr->inherit = !no_inherit;
1745d2cd909SArnaldo Carvalho de Melo 
1756acd8e92SJiri Olsa 	/*
1766acd8e92SJiri Olsa 	 * Some events get initialized with sample_(period/type) set,
1776acd8e92SJiri Olsa 	 * like tracepoints. Clear it up for counting.
1786acd8e92SJiri Olsa 	 */
1796acd8e92SJiri Olsa 	attr->sample_period = 0;
1804979d0c7SJiri Olsa 	/*
1814979d0c7SJiri Olsa 	 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
1824979d0c7SJiri Olsa 	 * while avoiding that older tools show confusing messages.
1834979d0c7SJiri Olsa 	 */
1844979d0c7SJiri Olsa 	attr->sample_type   = PERF_SAMPLE_IDENTIFIER;
1856acd8e92SJiri Olsa 
18667ccdecdSJiri Olsa 	/*
18767ccdecdSJiri Olsa 	 * Disabling all counters initially, they will be enabled
18867ccdecdSJiri Olsa 	 * either manually by us or by kernel via enable_on_exec
18967ccdecdSJiri Olsa 	 * set later.
19067ccdecdSJiri Olsa 	 */
191c8280cecSJiri Olsa 	if (perf_evsel__is_group_leader(evsel)) {
19267ccdecdSJiri Olsa 		attr->disabled = 1;
19367ccdecdSJiri Olsa 
194c8280cecSJiri Olsa 		/*
195c8280cecSJiri Olsa 		 * In case of initial_delay we enable tracee
196c8280cecSJiri Olsa 		 * events manually.
197c8280cecSJiri Olsa 		 */
198c8280cecSJiri Olsa 		if (target__none(&target) && !initial_delay)
199c8280cecSJiri Olsa 			attr->enable_on_exec = 1;
200c8280cecSJiri Olsa 	}
201c8280cecSJiri Olsa 
202602ad878SArnaldo Carvalho de Melo 	if (target__has_cpu(&target))
203594ac61aSArnaldo Carvalho de Melo 		return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
2045622c07bSStephane Eranian 
205594ac61aSArnaldo Carvalho de Melo 	return perf_evsel__open_per_thread(evsel, evsel_list->threads);
20686470930SIngo Molnar }
20786470930SIngo Molnar 
20886470930SIngo Molnar /*
20986470930SIngo Molnar  * Does the counter have nsecs as a unit?
21086470930SIngo Molnar  */
211daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel)
21286470930SIngo Molnar {
213daec78a0SArnaldo Carvalho de Melo 	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
214daec78a0SArnaldo Carvalho de Melo 	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
21586470930SIngo Molnar 		return 1;
21686470930SIngo Molnar 
21786470930SIngo Molnar 	return 0;
21886470930SIngo Molnar }
21986470930SIngo Molnar 
2208b99b1a4SJiri Olsa static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
2214979d0c7SJiri Olsa 				     union perf_event *event,
2224979d0c7SJiri Olsa 				     struct perf_sample *sample __maybe_unused,
2234979d0c7SJiri Olsa 				     struct machine *machine __maybe_unused)
2244979d0c7SJiri Olsa {
2258b99b1a4SJiri Olsa 	if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) {
2268b99b1a4SJiri Olsa 		pr_err("failed to write perf data, error: %m\n");
2278b99b1a4SJiri Olsa 		return -1;
2288b99b1a4SJiri Olsa 	}
2298b99b1a4SJiri Olsa 
2308b99b1a4SJiri Olsa 	perf_stat.bytes_written += event->header.size;
2318b99b1a4SJiri Olsa 	return 0;
2324979d0c7SJiri Olsa }
2334979d0c7SJiri Olsa 
2347aad0c32SJiri Olsa static int write_stat_round_event(u64 time, u64 type)
2357aad0c32SJiri Olsa {
2367aad0c32SJiri Olsa 	return perf_event__synthesize_stat_round(NULL, time, type,
2377aad0c32SJiri Olsa 						 process_synthesized_event,
2387aad0c32SJiri Olsa 						 NULL);
2397aad0c32SJiri Olsa }
2407aad0c32SJiri Olsa 
2417aad0c32SJiri Olsa #define WRITE_STAT_ROUND_EVENT(time, interval) \
2427aad0c32SJiri Olsa 	write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)
2437aad0c32SJiri Olsa 
2445a6ea81bSJiri Olsa #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
2455a6ea81bSJiri Olsa 
2465a6ea81bSJiri Olsa static int
2475a6ea81bSJiri Olsa perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
2485a6ea81bSJiri Olsa 			     struct perf_counts_values *count)
2495a6ea81bSJiri Olsa {
2505a6ea81bSJiri Olsa 	struct perf_sample_id *sid = SID(counter, cpu, thread);
2515a6ea81bSJiri Olsa 
2525a6ea81bSJiri Olsa 	return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
2535a6ea81bSJiri Olsa 					   process_synthesized_event, NULL);
2545a6ea81bSJiri Olsa }
2555a6ea81bSJiri Olsa 
256f5b4a9c3SStephane Eranian /*
257f5b4a9c3SStephane Eranian  * Read out the results of a single counter:
258f5b4a9c3SStephane Eranian  * do not aggregate counts across CPUs in system-wide mode
259f5b4a9c3SStephane Eranian  */
260c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter)
261f5b4a9c3SStephane Eranian {
2629bf1a529SJiri Olsa 	int nthreads = thread_map__nr(evsel_list->threads);
2639bf1a529SJiri Olsa 	int ncpus = perf_evsel__nr_cpus(counter);
2649bf1a529SJiri Olsa 	int cpu, thread;
265f5b4a9c3SStephane Eranian 
2663b4331d9SSuzuki K. Poulose 	if (!counter->supported)
2673b4331d9SSuzuki K. Poulose 		return -ENOENT;
2683b4331d9SSuzuki K. Poulose 
2699bf1a529SJiri Olsa 	if (counter->system_wide)
2709bf1a529SJiri Olsa 		nthreads = 1;
2719bf1a529SJiri Olsa 
2729bf1a529SJiri Olsa 	for (thread = 0; thread < nthreads; thread++) {
2739bf1a529SJiri Olsa 		for (cpu = 0; cpu < ncpus; cpu++) {
2743b3eb044SJiri Olsa 			struct perf_counts_values *count;
2753b3eb044SJiri Olsa 
2763b3eb044SJiri Olsa 			count = perf_counts(counter->counts, cpu, thread);
2773b3eb044SJiri Olsa 			if (perf_evsel__read(counter, cpu, thread, count))
278c52b12edSArnaldo Carvalho de Melo 				return -1;
2795a6ea81bSJiri Olsa 
2805a6ea81bSJiri Olsa 			if (STAT_RECORD) {
2815a6ea81bSJiri Olsa 				if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
2825a6ea81bSJiri Olsa 					pr_err("failed to write stat event\n");
2835a6ea81bSJiri Olsa 					return -1;
2845a6ea81bSJiri Olsa 				}
2855a6ea81bSJiri Olsa 			}
286f5b4a9c3SStephane Eranian 		}
2879bf1a529SJiri Olsa 	}
288c52b12edSArnaldo Carvalho de Melo 
289c52b12edSArnaldo Carvalho de Melo 	return 0;
29086470930SIngo Molnar }
29186470930SIngo Molnar 
2925fc472a6SJiri Olsa static void read_counters(bool close_counters)
293106a94a0SJiri Olsa {
294106a94a0SJiri Olsa 	struct perf_evsel *counter;
295106a94a0SJiri Olsa 
296106a94a0SJiri Olsa 	evlist__for_each(evsel_list, counter) {
2973b3eb044SJiri Olsa 		if (read_counter(counter))
298245bad8eSAndi Kleen 			pr_debug("failed to read counter %s\n", counter->name);
2993b3eb044SJiri Olsa 
300f80010ebSJiri Olsa 		if (perf_stat_process_counter(&stat_config, counter))
3013b3eb044SJiri Olsa 			pr_warning("failed to process counter %s\n", counter->name);
302106a94a0SJiri Olsa 
3035fc472a6SJiri Olsa 		if (close_counters) {
304106a94a0SJiri Olsa 			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
305106a94a0SJiri Olsa 					     thread_map__nr(evsel_list->threads));
306106a94a0SJiri Olsa 		}
307106a94a0SJiri Olsa 	}
308106a94a0SJiri Olsa }
309106a94a0SJiri Olsa 
310ba411a95SJiri Olsa static void process_interval(void)
31113370a9bSStephane Eranian {
31213370a9bSStephane Eranian 	struct timespec ts, rs;
31313370a9bSStephane Eranian 
314106a94a0SJiri Olsa 	read_counters(false);
31586ee6e18SStephane Eranian 
31613370a9bSStephane Eranian 	clock_gettime(CLOCK_MONOTONIC, &ts);
31713370a9bSStephane Eranian 	diff_timespec(&rs, &ts, &ref_time);
31813370a9bSStephane Eranian 
3197aad0c32SJiri Olsa 	if (STAT_RECORD) {
3207aad0c32SJiri Olsa 		if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL))
3217aad0c32SJiri Olsa 			pr_err("failed to write stat round event\n");
3227aad0c32SJiri Olsa 	}
3237aad0c32SJiri Olsa 
324d4f63a47SJiri Olsa 	print_counters(&rs, 0, NULL);
32513370a9bSStephane Eranian }
32613370a9bSStephane Eranian 
32767ccdecdSJiri Olsa static void enable_counters(void)
32841191688SAndi Kleen {
32967ccdecdSJiri Olsa 	if (initial_delay)
33041191688SAndi Kleen 		usleep(initial_delay * 1000);
33167ccdecdSJiri Olsa 
33267ccdecdSJiri Olsa 	/*
33367ccdecdSJiri Olsa 	 * We need to enable counters only if:
33467ccdecdSJiri Olsa 	 * - we don't have tracee (attaching to task or cpu)
33567ccdecdSJiri Olsa 	 * - we have initial delay configured
33667ccdecdSJiri Olsa 	 */
33767ccdecdSJiri Olsa 	if (!target__none(&target) || initial_delay)
338ab46db0aSJiri Olsa 		perf_evlist__enable(evsel_list);
33941191688SAndi Kleen }
34041191688SAndi Kleen 
341f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
3426af206fdSArnaldo Carvalho de Melo 
3436af206fdSArnaldo Carvalho de Melo /*
3446af206fdSArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
3456af206fdSArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
3466af206fdSArnaldo Carvalho de Melo  * want_signal to true.
3476af206fdSArnaldo Carvalho de Melo  */
348f33cbe72SArnaldo Carvalho de Melo static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
349f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
3506af206fdSArnaldo Carvalho de Melo {
351f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
3526af206fdSArnaldo Carvalho de Melo }
3536af206fdSArnaldo Carvalho de Melo 
3547b60a7e3SJiri Olsa static bool has_unit(struct perf_evsel *counter)
3557b60a7e3SJiri Olsa {
3567b60a7e3SJiri Olsa 	return counter->unit && *counter->unit;
3577b60a7e3SJiri Olsa }
3587b60a7e3SJiri Olsa 
3597b60a7e3SJiri Olsa static bool has_scale(struct perf_evsel *counter)
3607b60a7e3SJiri Olsa {
3617b60a7e3SJiri Olsa 	return counter->scale != 1;
3627b60a7e3SJiri Olsa }
3637b60a7e3SJiri Olsa 
364664c98d4SJiri Olsa static int perf_stat_synthesize_config(bool is_pipe)
3658b99b1a4SJiri Olsa {
3667b60a7e3SJiri Olsa 	struct perf_evsel *counter;
3678b99b1a4SJiri Olsa 	int err;
3688b99b1a4SJiri Olsa 
369664c98d4SJiri Olsa 	if (is_pipe) {
370664c98d4SJiri Olsa 		err = perf_event__synthesize_attrs(NULL, perf_stat.session,
371664c98d4SJiri Olsa 						   process_synthesized_event);
372664c98d4SJiri Olsa 		if (err < 0) {
373664c98d4SJiri Olsa 			pr_err("Couldn't synthesize attrs.\n");
374664c98d4SJiri Olsa 			return err;
375664c98d4SJiri Olsa 		}
376664c98d4SJiri Olsa 	}
377664c98d4SJiri Olsa 
3787b60a7e3SJiri Olsa 	/*
3797b60a7e3SJiri Olsa 	 * Synthesize other events stuff not carried within
3807b60a7e3SJiri Olsa 	 * attr event - unit, scale, name
3817b60a7e3SJiri Olsa 	 */
3827b60a7e3SJiri Olsa 	evlist__for_each(evsel_list, counter) {
3837b60a7e3SJiri Olsa 		if (!counter->supported)
3847b60a7e3SJiri Olsa 			continue;
3857b60a7e3SJiri Olsa 
3867b60a7e3SJiri Olsa 		/*
3877b60a7e3SJiri Olsa 		 * Synthesize unit and scale only if it's defined.
3887b60a7e3SJiri Olsa 		 */
3897b60a7e3SJiri Olsa 		if (has_unit(counter)) {
3907b60a7e3SJiri Olsa 			err = perf_event__synthesize_event_update_unit(NULL, counter, process_synthesized_event);
3917b60a7e3SJiri Olsa 			if (err < 0) {
3927b60a7e3SJiri Olsa 				pr_err("Couldn't synthesize evsel unit.\n");
3937b60a7e3SJiri Olsa 				return err;
3947b60a7e3SJiri Olsa 			}
3957b60a7e3SJiri Olsa 		}
3967b60a7e3SJiri Olsa 
3977b60a7e3SJiri Olsa 		if (has_scale(counter)) {
3987b60a7e3SJiri Olsa 			err = perf_event__synthesize_event_update_scale(NULL, counter, process_synthesized_event);
3997b60a7e3SJiri Olsa 			if (err < 0) {
4007b60a7e3SJiri Olsa 				pr_err("Couldn't synthesize evsel scale.\n");
4017b60a7e3SJiri Olsa 				return err;
4027b60a7e3SJiri Olsa 			}
4037b60a7e3SJiri Olsa 		}
4047b60a7e3SJiri Olsa 
4057b60a7e3SJiri Olsa 		if (counter->own_cpus) {
4067b60a7e3SJiri Olsa 			err = perf_event__synthesize_event_update_cpus(NULL, counter, process_synthesized_event);
4077b60a7e3SJiri Olsa 			if (err < 0) {
4087b60a7e3SJiri Olsa 				pr_err("Couldn't synthesize evsel scale.\n");
4097b60a7e3SJiri Olsa 				return err;
4107b60a7e3SJiri Olsa 			}
4117b60a7e3SJiri Olsa 		}
4127b60a7e3SJiri Olsa 
4137b60a7e3SJiri Olsa 		/*
4147b60a7e3SJiri Olsa 		 * Name is needed only for pipe output,
4157b60a7e3SJiri Olsa 		 * perf.data carries event names.
4167b60a7e3SJiri Olsa 		 */
4177b60a7e3SJiri Olsa 		if (is_pipe) {
4187b60a7e3SJiri Olsa 			err = perf_event__synthesize_event_update_name(NULL, counter, process_synthesized_event);
4197b60a7e3SJiri Olsa 			if (err < 0) {
4207b60a7e3SJiri Olsa 				pr_err("Couldn't synthesize evsel name.\n");
4217b60a7e3SJiri Olsa 				return err;
4227b60a7e3SJiri Olsa 			}
4237b60a7e3SJiri Olsa 		}
4247b60a7e3SJiri Olsa 	}
4257b60a7e3SJiri Olsa 
4268b99b1a4SJiri Olsa 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
4278b99b1a4SJiri Olsa 						process_synthesized_event,
4288b99b1a4SJiri Olsa 						NULL);
4298b99b1a4SJiri Olsa 	if (err < 0) {
4308b99b1a4SJiri Olsa 		pr_err("Couldn't synthesize thread map.\n");
4318b99b1a4SJiri Olsa 		return err;
4328b99b1a4SJiri Olsa 	}
4338b99b1a4SJiri Olsa 
4348b99b1a4SJiri Olsa 	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
4358b99b1a4SJiri Olsa 					     process_synthesized_event, NULL);
4368b99b1a4SJiri Olsa 	if (err < 0) {
4378b99b1a4SJiri Olsa 		pr_err("Couldn't synthesize thread map.\n");
4388b99b1a4SJiri Olsa 		return err;
4398b99b1a4SJiri Olsa 	}
4408b99b1a4SJiri Olsa 
4418b99b1a4SJiri Olsa 	err = perf_event__synthesize_stat_config(NULL, &stat_config,
4428b99b1a4SJiri Olsa 						 process_synthesized_event, NULL);
4438b99b1a4SJiri Olsa 	if (err < 0) {
4448b99b1a4SJiri Olsa 		pr_err("Couldn't synthesize config.\n");
4458b99b1a4SJiri Olsa 		return err;
4468b99b1a4SJiri Olsa 	}
4478b99b1a4SJiri Olsa 
4488b99b1a4SJiri Olsa 	return 0;
4498b99b1a4SJiri Olsa }
4508b99b1a4SJiri Olsa 
4512af4646dSJiri Olsa #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
4522af4646dSJiri Olsa 
4532af4646dSJiri Olsa static int __store_counter_ids(struct perf_evsel *counter,
4542af4646dSJiri Olsa 			       struct cpu_map *cpus,
4552af4646dSJiri Olsa 			       struct thread_map *threads)
4562af4646dSJiri Olsa {
4572af4646dSJiri Olsa 	int cpu, thread;
4582af4646dSJiri Olsa 
4592af4646dSJiri Olsa 	for (cpu = 0; cpu < cpus->nr; cpu++) {
4602af4646dSJiri Olsa 		for (thread = 0; thread < threads->nr; thread++) {
4612af4646dSJiri Olsa 			int fd = FD(counter, cpu, thread);
4622af4646dSJiri Olsa 
4632af4646dSJiri Olsa 			if (perf_evlist__id_add_fd(evsel_list, counter,
4642af4646dSJiri Olsa 						   cpu, thread, fd) < 0)
4652af4646dSJiri Olsa 				return -1;
4662af4646dSJiri Olsa 		}
4672af4646dSJiri Olsa 	}
4682af4646dSJiri Olsa 
4692af4646dSJiri Olsa 	return 0;
4702af4646dSJiri Olsa }
4712af4646dSJiri Olsa 
4722af4646dSJiri Olsa static int store_counter_ids(struct perf_evsel *counter)
4732af4646dSJiri Olsa {
4742af4646dSJiri Olsa 	struct cpu_map *cpus = counter->cpus;
4752af4646dSJiri Olsa 	struct thread_map *threads = counter->threads;
4762af4646dSJiri Olsa 
4772af4646dSJiri Olsa 	if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
4782af4646dSJiri Olsa 		return -ENOMEM;
4792af4646dSJiri Olsa 
4802af4646dSJiri Olsa 	return __store_counter_ids(counter, cpus, threads);
4812af4646dSJiri Olsa }
4822af4646dSJiri Olsa 
483acf28922SNamhyung Kim static int __run_perf_stat(int argc, const char **argv)
48486470930SIngo Molnar {
485ec0d3d1fSJiri Olsa 	int interval = stat_config.interval;
48656e52e85SArnaldo Carvalho de Melo 	char msg[512];
48786470930SIngo Molnar 	unsigned long long t0, t1;
488cac21425SJiri Olsa 	struct perf_evsel *counter;
48913370a9bSStephane Eranian 	struct timespec ts;
490410136f5SStephane Eranian 	size_t l;
49142202dd5SIngo Molnar 	int status = 0;
4926be2850eSZhang, Yanmin 	const bool forks = (argc > 0);
493664c98d4SJiri Olsa 	bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
49486470930SIngo Molnar 
49513370a9bSStephane Eranian 	if (interval) {
49613370a9bSStephane Eranian 		ts.tv_sec  = interval / 1000;
49713370a9bSStephane Eranian 		ts.tv_nsec = (interval % 1000) * 1000000;
49813370a9bSStephane Eranian 	} else {
49913370a9bSStephane Eranian 		ts.tv_sec  = 1;
50013370a9bSStephane Eranian 		ts.tv_nsec = 0;
50113370a9bSStephane Eranian 	}
50213370a9bSStephane Eranian 
503acf28922SNamhyung Kim 	if (forks) {
504664c98d4SJiri Olsa 		if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
505735f7e0bSArnaldo Carvalho de Melo 						  workload_exec_failed_signal) < 0) {
506acf28922SNamhyung Kim 			perror("failed to prepare workload");
507fceda7feSDavid Ahern 			return -1;
508051ae7f7SPaul Mackerras 		}
509d20a47e7SNamhyung Kim 		child_pid = evsel_list->workload.pid;
51060666c63SLiming Wang 	}
511051ae7f7SPaul Mackerras 
5126a4bb04cSJiri Olsa 	if (group)
51363dab225SArnaldo Carvalho de Melo 		perf_evlist__set_leader(evsel_list);
5146a4bb04cSJiri Olsa 
5150050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evsel_list, counter) {
516cac21425SJiri Olsa 		if (create_perf_stat_counter(counter) < 0) {
517979987a5SDavid Ahern 			/*
518979987a5SDavid Ahern 			 * PPC returns ENXIO for HW counters until 2.6.37
519979987a5SDavid Ahern 			 * (behavior changed with commit b0a873e).
520979987a5SDavid Ahern 			 */
52138f6ae1eSAnton Blanchard 			if (errno == EINVAL || errno == ENOSYS ||
522979987a5SDavid Ahern 			    errno == ENOENT || errno == EOPNOTSUPP ||
523979987a5SDavid Ahern 			    errno == ENXIO) {
524c63ca0c0SDavid Ahern 				if (verbose)
525c63ca0c0SDavid Ahern 					ui__warning("%s event is not supported by the kernel.\n",
5267289f83cSArnaldo Carvalho de Melo 						    perf_evsel__name(counter));
5272cee77c4SDavid Ahern 				counter->supported = false;
528cb5ef600SKan Liang 
529cb5ef600SKan Liang 				if ((counter->leader != counter) ||
530cb5ef600SKan Liang 				    !(counter->leader->nr_members > 1))
531ede70290SIngo Molnar 					continue;
532c63ca0c0SDavid Ahern 			}
533ede70290SIngo Molnar 
53456e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(counter, &target,
53556e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
53656e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
53756e52e85SArnaldo Carvalho de Melo 
538084ab9f8SArnaldo Carvalho de Melo 			if (child_pid != -1)
539084ab9f8SArnaldo Carvalho de Melo 				kill(child_pid, SIGTERM);
540fceda7feSDavid Ahern 
541084ab9f8SArnaldo Carvalho de Melo 			return -1;
542084ab9f8SArnaldo Carvalho de Melo 		}
5432cee77c4SDavid Ahern 		counter->supported = true;
544410136f5SStephane Eranian 
545410136f5SStephane Eranian 		l = strlen(counter->unit);
546410136f5SStephane Eranian 		if (l > unit_width)
547410136f5SStephane Eranian 			unit_width = l;
5482af4646dSJiri Olsa 
5492af4646dSJiri Olsa 		if (STAT_RECORD && store_counter_ids(counter))
5502af4646dSJiri Olsa 			return -1;
55148290609SArnaldo Carvalho de Melo 	}
55286470930SIngo Molnar 
55323d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evsel_list, &counter)) {
55423d4aad4SArnaldo Carvalho de Melo 		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
55523d4aad4SArnaldo Carvalho de Melo 			counter->filter, perf_evsel__name(counter), errno,
556759e612bSMasami Hiramatsu 			strerror_r(errno, msg, sizeof(msg)));
557cfd748aeSFrederic Weisbecker 		return -1;
558cfd748aeSFrederic Weisbecker 	}
559cfd748aeSFrederic Weisbecker 
5604979d0c7SJiri Olsa 	if (STAT_RECORD) {
5614979d0c7SJiri Olsa 		int err, fd = perf_data_file__fd(&perf_stat.file);
5624979d0c7SJiri Olsa 
563664c98d4SJiri Olsa 		if (is_pipe) {
564664c98d4SJiri Olsa 			err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file));
565664c98d4SJiri Olsa 		} else {
5664979d0c7SJiri Olsa 			err = perf_session__write_header(perf_stat.session, evsel_list,
5674979d0c7SJiri Olsa 							 fd, false);
568664c98d4SJiri Olsa 		}
569664c98d4SJiri Olsa 
5704979d0c7SJiri Olsa 		if (err < 0)
5714979d0c7SJiri Olsa 			return err;
5728b99b1a4SJiri Olsa 
573664c98d4SJiri Olsa 		err = perf_stat_synthesize_config(is_pipe);
5748b99b1a4SJiri Olsa 		if (err < 0)
5758b99b1a4SJiri Olsa 			return err;
5764979d0c7SJiri Olsa 	}
5774979d0c7SJiri Olsa 
57886470930SIngo Molnar 	/*
57986470930SIngo Molnar 	 * Enable counters and exec the command:
58086470930SIngo Molnar 	 */
58186470930SIngo Molnar 	t0 = rdclock();
58213370a9bSStephane Eranian 	clock_gettime(CLOCK_MONOTONIC, &ref_time);
58386470930SIngo Molnar 
58460666c63SLiming Wang 	if (forks) {
585acf28922SNamhyung Kim 		perf_evlist__start_workload(evsel_list);
58667ccdecdSJiri Olsa 		enable_counters();
587acf28922SNamhyung Kim 
58813370a9bSStephane Eranian 		if (interval) {
58913370a9bSStephane Eranian 			while (!waitpid(child_pid, &status, WNOHANG)) {
59013370a9bSStephane Eranian 				nanosleep(&ts, NULL);
591ba411a95SJiri Olsa 				process_interval();
59213370a9bSStephane Eranian 			}
59313370a9bSStephane Eranian 		}
59442202dd5SIngo Molnar 		wait(&status);
5956af206fdSArnaldo Carvalho de Melo 
596f33cbe72SArnaldo Carvalho de Melo 		if (workload_exec_errno) {
597f33cbe72SArnaldo Carvalho de Melo 			const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
598f33cbe72SArnaldo Carvalho de Melo 			pr_err("Workload failed: %s\n", emsg);
5996af206fdSArnaldo Carvalho de Melo 			return -1;
600f33cbe72SArnaldo Carvalho de Melo 		}
6016af206fdSArnaldo Carvalho de Melo 
60233e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
60333e49ea7SAndi Kleen 			psignal(WTERMSIG(status), argv[0]);
60460666c63SLiming Wang 	} else {
60567ccdecdSJiri Olsa 		enable_counters();
60613370a9bSStephane Eranian 		while (!done) {
60713370a9bSStephane Eranian 			nanosleep(&ts, NULL);
60813370a9bSStephane Eranian 			if (interval)
609ba411a95SJiri Olsa 				process_interval();
61013370a9bSStephane Eranian 		}
61160666c63SLiming Wang 	}
61286470930SIngo Molnar 
61386470930SIngo Molnar 	t1 = rdclock();
61486470930SIngo Molnar 
6159e9772c4SPeter Zijlstra 	update_stats(&walltime_nsecs_stats, t1 - t0);
61642202dd5SIngo Molnar 
617106a94a0SJiri Olsa 	read_counters(true);
618c52b12edSArnaldo Carvalho de Melo 
61942202dd5SIngo Molnar 	return WEXITSTATUS(status);
62042202dd5SIngo Molnar }
62142202dd5SIngo Molnar 
62241cde476SArnaldo Carvalho de Melo static int run_perf_stat(int argc, const char **argv)
6231f16c575SPeter Zijlstra {
6241f16c575SPeter Zijlstra 	int ret;
6251f16c575SPeter Zijlstra 
6261f16c575SPeter Zijlstra 	if (pre_cmd) {
6271f16c575SPeter Zijlstra 		ret = system(pre_cmd);
6281f16c575SPeter Zijlstra 		if (ret)
6291f16c575SPeter Zijlstra 			return ret;
6301f16c575SPeter Zijlstra 	}
6311f16c575SPeter Zijlstra 
6321f16c575SPeter Zijlstra 	if (sync_run)
6331f16c575SPeter Zijlstra 		sync();
6341f16c575SPeter Zijlstra 
6351f16c575SPeter Zijlstra 	ret = __run_perf_stat(argc, argv);
6361f16c575SPeter Zijlstra 	if (ret)
6371f16c575SPeter Zijlstra 		return ret;
6381f16c575SPeter Zijlstra 
6391f16c575SPeter Zijlstra 	if (post_cmd) {
6401f16c575SPeter Zijlstra 		ret = system(post_cmd);
6411f16c575SPeter Zijlstra 		if (ret)
6421f16c575SPeter Zijlstra 			return ret;
6431f16c575SPeter Zijlstra 	}
6441f16c575SPeter Zijlstra 
6451f16c575SPeter Zijlstra 	return ret;
6461f16c575SPeter Zijlstra }
6471f16c575SPeter Zijlstra 
648d73515c0SAndi Kleen static void print_running(u64 run, u64 ena)
649d73515c0SAndi Kleen {
650d73515c0SAndi Kleen 	if (csv_output) {
6515821522eSJiri Olsa 		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
652d73515c0SAndi Kleen 					csv_sep,
653d73515c0SAndi Kleen 					run,
654d73515c0SAndi Kleen 					csv_sep,
655d73515c0SAndi Kleen 					ena ? 100.0 * run / ena : 100.0);
656d73515c0SAndi Kleen 	} else if (run != ena) {
6575821522eSJiri Olsa 		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
658d73515c0SAndi Kleen 	}
659d73515c0SAndi Kleen }
660d73515c0SAndi Kleen 
661f99844cbSIngo Molnar static void print_noise_pct(double total, double avg)
662f99844cbSIngo Molnar {
6630007eceaSXiao Guangrong 	double pct = rel_stddev_stats(total, avg);
664f99844cbSIngo Molnar 
6653ae9a34dSZhengyu He 	if (csv_output)
6665821522eSJiri Olsa 		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
667a1bca6ccSJim Cromie 	else if (pct)
6685821522eSJiri Olsa 		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
669f99844cbSIngo Molnar }
670f99844cbSIngo Molnar 
67169aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg)
67242202dd5SIngo Molnar {
673581cc8a2SJiri Olsa 	struct perf_stat_evsel *ps;
67469aad6f1SArnaldo Carvalho de Melo 
675849abde9SPeter Zijlstra 	if (run_count == 1)
676849abde9SPeter Zijlstra 		return;
677849abde9SPeter Zijlstra 
67869aad6f1SArnaldo Carvalho de Melo 	ps = evsel->priv;
679f99844cbSIngo Molnar 	print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
68042202dd5SIngo Molnar }
68142202dd5SIngo Molnar 
68212c08a9fSStephane Eranian static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
68342202dd5SIngo Molnar {
684421a50f3SJiri Olsa 	switch (stat_config.aggr_mode) {
68512c08a9fSStephane Eranian 	case AGGR_CORE:
6865821522eSJiri Olsa 		fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
68712c08a9fSStephane Eranian 			cpu_map__id_to_socket(id),
68812c08a9fSStephane Eranian 			csv_output ? 0 : -8,
68912c08a9fSStephane Eranian 			cpu_map__id_to_cpu(id),
69012c08a9fSStephane Eranian 			csv_sep,
69112c08a9fSStephane Eranian 			csv_output ? 0 : 4,
69212c08a9fSStephane Eranian 			nr,
69312c08a9fSStephane Eranian 			csv_sep);
69412c08a9fSStephane Eranian 		break;
69586ee6e18SStephane Eranian 	case AGGR_SOCKET:
6965821522eSJiri Olsa 		fprintf(stat_config.output, "S%*d%s%*d%s",
697d7e7a451SStephane Eranian 			csv_output ? 0 : -5,
69812c08a9fSStephane Eranian 			id,
699d7e7a451SStephane Eranian 			csv_sep,
700d7e7a451SStephane Eranian 			csv_output ? 0 : 4,
701d7e7a451SStephane Eranian 			nr,
702d7e7a451SStephane Eranian 			csv_sep);
70386ee6e18SStephane Eranian 			break;
70486ee6e18SStephane Eranian 	case AGGR_NONE:
7055821522eSJiri Olsa 		fprintf(stat_config.output, "CPU%*d%s",
706d7470b6aSStephane Eranian 			csv_output ? 0 : -4,
70712c08a9fSStephane Eranian 			perf_evsel__cpus(evsel)->map[id], csv_sep);
70886ee6e18SStephane Eranian 		break;
70932b8af82SJiri Olsa 	case AGGR_THREAD:
7105821522eSJiri Olsa 		fprintf(stat_config.output, "%*s-%*d%s",
71132b8af82SJiri Olsa 			csv_output ? 0 : 16,
71232b8af82SJiri Olsa 			thread_map__comm(evsel->threads, id),
71332b8af82SJiri Olsa 			csv_output ? 0 : -8,
71432b8af82SJiri Olsa 			thread_map__pid(evsel->threads, id),
71532b8af82SJiri Olsa 			csv_sep);
71632b8af82SJiri Olsa 		break;
71786ee6e18SStephane Eranian 	case AGGR_GLOBAL:
718208df99eSJiri Olsa 	case AGGR_UNSET:
71986ee6e18SStephane Eranian 	default:
72086ee6e18SStephane Eranian 		break;
72186ee6e18SStephane Eranian 	}
72286ee6e18SStephane Eranian }
723d7470b6aSStephane Eranian 
724da88c7f7SAndi Kleen static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
72586ee6e18SStephane Eranian {
7265821522eSJiri Olsa 	FILE *output = stat_config.output;
72786ee6e18SStephane Eranian 	double msecs = avg / 1e6;
728410136f5SStephane Eranian 	const char *fmt_v, *fmt_n;
7294bbe5a61SDavid Ahern 	char name[25];
73086ee6e18SStephane Eranian 
731410136f5SStephane Eranian 	fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
732410136f5SStephane Eranian 	fmt_n = csv_output ? "%s" : "%-25s";
733410136f5SStephane Eranian 
734da88c7f7SAndi Kleen 	aggr_printout(evsel, id, nr);
73586ee6e18SStephane Eranian 
7364bbe5a61SDavid Ahern 	scnprintf(name, sizeof(name), "%s%s",
7374bbe5a61SDavid Ahern 		  perf_evsel__name(evsel), csv_output ? "" : " (msec)");
738410136f5SStephane Eranian 
739410136f5SStephane Eranian 	fprintf(output, fmt_v, msecs, csv_sep);
740410136f5SStephane Eranian 
741410136f5SStephane Eranian 	if (csv_output)
742410136f5SStephane Eranian 		fprintf(output, "%s%s", evsel->unit, csv_sep);
743410136f5SStephane Eranian 	else
744410136f5SStephane Eranian 		fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep);
745410136f5SStephane Eranian 
746410136f5SStephane Eranian 	fprintf(output, fmt_n, name);
747d7470b6aSStephane Eranian 
748023695d9SStephane Eranian 	if (evsel->cgrp)
7494aa9015fSStephane Eranian 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
75042202dd5SIngo Molnar }
75142202dd5SIngo Molnar 
752556b1fb7SJiri Olsa static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
753556b1fb7SJiri Olsa {
7545821522eSJiri Olsa 	FILE *output = stat_config.output;
755556b1fb7SJiri Olsa 	double sc =  evsel->scale;
756556b1fb7SJiri Olsa 	const char *fmt;
757556b1fb7SJiri Olsa 
758556b1fb7SJiri Olsa 	if (csv_output) {
759556b1fb7SJiri Olsa 		fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
760556b1fb7SJiri Olsa 	} else {
761556b1fb7SJiri Olsa 		if (big_num)
762556b1fb7SJiri Olsa 			fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
763556b1fb7SJiri Olsa 		else
764556b1fb7SJiri Olsa 			fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
765556b1fb7SJiri Olsa 	}
766556b1fb7SJiri Olsa 
767556b1fb7SJiri Olsa 	aggr_printout(evsel, id, nr);
768556b1fb7SJiri Olsa 
769556b1fb7SJiri Olsa 	fprintf(output, fmt, avg, csv_sep);
770556b1fb7SJiri Olsa 
771556b1fb7SJiri Olsa 	if (evsel->unit)
772556b1fb7SJiri Olsa 		fprintf(output, "%-*s%s",
773556b1fb7SJiri Olsa 			csv_output ? 0 : unit_width,
774556b1fb7SJiri Olsa 			evsel->unit, csv_sep);
775556b1fb7SJiri Olsa 
776556b1fb7SJiri Olsa 	fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
777556b1fb7SJiri Olsa 
778556b1fb7SJiri Olsa 	if (evsel->cgrp)
779556b1fb7SJiri Olsa 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
780eedfcb4bSAndi Kleen }
781556b1fb7SJiri Olsa 
782eedfcb4bSAndi Kleen static void printout(int id, int nr, struct perf_evsel *counter, double uval)
783eedfcb4bSAndi Kleen {
784eedfcb4bSAndi Kleen 	int cpu = cpu_map__id_to_cpu(id);
785556b1fb7SJiri Olsa 
786eedfcb4bSAndi Kleen 	if (stat_config.aggr_mode == AGGR_GLOBAL)
787eedfcb4bSAndi Kleen 		cpu = 0;
788eedfcb4bSAndi Kleen 
789eedfcb4bSAndi Kleen 	if (nsec_counter(counter))
790eedfcb4bSAndi Kleen 		nsec_printout(id, nr, counter, uval);
791eedfcb4bSAndi Kleen 	else
792eedfcb4bSAndi Kleen 		abs_printout(id, nr, counter, uval);
793eedfcb4bSAndi Kleen 
794eedfcb4bSAndi Kleen 	if (!csv_output && !stat_config.interval)
795eedfcb4bSAndi Kleen 		perf_stat__print_shadow_stats(stat_config.output, counter,
796eedfcb4bSAndi Kleen 					      uval, cpu,
797421a50f3SJiri Olsa 					      stat_config.aggr_mode);
798556b1fb7SJiri Olsa }
799556b1fb7SJiri Olsa 
80086ee6e18SStephane Eranian static void print_aggr(char *prefix)
801d7e7a451SStephane Eranian {
8025821522eSJiri Olsa 	FILE *output = stat_config.output;
803d7e7a451SStephane Eranian 	struct perf_evsel *counter;
804601083cfSKan Liang 	int cpu, s, s2, id, nr;
805410136f5SStephane Eranian 	double uval;
806d7e7a451SStephane Eranian 	u64 ena, run, val;
807d7e7a451SStephane Eranian 
80886ee6e18SStephane Eranian 	if (!(aggr_map || aggr_get_id))
809d7e7a451SStephane Eranian 		return;
810d7e7a451SStephane Eranian 
81186ee6e18SStephane Eranian 	for (s = 0; s < aggr_map->nr; s++) {
81286ee6e18SStephane Eranian 		id = aggr_map->map[s];
8130050f7aaSArnaldo Carvalho de Melo 		evlist__for_each(evsel_list, counter) {
814d7e7a451SStephane Eranian 			val = ena = run = 0;
815d7e7a451SStephane Eranian 			nr = 0;
816d7e7a451SStephane Eranian 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
817601083cfSKan Liang 				s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
81886ee6e18SStephane Eranian 				if (s2 != id)
819d7e7a451SStephane Eranian 					continue;
820a6fa0038SJiri Olsa 				val += perf_counts(counter->counts, cpu, 0)->val;
821a6fa0038SJiri Olsa 				ena += perf_counts(counter->counts, cpu, 0)->ena;
822a6fa0038SJiri Olsa 				run += perf_counts(counter->counts, cpu, 0)->run;
823d7e7a451SStephane Eranian 				nr++;
824d7e7a451SStephane Eranian 			}
825d7e7a451SStephane Eranian 			if (prefix)
826d7e7a451SStephane Eranian 				fprintf(output, "%s", prefix);
827d7e7a451SStephane Eranian 
828d7e7a451SStephane Eranian 			if (run == 0 || ena == 0) {
829582ec082SStephane Eranian 				aggr_printout(counter, id, nr);
83086ee6e18SStephane Eranian 
831410136f5SStephane Eranian 				fprintf(output, "%*s%s",
832d7e7a451SStephane Eranian 					csv_output ? 0 : 18,
833d7e7a451SStephane Eranian 					counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
834410136f5SStephane Eranian 					csv_sep);
835410136f5SStephane Eranian 
836410136f5SStephane Eranian 				fprintf(output, "%-*s%s",
837410136f5SStephane Eranian 					csv_output ? 0 : unit_width,
838410136f5SStephane Eranian 					counter->unit, csv_sep);
839410136f5SStephane Eranian 
840410136f5SStephane Eranian 				fprintf(output, "%*s",
841410136f5SStephane Eranian 					csv_output ? 0 : -25,
842d7e7a451SStephane Eranian 					perf_evsel__name(counter));
84386ee6e18SStephane Eranian 
844d7e7a451SStephane Eranian 				if (counter->cgrp)
845d7e7a451SStephane Eranian 					fprintf(output, "%s%s",
846d7e7a451SStephane Eranian 						csv_sep, counter->cgrp->name);
847d7e7a451SStephane Eranian 
848d73515c0SAndi Kleen 				print_running(run, ena);
849d7e7a451SStephane Eranian 				fputc('\n', output);
850d7e7a451SStephane Eranian 				continue;
851d7e7a451SStephane Eranian 			}
852410136f5SStephane Eranian 			uval = val * counter->scale;
853eedfcb4bSAndi Kleen 			printout(id, nr, counter, uval);
854d73515c0SAndi Kleen 			if (!csv_output)
855d7e7a451SStephane Eranian 				print_noise(counter, 1.0);
856d7e7a451SStephane Eranian 
857d73515c0SAndi Kleen 			print_running(run, ena);
858d7e7a451SStephane Eranian 			fputc('\n', output);
859d7e7a451SStephane Eranian 		}
860d7e7a451SStephane Eranian 	}
861d7e7a451SStephane Eranian }
862d7e7a451SStephane Eranian 
86332b8af82SJiri Olsa static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
86432b8af82SJiri Olsa {
8655821522eSJiri Olsa 	FILE *output = stat_config.output;
86632b8af82SJiri Olsa 	int nthreads = thread_map__nr(counter->threads);
86732b8af82SJiri Olsa 	int ncpus = cpu_map__nr(counter->cpus);
86832b8af82SJiri Olsa 	int cpu, thread;
86932b8af82SJiri Olsa 	double uval;
87032b8af82SJiri Olsa 
87132b8af82SJiri Olsa 	for (thread = 0; thread < nthreads; thread++) {
87232b8af82SJiri Olsa 		u64 ena = 0, run = 0, val = 0;
87332b8af82SJiri Olsa 
87432b8af82SJiri Olsa 		for (cpu = 0; cpu < ncpus; cpu++) {
87532b8af82SJiri Olsa 			val += perf_counts(counter->counts, cpu, thread)->val;
87632b8af82SJiri Olsa 			ena += perf_counts(counter->counts, cpu, thread)->ena;
87732b8af82SJiri Olsa 			run += perf_counts(counter->counts, cpu, thread)->run;
87832b8af82SJiri Olsa 		}
87932b8af82SJiri Olsa 
88032b8af82SJiri Olsa 		if (prefix)
88132b8af82SJiri Olsa 			fprintf(output, "%s", prefix);
88232b8af82SJiri Olsa 
88332b8af82SJiri Olsa 		uval = val * counter->scale;
884eedfcb4bSAndi Kleen 		printout(thread, 0, counter, uval);
88532b8af82SJiri Olsa 
88632b8af82SJiri Olsa 		if (!csv_output)
88732b8af82SJiri Olsa 			print_noise(counter, 1.0);
88832b8af82SJiri Olsa 
88932b8af82SJiri Olsa 		print_running(run, ena);
89032b8af82SJiri Olsa 		fputc('\n', output);
89132b8af82SJiri Olsa 	}
89232b8af82SJiri Olsa }
89332b8af82SJiri Olsa 
89442202dd5SIngo Molnar /*
89542202dd5SIngo Molnar  * Print out the results of a single counter:
896f5b4a9c3SStephane Eranian  * aggregated counts in system-wide mode
89742202dd5SIngo Molnar  */
89813370a9bSStephane Eranian static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
89942202dd5SIngo Molnar {
9005821522eSJiri Olsa 	FILE *output = stat_config.output;
901581cc8a2SJiri Olsa 	struct perf_stat_evsel *ps = counter->priv;
90269aad6f1SArnaldo Carvalho de Melo 	double avg = avg_stats(&ps->res_stats[0]);
903c52b12edSArnaldo Carvalho de Melo 	int scaled = counter->counts->scaled;
904410136f5SStephane Eranian 	double uval;
905d73515c0SAndi Kleen 	double avg_enabled, avg_running;
906d73515c0SAndi Kleen 
907d73515c0SAndi Kleen 	avg_enabled = avg_stats(&ps->res_stats[1]);
908d73515c0SAndi Kleen 	avg_running = avg_stats(&ps->res_stats[2]);
90942202dd5SIngo Molnar 
91013370a9bSStephane Eranian 	if (prefix)
91113370a9bSStephane Eranian 		fprintf(output, "%s", prefix);
91213370a9bSStephane Eranian 
9133b4331d9SSuzuki K. Poulose 	if (scaled == -1 || !counter->supported) {
914410136f5SStephane Eranian 		fprintf(output, "%*s%s",
915d7470b6aSStephane Eranian 			csv_output ? 0 : 18,
9162cee77c4SDavid Ahern 			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
917410136f5SStephane Eranian 			csv_sep);
918410136f5SStephane Eranian 		fprintf(output, "%-*s%s",
919410136f5SStephane Eranian 			csv_output ? 0 : unit_width,
920410136f5SStephane Eranian 			counter->unit, csv_sep);
921410136f5SStephane Eranian 		fprintf(output, "%*s",
922410136f5SStephane Eranian 			csv_output ? 0 : -25,
9237289f83cSArnaldo Carvalho de Melo 			perf_evsel__name(counter));
924023695d9SStephane Eranian 
925023695d9SStephane Eranian 		if (counter->cgrp)
9264aa9015fSStephane Eranian 			fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
927023695d9SStephane Eranian 
928d73515c0SAndi Kleen 		print_running(avg_running, avg_enabled);
9294aa9015fSStephane Eranian 		fputc('\n', output);
93042202dd5SIngo Molnar 		return;
93142202dd5SIngo Molnar 	}
93242202dd5SIngo Molnar 
933410136f5SStephane Eranian 	uval = avg * counter->scale;
934eedfcb4bSAndi Kleen 	printout(-1, 0, counter, uval);
935849abde9SPeter Zijlstra 
9363ae9a34dSZhengyu He 	print_noise(counter, avg);
9373ae9a34dSZhengyu He 
938d73515c0SAndi Kleen 	print_running(avg_running, avg_enabled);
9394aa9015fSStephane Eranian 	fprintf(output, "\n");
94042202dd5SIngo Molnar }
94142202dd5SIngo Molnar 
942f5b4a9c3SStephane Eranian /*
943f5b4a9c3SStephane Eranian  * Print out the results of a single counter:
944f5b4a9c3SStephane Eranian  * does not use aggregated count in system-wide
945f5b4a9c3SStephane Eranian  */
94613370a9bSStephane Eranian static void print_counter(struct perf_evsel *counter, char *prefix)
947f5b4a9c3SStephane Eranian {
9485821522eSJiri Olsa 	FILE *output = stat_config.output;
949f5b4a9c3SStephane Eranian 	u64 ena, run, val;
950410136f5SStephane Eranian 	double uval;
951f5b4a9c3SStephane Eranian 	int cpu;
952f5b4a9c3SStephane Eranian 
9537ae92e74SYan, Zheng 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
954a6fa0038SJiri Olsa 		val = perf_counts(counter->counts, cpu, 0)->val;
955a6fa0038SJiri Olsa 		ena = perf_counts(counter->counts, cpu, 0)->ena;
956a6fa0038SJiri Olsa 		run = perf_counts(counter->counts, cpu, 0)->run;
95713370a9bSStephane Eranian 
95813370a9bSStephane Eranian 		if (prefix)
95913370a9bSStephane Eranian 			fprintf(output, "%s", prefix);
96013370a9bSStephane Eranian 
961f5b4a9c3SStephane Eranian 		if (run == 0 || ena == 0) {
962410136f5SStephane Eranian 			fprintf(output, "CPU%*d%s%*s%s",
963d7470b6aSStephane Eranian 				csv_output ? 0 : -4,
9647ae92e74SYan, Zheng 				perf_evsel__cpus(counter)->map[cpu], csv_sep,
965d7470b6aSStephane Eranian 				csv_output ? 0 : 18,
9662cee77c4SDavid Ahern 				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
967410136f5SStephane Eranian 				csv_sep);
968410136f5SStephane Eranian 
969410136f5SStephane Eranian 				fprintf(output, "%-*s%s",
970410136f5SStephane Eranian 					csv_output ? 0 : unit_width,
971410136f5SStephane Eranian 					counter->unit, csv_sep);
972410136f5SStephane Eranian 
973410136f5SStephane Eranian 				fprintf(output, "%*s",
974410136f5SStephane Eranian 					csv_output ? 0 : -25,
9757289f83cSArnaldo Carvalho de Melo 					perf_evsel__name(counter));
976f5b4a9c3SStephane Eranian 
977023695d9SStephane Eranian 			if (counter->cgrp)
9784aa9015fSStephane Eranian 				fprintf(output, "%s%s",
9794aa9015fSStephane Eranian 					csv_sep, counter->cgrp->name);
980023695d9SStephane Eranian 
981d73515c0SAndi Kleen 			print_running(run, ena);
9824aa9015fSStephane Eranian 			fputc('\n', output);
983f5b4a9c3SStephane Eranian 			continue;
984f5b4a9c3SStephane Eranian 		}
985f5b4a9c3SStephane Eranian 
986410136f5SStephane Eranian 		uval = val * counter->scale;
987eedfcb4bSAndi Kleen 		printout(cpu, 0, counter, uval);
988d73515c0SAndi Kleen 		if (!csv_output)
989f5b4a9c3SStephane Eranian 			print_noise(counter, 1.0);
990d73515c0SAndi Kleen 		print_running(run, ena);
991f5b4a9c3SStephane Eranian 
9924aa9015fSStephane Eranian 		fputc('\n', output);
993f5b4a9c3SStephane Eranian 	}
994f5b4a9c3SStephane Eranian }
995f5b4a9c3SStephane Eranian 
996d4f63a47SJiri Olsa static void print_interval(char *prefix, struct timespec *ts)
99742202dd5SIngo Molnar {
9985821522eSJiri Olsa 	FILE *output = stat_config.output;
999d4f63a47SJiri Olsa 	static int num_print_interval;
1000d4f63a47SJiri Olsa 
1001d4f63a47SJiri Olsa 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1002d4f63a47SJiri Olsa 
1003d4f63a47SJiri Olsa 	if (num_print_interval == 0 && !csv_output) {
1004421a50f3SJiri Olsa 		switch (stat_config.aggr_mode) {
1005d4f63a47SJiri Olsa 		case AGGR_SOCKET:
1006d4f63a47SJiri Olsa 			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
1007d4f63a47SJiri Olsa 			break;
1008d4f63a47SJiri Olsa 		case AGGR_CORE:
1009d4f63a47SJiri Olsa 			fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
1010d4f63a47SJiri Olsa 			break;
1011d4f63a47SJiri Olsa 		case AGGR_NONE:
1012d4f63a47SJiri Olsa 			fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
1013d4f63a47SJiri Olsa 			break;
101432b8af82SJiri Olsa 		case AGGR_THREAD:
101532b8af82SJiri Olsa 			fprintf(output, "#           time             comm-pid                  counts %*s events\n", unit_width, "unit");
101632b8af82SJiri Olsa 			break;
1017d4f63a47SJiri Olsa 		case AGGR_GLOBAL:
1018d4f63a47SJiri Olsa 		default:
1019d4f63a47SJiri Olsa 			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
1020208df99eSJiri Olsa 		case AGGR_UNSET:
1021208df99eSJiri Olsa 			break;
1022d4f63a47SJiri Olsa 		}
1023d4f63a47SJiri Olsa 	}
1024d4f63a47SJiri Olsa 
1025d4f63a47SJiri Olsa 	if (++num_print_interval == 25)
1026d4f63a47SJiri Olsa 		num_print_interval = 0;
1027d4f63a47SJiri Olsa }
1028d4f63a47SJiri Olsa 
1029d4f63a47SJiri Olsa static void print_header(int argc, const char **argv)
1030d4f63a47SJiri Olsa {
10315821522eSJiri Olsa 	FILE *output = stat_config.output;
103269aad6f1SArnaldo Carvalho de Melo 	int i;
103342202dd5SIngo Molnar 
103486470930SIngo Molnar 	fflush(stdout);
103586470930SIngo Molnar 
1036d7470b6aSStephane Eranian 	if (!csv_output) {
10374aa9015fSStephane Eranian 		fprintf(output, "\n");
10384aa9015fSStephane Eranian 		fprintf(output, " Performance counter stats for ");
103962d3b617SDavid Ahern 		if (target.system_wide)
104062d3b617SDavid Ahern 			fprintf(output, "\'system wide");
104162d3b617SDavid Ahern 		else if (target.cpu_list)
104262d3b617SDavid Ahern 			fprintf(output, "\'CPU(s) %s", target.cpu_list);
1043602ad878SArnaldo Carvalho de Melo 		else if (!target__has_task(&target)) {
10444aa9015fSStephane Eranian 			fprintf(output, "\'%s", argv[0]);
104586470930SIngo Molnar 			for (i = 1; i < argc; i++)
10464aa9015fSStephane Eranian 				fprintf(output, " %s", argv[i]);
104720f946b4SNamhyung Kim 		} else if (target.pid)
104820f946b4SNamhyung Kim 			fprintf(output, "process id \'%s", target.pid);
1049d6d901c2SZhang, Yanmin 		else
105020f946b4SNamhyung Kim 			fprintf(output, "thread id \'%s", target.tid);
105186470930SIngo Molnar 
10524aa9015fSStephane Eranian 		fprintf(output, "\'");
105342202dd5SIngo Molnar 		if (run_count > 1)
10544aa9015fSStephane Eranian 			fprintf(output, " (%d runs)", run_count);
10554aa9015fSStephane Eranian 		fprintf(output, ":\n\n");
1056d7470b6aSStephane Eranian 	}
1057f5b4a9c3SStephane Eranian }
105886470930SIngo Molnar 
1059d4f63a47SJiri Olsa static void print_footer(void)
1060d4f63a47SJiri Olsa {
10615821522eSJiri Olsa 	FILE *output = stat_config.output;
10625821522eSJiri Olsa 
1063c3305257SIngo Molnar 	if (!null_run)
10644aa9015fSStephane Eranian 		fprintf(output, "\n");
10654aa9015fSStephane Eranian 	fprintf(output, " %17.9f seconds time elapsed",
1066506d4bc8SPeter Zijlstra 			avg_stats(&walltime_nsecs_stats)/1e9);
1067566747e6SIngo Molnar 	if (run_count > 1) {
10684aa9015fSStephane Eranian 		fprintf(output, "                                        ");
1069f99844cbSIngo Molnar 		print_noise_pct(stddev_stats(&walltime_nsecs_stats),
1070506d4bc8SPeter Zijlstra 				avg_stats(&walltime_nsecs_stats));
1071566747e6SIngo Molnar 	}
10724aa9015fSStephane Eranian 	fprintf(output, "\n\n");
107386470930SIngo Molnar }
1074d4f63a47SJiri Olsa 
1075d4f63a47SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv)
1076d4f63a47SJiri Olsa {
1077ec0d3d1fSJiri Olsa 	int interval = stat_config.interval;
1078d4f63a47SJiri Olsa 	struct perf_evsel *counter;
1079d4f63a47SJiri Olsa 	char buf[64], *prefix = NULL;
1080d4f63a47SJiri Olsa 
1081664c98d4SJiri Olsa 	/* Do not print anything if we record to the pipe. */
1082664c98d4SJiri Olsa 	if (STAT_RECORD && perf_stat.file.is_pipe)
1083664c98d4SJiri Olsa 		return;
1084664c98d4SJiri Olsa 
1085d4f63a47SJiri Olsa 	if (interval)
1086d4f63a47SJiri Olsa 		print_interval(prefix = buf, ts);
1087d4f63a47SJiri Olsa 	else
1088d4f63a47SJiri Olsa 		print_header(argc, argv);
1089d4f63a47SJiri Olsa 
1090421a50f3SJiri Olsa 	switch (stat_config.aggr_mode) {
1091d4f63a47SJiri Olsa 	case AGGR_CORE:
1092d4f63a47SJiri Olsa 	case AGGR_SOCKET:
1093d4f63a47SJiri Olsa 		print_aggr(prefix);
1094d4f63a47SJiri Olsa 		break;
109532b8af82SJiri Olsa 	case AGGR_THREAD:
109632b8af82SJiri Olsa 		evlist__for_each(evsel_list, counter)
109732b8af82SJiri Olsa 			print_aggr_thread(counter, prefix);
109832b8af82SJiri Olsa 		break;
1099d4f63a47SJiri Olsa 	case AGGR_GLOBAL:
1100d4f63a47SJiri Olsa 		evlist__for_each(evsel_list, counter)
1101d4f63a47SJiri Olsa 			print_counter_aggr(counter, prefix);
1102d4f63a47SJiri Olsa 		break;
1103d4f63a47SJiri Olsa 	case AGGR_NONE:
1104d4f63a47SJiri Olsa 		evlist__for_each(evsel_list, counter)
1105d4f63a47SJiri Olsa 			print_counter(counter, prefix);
1106d4f63a47SJiri Olsa 		break;
1107208df99eSJiri Olsa 	case AGGR_UNSET:
1108d4f63a47SJiri Olsa 	default:
1109d4f63a47SJiri Olsa 		break;
1110d4f63a47SJiri Olsa 	}
1111d4f63a47SJiri Olsa 
1112d4f63a47SJiri Olsa 	if (!interval && !csv_output)
1113d4f63a47SJiri Olsa 		print_footer();
1114d4f63a47SJiri Olsa 
11155821522eSJiri Olsa 	fflush(stat_config.output);
1116d7470b6aSStephane Eranian }
111786470930SIngo Molnar 
1118f7b7c26eSPeter Zijlstra static volatile int signr = -1;
1119f7b7c26eSPeter Zijlstra 
112086470930SIngo Molnar static void skip_signal(int signo)
112186470930SIngo Molnar {
1122ec0d3d1fSJiri Olsa 	if ((child_pid == -1) || stat_config.interval)
112360666c63SLiming Wang 		done = 1;
112460666c63SLiming Wang 
1125f7b7c26eSPeter Zijlstra 	signr = signo;
1126d07f0b12SStephane Eranian 	/*
1127d07f0b12SStephane Eranian 	 * render child_pid harmless
1128d07f0b12SStephane Eranian 	 * won't send SIGTERM to a random
1129d07f0b12SStephane Eranian 	 * process in case of race condition
1130d07f0b12SStephane Eranian 	 * and fast PID recycling
1131d07f0b12SStephane Eranian 	 */
1132d07f0b12SStephane Eranian 	child_pid = -1;
1133f7b7c26eSPeter Zijlstra }
1134f7b7c26eSPeter Zijlstra 
1135f7b7c26eSPeter Zijlstra static void sig_atexit(void)
1136f7b7c26eSPeter Zijlstra {
1137d07f0b12SStephane Eranian 	sigset_t set, oset;
1138d07f0b12SStephane Eranian 
1139d07f0b12SStephane Eranian 	/*
1140d07f0b12SStephane Eranian 	 * avoid race condition with SIGCHLD handler
1141d07f0b12SStephane Eranian 	 * in skip_signal() which is modifying child_pid
1142d07f0b12SStephane Eranian 	 * goal is to avoid send SIGTERM to a random
1143d07f0b12SStephane Eranian 	 * process
1144d07f0b12SStephane Eranian 	 */
1145d07f0b12SStephane Eranian 	sigemptyset(&set);
1146d07f0b12SStephane Eranian 	sigaddset(&set, SIGCHLD);
1147d07f0b12SStephane Eranian 	sigprocmask(SIG_BLOCK, &set, &oset);
1148d07f0b12SStephane Eranian 
1149933da83aSChris Wilson 	if (child_pid != -1)
1150933da83aSChris Wilson 		kill(child_pid, SIGTERM);
1151933da83aSChris Wilson 
1152d07f0b12SStephane Eranian 	sigprocmask(SIG_SETMASK, &oset, NULL);
1153d07f0b12SStephane Eranian 
1154f7b7c26eSPeter Zijlstra 	if (signr == -1)
1155f7b7c26eSPeter Zijlstra 		return;
1156f7b7c26eSPeter Zijlstra 
1157f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
1158f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
115986470930SIngo Molnar }
116086470930SIngo Molnar 
11611d037ca1SIrina Tirdea static int stat__set_big_num(const struct option *opt __maybe_unused,
11621d037ca1SIrina Tirdea 			     const char *s __maybe_unused, int unset)
1163d7470b6aSStephane Eranian {
1164d7470b6aSStephane Eranian 	big_num_opt = unset ? 0 : 1;
1165d7470b6aSStephane Eranian 	return 0;
1166d7470b6aSStephane Eranian }
1167d7470b6aSStephane Eranian 
1168e0547311SJiri Olsa static const struct option stat_options[] = {
1169e0547311SJiri Olsa 	OPT_BOOLEAN('T', "transaction", &transaction_run,
1170e0547311SJiri Olsa 		    "hardware transaction statistics"),
1171e0547311SJiri Olsa 	OPT_CALLBACK('e', "event", &evsel_list, "event",
1172e0547311SJiri Olsa 		     "event selector. use 'perf list' to list available events",
1173e0547311SJiri Olsa 		     parse_events_option),
1174e0547311SJiri Olsa 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1175e0547311SJiri Olsa 		     "event filter", parse_filter),
1176e0547311SJiri Olsa 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1177e0547311SJiri Olsa 		    "child tasks do not inherit counters"),
1178e0547311SJiri Olsa 	OPT_STRING('p', "pid", &target.pid, "pid",
1179e0547311SJiri Olsa 		   "stat events on existing process id"),
1180e0547311SJiri Olsa 	OPT_STRING('t', "tid", &target.tid, "tid",
1181e0547311SJiri Olsa 		   "stat events on existing thread id"),
1182e0547311SJiri Olsa 	OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1183e0547311SJiri Olsa 		    "system-wide collection from all CPUs"),
1184e0547311SJiri Olsa 	OPT_BOOLEAN('g', "group", &group,
1185e0547311SJiri Olsa 		    "put the counters into a counter group"),
1186e0547311SJiri Olsa 	OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
1187e0547311SJiri Olsa 	OPT_INCR('v', "verbose", &verbose,
1188e0547311SJiri Olsa 		    "be more verbose (show counter open errors, etc)"),
1189e0547311SJiri Olsa 	OPT_INTEGER('r', "repeat", &run_count,
1190e0547311SJiri Olsa 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
1191e0547311SJiri Olsa 	OPT_BOOLEAN('n', "null", &null_run,
1192e0547311SJiri Olsa 		    "null run - dont start any counters"),
1193e0547311SJiri Olsa 	OPT_INCR('d', "detailed", &detailed_run,
1194e0547311SJiri Olsa 		    "detailed run - start a lot of events"),
1195e0547311SJiri Olsa 	OPT_BOOLEAN('S', "sync", &sync_run,
1196e0547311SJiri Olsa 		    "call sync() before starting a run"),
1197e0547311SJiri Olsa 	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1198e0547311SJiri Olsa 			   "print large numbers with thousands\' separators",
1199e0547311SJiri Olsa 			   stat__set_big_num),
1200e0547311SJiri Olsa 	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1201e0547311SJiri Olsa 		    "list of cpus to monitor in system-wide"),
1202e0547311SJiri Olsa 	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
1203e0547311SJiri Olsa 		    "disable CPU count aggregation", AGGR_NONE),
1204e0547311SJiri Olsa 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
1205e0547311SJiri Olsa 		   "print counts with custom separator"),
1206e0547311SJiri Olsa 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1207e0547311SJiri Olsa 		     "monitor event in cgroup name only", parse_cgroups),
1208e0547311SJiri Olsa 	OPT_STRING('o', "output", &output_name, "file", "output file name"),
1209e0547311SJiri Olsa 	OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1210e0547311SJiri Olsa 	OPT_INTEGER(0, "log-fd", &output_fd,
1211e0547311SJiri Olsa 		    "log output to fd, instead of stderr"),
1212e0547311SJiri Olsa 	OPT_STRING(0, "pre", &pre_cmd, "command",
1213e0547311SJiri Olsa 			"command to run prior to the measured command"),
1214e0547311SJiri Olsa 	OPT_STRING(0, "post", &post_cmd, "command",
1215e0547311SJiri Olsa 			"command to run after to the measured command"),
1216e0547311SJiri Olsa 	OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1217e0547311SJiri Olsa 		    "print counts at regular interval in ms (>= 10)"),
1218e0547311SJiri Olsa 	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1219e0547311SJiri Olsa 		     "aggregate counts per processor socket", AGGR_SOCKET),
1220e0547311SJiri Olsa 	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
1221e0547311SJiri Olsa 		     "aggregate counts per physical processor core", AGGR_CORE),
1222e0547311SJiri Olsa 	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
1223e0547311SJiri Olsa 		     "aggregate counts per thread", AGGR_THREAD),
1224e0547311SJiri Olsa 	OPT_UINTEGER('D', "delay", &initial_delay,
1225e0547311SJiri Olsa 		     "ms to wait before starting measurement after program start"),
1226e0547311SJiri Olsa 	OPT_END()
1227e0547311SJiri Olsa };
1228e0547311SJiri Olsa 
12291fe7a300SJiri Olsa static int perf_stat__get_socket(struct cpu_map *map, int cpu)
12301fe7a300SJiri Olsa {
12311fe7a300SJiri Olsa 	return cpu_map__get_socket(map, cpu, NULL);
12321fe7a300SJiri Olsa }
12331fe7a300SJiri Olsa 
12341fe7a300SJiri Olsa static int perf_stat__get_core(struct cpu_map *map, int cpu)
12351fe7a300SJiri Olsa {
12361fe7a300SJiri Olsa 	return cpu_map__get_core(map, cpu, NULL);
12371fe7a300SJiri Olsa }
12381fe7a300SJiri Olsa 
12391e5a2931SJiri Olsa static int cpu_map__get_max(struct cpu_map *map)
12401e5a2931SJiri Olsa {
12411e5a2931SJiri Olsa 	int i, max = -1;
12421e5a2931SJiri Olsa 
12431e5a2931SJiri Olsa 	for (i = 0; i < map->nr; i++) {
12441e5a2931SJiri Olsa 		if (map->map[i] > max)
12451e5a2931SJiri Olsa 			max = map->map[i];
12461e5a2931SJiri Olsa 	}
12471e5a2931SJiri Olsa 
12481e5a2931SJiri Olsa 	return max;
12491e5a2931SJiri Olsa }
12501e5a2931SJiri Olsa 
12511e5a2931SJiri Olsa static struct cpu_map *cpus_aggr_map;
12521e5a2931SJiri Olsa 
12531e5a2931SJiri Olsa static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
12541e5a2931SJiri Olsa {
12551e5a2931SJiri Olsa 	int cpu;
12561e5a2931SJiri Olsa 
12571e5a2931SJiri Olsa 	if (idx >= map->nr)
12581e5a2931SJiri Olsa 		return -1;
12591e5a2931SJiri Olsa 
12601e5a2931SJiri Olsa 	cpu = map->map[idx];
12611e5a2931SJiri Olsa 
12621e5a2931SJiri Olsa 	if (cpus_aggr_map->map[cpu] == -1)
12631e5a2931SJiri Olsa 		cpus_aggr_map->map[cpu] = get_id(map, idx);
12641e5a2931SJiri Olsa 
12651e5a2931SJiri Olsa 	return cpus_aggr_map->map[cpu];
12661e5a2931SJiri Olsa }
12671e5a2931SJiri Olsa 
12681e5a2931SJiri Olsa static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
12691e5a2931SJiri Olsa {
12701e5a2931SJiri Olsa 	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
12711e5a2931SJiri Olsa }
12721e5a2931SJiri Olsa 
12731e5a2931SJiri Olsa static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
12741e5a2931SJiri Olsa {
12751e5a2931SJiri Olsa 	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
12761e5a2931SJiri Olsa }
12771e5a2931SJiri Olsa 
127886ee6e18SStephane Eranian static int perf_stat_init_aggr_mode(void)
127986ee6e18SStephane Eranian {
12801e5a2931SJiri Olsa 	int nr;
12811e5a2931SJiri Olsa 
1282421a50f3SJiri Olsa 	switch (stat_config.aggr_mode) {
128386ee6e18SStephane Eranian 	case AGGR_SOCKET:
128486ee6e18SStephane Eranian 		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
128586ee6e18SStephane Eranian 			perror("cannot build socket map");
128686ee6e18SStephane Eranian 			return -1;
128786ee6e18SStephane Eranian 		}
12881e5a2931SJiri Olsa 		aggr_get_id = perf_stat__get_socket_cached;
128986ee6e18SStephane Eranian 		break;
129012c08a9fSStephane Eranian 	case AGGR_CORE:
129112c08a9fSStephane Eranian 		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
129212c08a9fSStephane Eranian 			perror("cannot build core map");
129312c08a9fSStephane Eranian 			return -1;
129412c08a9fSStephane Eranian 		}
12951e5a2931SJiri Olsa 		aggr_get_id = perf_stat__get_core_cached;
129612c08a9fSStephane Eranian 		break;
129786ee6e18SStephane Eranian 	case AGGR_NONE:
129886ee6e18SStephane Eranian 	case AGGR_GLOBAL:
129932b8af82SJiri Olsa 	case AGGR_THREAD:
1300208df99eSJiri Olsa 	case AGGR_UNSET:
130186ee6e18SStephane Eranian 	default:
130286ee6e18SStephane Eranian 		break;
130386ee6e18SStephane Eranian 	}
13041e5a2931SJiri Olsa 
13051e5a2931SJiri Olsa 	/*
13061e5a2931SJiri Olsa 	 * The evsel_list->cpus is the base we operate on,
13071e5a2931SJiri Olsa 	 * taking the highest cpu number to be the size of
13081e5a2931SJiri Olsa 	 * the aggregation translate cpumap.
13091e5a2931SJiri Olsa 	 */
13101e5a2931SJiri Olsa 	nr = cpu_map__get_max(evsel_list->cpus);
13111e5a2931SJiri Olsa 	cpus_aggr_map = cpu_map__empty_new(nr + 1);
13121e5a2931SJiri Olsa 	return cpus_aggr_map ? 0 : -ENOMEM;
131386ee6e18SStephane Eranian }
131486ee6e18SStephane Eranian 
1315544c2ae7SMasami Hiramatsu static void perf_stat__exit_aggr_mode(void)
1316544c2ae7SMasami Hiramatsu {
1317544c2ae7SMasami Hiramatsu 	cpu_map__put(aggr_map);
1318544c2ae7SMasami Hiramatsu 	cpu_map__put(cpus_aggr_map);
1319544c2ae7SMasami Hiramatsu 	aggr_map = NULL;
1320544c2ae7SMasami Hiramatsu 	cpus_aggr_map = NULL;
1321544c2ae7SMasami Hiramatsu }
1322544c2ae7SMasami Hiramatsu 
13232cba3ffbSIngo Molnar /*
13242cba3ffbSIngo Molnar  * Add default attributes, if there were no attributes specified or
13252cba3ffbSIngo Molnar  * if -d/--detailed, -d -d or -d -d -d is used:
13262cba3ffbSIngo Molnar  */
13272cba3ffbSIngo Molnar static int add_default_attributes(void)
13282cba3ffbSIngo Molnar {
1329b070a547SArnaldo Carvalho de Melo 	struct perf_event_attr default_attrs[] = {
1330b070a547SArnaldo Carvalho de Melo 
1331b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
1332b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
1333b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
1334b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},
1335b070a547SArnaldo Carvalho de Melo 
1336b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
1337b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},
1338b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},
1339b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
1340b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
1341b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
1342b070a547SArnaldo Carvalho de Melo 
1343b070a547SArnaldo Carvalho de Melo };
1344b070a547SArnaldo Carvalho de Melo 
1345b070a547SArnaldo Carvalho de Melo /*
1346b070a547SArnaldo Carvalho de Melo  * Detailed stats (-d), covering the L1 and last level data caches:
1347b070a547SArnaldo Carvalho de Melo  */
1348b070a547SArnaldo Carvalho de Melo 	struct perf_event_attr detailed_attrs[] = {
1349b070a547SArnaldo Carvalho de Melo 
1350b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1351b070a547SArnaldo Carvalho de Melo     .config =
1352b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
1353b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1354b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1355b070a547SArnaldo Carvalho de Melo 
1356b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1357b070a547SArnaldo Carvalho de Melo     .config =
1358b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
1359b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1360b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1361b070a547SArnaldo Carvalho de Melo 
1362b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1363b070a547SArnaldo Carvalho de Melo     .config =
1364b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_LL			<<  0  |
1365b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1366b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1367b070a547SArnaldo Carvalho de Melo 
1368b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1369b070a547SArnaldo Carvalho de Melo     .config =
1370b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_LL			<<  0  |
1371b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1372b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1373b070a547SArnaldo Carvalho de Melo };
1374b070a547SArnaldo Carvalho de Melo 
1375b070a547SArnaldo Carvalho de Melo /*
1376b070a547SArnaldo Carvalho de Melo  * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
1377b070a547SArnaldo Carvalho de Melo  */
1378b070a547SArnaldo Carvalho de Melo 	struct perf_event_attr very_detailed_attrs[] = {
1379b070a547SArnaldo Carvalho de Melo 
1380b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1381b070a547SArnaldo Carvalho de Melo     .config =
1382b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
1383b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1384b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1385b070a547SArnaldo Carvalho de Melo 
1386b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1387b070a547SArnaldo Carvalho de Melo     .config =
1388b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
1389b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1390b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1391b070a547SArnaldo Carvalho de Melo 
1392b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1393b070a547SArnaldo Carvalho de Melo     .config =
1394b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
1395b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1396b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1397b070a547SArnaldo Carvalho de Melo 
1398b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1399b070a547SArnaldo Carvalho de Melo     .config =
1400b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
1401b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1402b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1403b070a547SArnaldo Carvalho de Melo 
1404b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1405b070a547SArnaldo Carvalho de Melo     .config =
1406b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
1407b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1408b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1409b070a547SArnaldo Carvalho de Melo 
1410b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1411b070a547SArnaldo Carvalho de Melo     .config =
1412b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
1413b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
1414b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1415b070a547SArnaldo Carvalho de Melo 
1416b070a547SArnaldo Carvalho de Melo };
1417b070a547SArnaldo Carvalho de Melo 
1418b070a547SArnaldo Carvalho de Melo /*
1419b070a547SArnaldo Carvalho de Melo  * Very, very detailed stats (-d -d -d), adding prefetch events:
1420b070a547SArnaldo Carvalho de Melo  */
1421b070a547SArnaldo Carvalho de Melo 	struct perf_event_attr very_very_detailed_attrs[] = {
1422b070a547SArnaldo Carvalho de Melo 
1423b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1424b070a547SArnaldo Carvalho de Melo     .config =
1425b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
1426b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
1427b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
1428b070a547SArnaldo Carvalho de Melo 
1429b070a547SArnaldo Carvalho de Melo   { .type = PERF_TYPE_HW_CACHE,
1430b070a547SArnaldo Carvalho de Melo     .config =
1431b070a547SArnaldo Carvalho de Melo 	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
1432b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
1433b070a547SArnaldo Carvalho de Melo 	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
1434b070a547SArnaldo Carvalho de Melo };
1435b070a547SArnaldo Carvalho de Melo 
14362cba3ffbSIngo Molnar 	/* Set attrs if no event is selected and !null_run: */
14372cba3ffbSIngo Molnar 	if (null_run)
14382cba3ffbSIngo Molnar 		return 0;
14392cba3ffbSIngo Molnar 
14404cabc3d1SAndi Kleen 	if (transaction_run) {
14414cabc3d1SAndi Kleen 		int err;
14424cabc3d1SAndi Kleen 		if (pmu_have_event("cpu", "cycles-ct") &&
14434cabc3d1SAndi Kleen 		    pmu_have_event("cpu", "el-start"))
1444a454742cSJiri Olsa 			err = parse_events(evsel_list, transaction_attrs, NULL);
14454cabc3d1SAndi Kleen 		else
1446a454742cSJiri Olsa 			err = parse_events(evsel_list, transaction_limited_attrs, NULL);
1447a454742cSJiri Olsa 		if (err) {
14484cabc3d1SAndi Kleen 			fprintf(stderr, "Cannot set up transaction events\n");
14494cabc3d1SAndi Kleen 			return -1;
14504cabc3d1SAndi Kleen 		}
14514cabc3d1SAndi Kleen 		return 0;
14524cabc3d1SAndi Kleen 	}
14534cabc3d1SAndi Kleen 
14542cba3ffbSIngo Molnar 	if (!evsel_list->nr_entries) {
145579695e1bSArnaldo Carvalho de Melo 		if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
14562cba3ffbSIngo Molnar 			return -1;
14572cba3ffbSIngo Molnar 	}
14582cba3ffbSIngo Molnar 
14592cba3ffbSIngo Molnar 	/* Detailed events get appended to the event list: */
14602cba3ffbSIngo Molnar 
14612cba3ffbSIngo Molnar 	if (detailed_run <  1)
14622cba3ffbSIngo Molnar 		return 0;
14632cba3ffbSIngo Molnar 
14642cba3ffbSIngo Molnar 	/* Append detailed run extra attributes: */
146579695e1bSArnaldo Carvalho de Melo 	if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
14662cba3ffbSIngo Molnar 		return -1;
14672cba3ffbSIngo Molnar 
14682cba3ffbSIngo Molnar 	if (detailed_run < 2)
14692cba3ffbSIngo Molnar 		return 0;
14702cba3ffbSIngo Molnar 
14712cba3ffbSIngo Molnar 	/* Append very detailed run extra attributes: */
147279695e1bSArnaldo Carvalho de Melo 	if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
14732cba3ffbSIngo Molnar 		return -1;
14742cba3ffbSIngo Molnar 
14752cba3ffbSIngo Molnar 	if (detailed_run < 3)
14762cba3ffbSIngo Molnar 		return 0;
14772cba3ffbSIngo Molnar 
14782cba3ffbSIngo Molnar 	/* Append very, very detailed run extra attributes: */
147979695e1bSArnaldo Carvalho de Melo 	return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
14802cba3ffbSIngo Molnar }
14812cba3ffbSIngo Molnar 
14824979d0c7SJiri Olsa static const char * const recort_usage[] = {
14834979d0c7SJiri Olsa 	"perf stat record [<options>]",
14844979d0c7SJiri Olsa 	NULL,
14854979d0c7SJiri Olsa };
14864979d0c7SJiri Olsa 
14873ba78bd0SJiri Olsa static void init_features(struct perf_session *session)
14883ba78bd0SJiri Olsa {
14893ba78bd0SJiri Olsa 	int feat;
14903ba78bd0SJiri Olsa 
14913ba78bd0SJiri Olsa 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
14923ba78bd0SJiri Olsa 		perf_header__set_feat(&session->header, feat);
14933ba78bd0SJiri Olsa 
14943ba78bd0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
14953ba78bd0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
14963ba78bd0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
14973ba78bd0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
14983ba78bd0SJiri Olsa }
14993ba78bd0SJiri Olsa 
15004979d0c7SJiri Olsa static int __cmd_record(int argc, const char **argv)
15014979d0c7SJiri Olsa {
15024979d0c7SJiri Olsa 	struct perf_session *session;
15034979d0c7SJiri Olsa 	struct perf_data_file *file = &perf_stat.file;
15044979d0c7SJiri Olsa 
15054979d0c7SJiri Olsa 	argc = parse_options(argc, argv, stat_options, record_usage,
15064979d0c7SJiri Olsa 			     PARSE_OPT_STOP_AT_NON_OPTION);
15074979d0c7SJiri Olsa 
15084979d0c7SJiri Olsa 	if (output_name)
15094979d0c7SJiri Olsa 		file->path = output_name;
15104979d0c7SJiri Olsa 
1511e9d6db8eSJiri Olsa 	if (run_count != 1 || forever) {
1512e9d6db8eSJiri Olsa 		pr_err("Cannot use -r option with perf stat record.\n");
1513e9d6db8eSJiri Olsa 		return -1;
1514e9d6db8eSJiri Olsa 	}
1515e9d6db8eSJiri Olsa 
15164979d0c7SJiri Olsa 	session = perf_session__new(file, false, NULL);
15174979d0c7SJiri Olsa 	if (session == NULL) {
15184979d0c7SJiri Olsa 		pr_err("Perf session creation failed.\n");
15194979d0c7SJiri Olsa 		return -1;
15204979d0c7SJiri Olsa 	}
15214979d0c7SJiri Olsa 
15223ba78bd0SJiri Olsa 	init_features(session);
15233ba78bd0SJiri Olsa 
15244979d0c7SJiri Olsa 	session->evlist   = evsel_list;
15254979d0c7SJiri Olsa 	perf_stat.session = session;
15264979d0c7SJiri Olsa 	perf_stat.record  = true;
15274979d0c7SJiri Olsa 	return argc;
15284979d0c7SJiri Olsa }
15294979d0c7SJiri Olsa 
15301d037ca1SIrina Tirdea int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
153186470930SIngo Molnar {
1532b070a547SArnaldo Carvalho de Melo 	const char * const stat_usage[] = {
1533b070a547SArnaldo Carvalho de Melo 		"perf stat [<options>] [<command>]",
1534b070a547SArnaldo Carvalho de Melo 		NULL
1535b070a547SArnaldo Carvalho de Melo 	};
1536cc03c542SNamhyung Kim 	int status = -EINVAL, run_idx;
15374aa9015fSStephane Eranian 	const char *mode;
15385821522eSJiri Olsa 	FILE *output = stderr;
1539ec0d3d1fSJiri Olsa 	unsigned int interval;
15404979d0c7SJiri Olsa 	const char * const stat_subcommands[] = { "record" };
154142202dd5SIngo Molnar 
15425af52b51SStephane Eranian 	setlocale(LC_ALL, "");
15435af52b51SStephane Eranian 
1544334fe7a3SNamhyung Kim 	evsel_list = perf_evlist__new();
1545361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
1546361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1547361c99a6SArnaldo Carvalho de Melo 
15484979d0c7SJiri Olsa 	argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
15494979d0c7SJiri Olsa 					(const char **) stat_usage,
1550a0541234SAnton Blanchard 					PARSE_OPT_STOP_AT_NON_OPTION);
1551d7470b6aSStephane Eranian 
15524979d0c7SJiri Olsa 	if (argc && !strncmp(argv[0], "rec", 3)) {
15534979d0c7SJiri Olsa 		argc = __cmd_record(argc, argv);
15544979d0c7SJiri Olsa 		if (argc < 0)
15554979d0c7SJiri Olsa 			return -1;
15564979d0c7SJiri Olsa 	}
15574979d0c7SJiri Olsa 
1558ec0d3d1fSJiri Olsa 	interval = stat_config.interval;
1559ec0d3d1fSJiri Olsa 
15604979d0c7SJiri Olsa 	/*
15614979d0c7SJiri Olsa 	 * For record command the -o is already taken care of.
15624979d0c7SJiri Olsa 	 */
15634979d0c7SJiri Olsa 	if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
15644aa9015fSStephane Eranian 		output = NULL;
15654aa9015fSStephane Eranian 
156656f3bae7SJim Cromie 	if (output_name && output_fd) {
156756f3bae7SJim Cromie 		fprintf(stderr, "cannot use both --output and --log-fd\n");
1568e0547311SJiri Olsa 		parse_options_usage(stat_usage, stat_options, "o", 1);
1569e0547311SJiri Olsa 		parse_options_usage(NULL, stat_options, "log-fd", 0);
1570cc03c542SNamhyung Kim 		goto out;
157156f3bae7SJim Cromie 	}
1572fc3e4d07SStephane Eranian 
1573fc3e4d07SStephane Eranian 	if (output_fd < 0) {
1574fc3e4d07SStephane Eranian 		fprintf(stderr, "argument to --log-fd must be a > 0\n");
1575e0547311SJiri Olsa 		parse_options_usage(stat_usage, stat_options, "log-fd", 0);
1576cc03c542SNamhyung Kim 		goto out;
1577fc3e4d07SStephane Eranian 	}
1578fc3e4d07SStephane Eranian 
15794aa9015fSStephane Eranian 	if (!output) {
15804aa9015fSStephane Eranian 		struct timespec tm;
15814aa9015fSStephane Eranian 		mode = append_file ? "a" : "w";
15824aa9015fSStephane Eranian 
15834aa9015fSStephane Eranian 		output = fopen(output_name, mode);
15844aa9015fSStephane Eranian 		if (!output) {
15854aa9015fSStephane Eranian 			perror("failed to create output file");
1586fceda7feSDavid Ahern 			return -1;
15874aa9015fSStephane Eranian 		}
15884aa9015fSStephane Eranian 		clock_gettime(CLOCK_REALTIME, &tm);
15894aa9015fSStephane Eranian 		fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1590fc3e4d07SStephane Eranian 	} else if (output_fd > 0) {
159156f3bae7SJim Cromie 		mode = append_file ? "a" : "w";
159256f3bae7SJim Cromie 		output = fdopen(output_fd, mode);
159356f3bae7SJim Cromie 		if (!output) {
159456f3bae7SJim Cromie 			perror("Failed opening logfd");
159556f3bae7SJim Cromie 			return -errno;
159656f3bae7SJim Cromie 		}
15974aa9015fSStephane Eranian 	}
15984aa9015fSStephane Eranian 
15995821522eSJiri Olsa 	stat_config.output = output;
16005821522eSJiri Olsa 
1601d4ffd04dSJim Cromie 	if (csv_sep) {
1602d7470b6aSStephane Eranian 		csv_output = true;
1603d4ffd04dSJim Cromie 		if (!strcmp(csv_sep, "\\t"))
1604d4ffd04dSJim Cromie 			csv_sep = "\t";
1605d4ffd04dSJim Cromie 	} else
1606d7470b6aSStephane Eranian 		csv_sep = DEFAULT_SEPARATOR;
1607d7470b6aSStephane Eranian 
1608d7470b6aSStephane Eranian 	/*
1609d7470b6aSStephane Eranian 	 * let the spreadsheet do the pretty-printing
1610d7470b6aSStephane Eranian 	 */
1611d7470b6aSStephane Eranian 	if (csv_output) {
161261a9f324SJim Cromie 		/* User explicitly passed -B? */
1613d7470b6aSStephane Eranian 		if (big_num_opt == 1) {
1614d7470b6aSStephane Eranian 			fprintf(stderr, "-B option not supported with -x\n");
1615e0547311SJiri Olsa 			parse_options_usage(stat_usage, stat_options, "B", 1);
1616e0547311SJiri Olsa 			parse_options_usage(NULL, stat_options, "x", 1);
1617cc03c542SNamhyung Kim 			goto out;
1618d7470b6aSStephane Eranian 		} else /* Nope, so disable big number formatting */
1619d7470b6aSStephane Eranian 			big_num = false;
1620d7470b6aSStephane Eranian 	} else if (big_num_opt == 0) /* User passed --no-big-num */
1621d7470b6aSStephane Eranian 		big_num = false;
1622d7470b6aSStephane Eranian 
1623602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&target))
1624e0547311SJiri Olsa 		usage_with_options(stat_usage, stat_options);
1625ac3063bdSDavid Ahern 
1626a7e191c3SFrederik Deweerdt 	if (run_count < 0) {
1627cc03c542SNamhyung Kim 		pr_err("Run count must be a positive number\n");
1628e0547311SJiri Olsa 		parse_options_usage(stat_usage, stat_options, "r", 1);
1629cc03c542SNamhyung Kim 		goto out;
1630a7e191c3SFrederik Deweerdt 	} else if (run_count == 0) {
1631a7e191c3SFrederik Deweerdt 		forever = true;
1632a7e191c3SFrederik Deweerdt 		run_count = 1;
1633a7e191c3SFrederik Deweerdt 	}
163486470930SIngo Molnar 
1635421a50f3SJiri Olsa 	if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
163632b8af82SJiri Olsa 		fprintf(stderr, "The --per-thread option is only available "
163732b8af82SJiri Olsa 			"when monitoring via -p -t options.\n");
1638e0547311SJiri Olsa 		parse_options_usage(NULL, stat_options, "p", 1);
1639e0547311SJiri Olsa 		parse_options_usage(NULL, stat_options, "t", 1);
164032b8af82SJiri Olsa 		goto out;
164132b8af82SJiri Olsa 	}
164232b8af82SJiri Olsa 
164332b8af82SJiri Olsa 	/*
164432b8af82SJiri Olsa 	 * no_aggr, cgroup are for system-wide only
164532b8af82SJiri Olsa 	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
164632b8af82SJiri Olsa 	 */
1647421a50f3SJiri Olsa 	if (((stat_config.aggr_mode != AGGR_GLOBAL &&
1648421a50f3SJiri Olsa 	      stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
1649602ad878SArnaldo Carvalho de Melo 	    !target__has_cpu(&target)) {
1650023695d9SStephane Eranian 		fprintf(stderr, "both cgroup and no-aggregation "
1651023695d9SStephane Eranian 			"modes only available in system-wide mode\n");
1652023695d9SStephane Eranian 
1653e0547311SJiri Olsa 		parse_options_usage(stat_usage, stat_options, "G", 1);
1654e0547311SJiri Olsa 		parse_options_usage(NULL, stat_options, "A", 1);
1655e0547311SJiri Olsa 		parse_options_usage(NULL, stat_options, "a", 1);
1656cc03c542SNamhyung Kim 		goto out;
1657d7e7a451SStephane Eranian 	}
1658d7e7a451SStephane Eranian 
16592cba3ffbSIngo Molnar 	if (add_default_attributes())
1660c6264defSIngo Molnar 		goto out;
166186470930SIngo Molnar 
1662602ad878SArnaldo Carvalho de Melo 	target__validate(&target);
16635c98d466SArnaldo Carvalho de Melo 
166477a6f014SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1665602ad878SArnaldo Carvalho de Melo 		if (target__has_task(&target)) {
16665c98d466SArnaldo Carvalho de Melo 			pr_err("Problems finding threads of monitor\n");
1667e0547311SJiri Olsa 			parse_options_usage(stat_usage, stat_options, "p", 1);
1668e0547311SJiri Olsa 			parse_options_usage(NULL, stat_options, "t", 1);
1669602ad878SArnaldo Carvalho de Melo 		} else if (target__has_cpu(&target)) {
167060d567e2SArnaldo Carvalho de Melo 			perror("failed to parse CPUs map");
1671e0547311SJiri Olsa 			parse_options_usage(stat_usage, stat_options, "C", 1);
1672e0547311SJiri Olsa 			parse_options_usage(NULL, stat_options, "a", 1);
1673cc03c542SNamhyung Kim 		}
1674cc03c542SNamhyung Kim 		goto out;
167560d567e2SArnaldo Carvalho de Melo 	}
167632b8af82SJiri Olsa 
167732b8af82SJiri Olsa 	/*
167832b8af82SJiri Olsa 	 * Initialize thread_map with comm names,
167932b8af82SJiri Olsa 	 * so we could print it out on output.
168032b8af82SJiri Olsa 	 */
1681421a50f3SJiri Olsa 	if (stat_config.aggr_mode == AGGR_THREAD)
168232b8af82SJiri Olsa 		thread_map__read_comms(evsel_list->threads);
168332b8af82SJiri Olsa 
168413370a9bSStephane Eranian 	if (interval && interval < 100) {
168519afd104SKan Liang 		if (interval < 10) {
168619afd104SKan Liang 			pr_err("print interval must be >= 10ms\n");
1687e0547311SJiri Olsa 			parse_options_usage(stat_usage, stat_options, "I", 1);
168803ad9747SArnaldo Carvalho de Melo 			goto out;
168919afd104SKan Liang 		} else
169019afd104SKan Liang 			pr_warning("print interval < 100ms. "
169119afd104SKan Liang 				   "The overhead percentage could be high in some cases. "
169219afd104SKan Liang 				   "Please proceed with caution.\n");
169313370a9bSStephane Eranian 	}
1694c45c6ea2SStephane Eranian 
1695d134ffb9SArnaldo Carvalho de Melo 	if (perf_evlist__alloc_stats(evsel_list, interval))
169603ad9747SArnaldo Carvalho de Melo 		goto out;
1697d6d901c2SZhang, Yanmin 
169886ee6e18SStephane Eranian 	if (perf_stat_init_aggr_mode())
169903ad9747SArnaldo Carvalho de Melo 		goto out;
170086ee6e18SStephane Eranian 
170186470930SIngo Molnar 	/*
170286470930SIngo Molnar 	 * We dont want to block the signals - that would cause
170386470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
170486470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
170586470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
170686470930SIngo Molnar 	 */
1707f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
1708a7e191c3SFrederik Deweerdt 	if (!forever)
170986470930SIngo Molnar 		signal(SIGINT,  skip_signal);
171013370a9bSStephane Eranian 	signal(SIGCHLD, skip_signal);
171186470930SIngo Molnar 	signal(SIGALRM, skip_signal);
171286470930SIngo Molnar 	signal(SIGABRT, skip_signal);
171386470930SIngo Molnar 
171442202dd5SIngo Molnar 	status = 0;
1715a7e191c3SFrederik Deweerdt 	for (run_idx = 0; forever || run_idx < run_count; run_idx++) {
171642202dd5SIngo Molnar 		if (run_count != 1 && verbose)
17174aa9015fSStephane Eranian 			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
17184aa9015fSStephane Eranian 				run_idx + 1);
1719f9cef0a9SIngo Molnar 
172042202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
1721a7e191c3SFrederik Deweerdt 		if (forever && status != -1) {
1722d4f63a47SJiri Olsa 			print_counters(NULL, argc, argv);
1723254ecbc7SJiri Olsa 			perf_stat__reset_stats();
1724a7e191c3SFrederik Deweerdt 		}
172542202dd5SIngo Molnar 	}
172642202dd5SIngo Molnar 
1727a7e191c3SFrederik Deweerdt 	if (!forever && status != -1 && !interval)
1728d4f63a47SJiri Olsa 		print_counters(NULL, argc, argv);
1729d134ffb9SArnaldo Carvalho de Melo 
17304979d0c7SJiri Olsa 	if (STAT_RECORD) {
17314979d0c7SJiri Olsa 		/*
17324979d0c7SJiri Olsa 		 * We synthesize the kernel mmap record just so that older tools
17334979d0c7SJiri Olsa 		 * don't emit warnings about not being able to resolve symbols
17344979d0c7SJiri Olsa 		 * due to /proc/sys/kernel/kptr_restrict settings and instear provide
17354979d0c7SJiri Olsa 		 * a saner message about no samples being in the perf.data file.
17364979d0c7SJiri Olsa 		 *
17374979d0c7SJiri Olsa 		 * This also serves to suppress a warning about f_header.data.size == 0
17388b99b1a4SJiri Olsa 		 * in header.c at the moment 'perf stat record' gets introduced, which
17398b99b1a4SJiri Olsa 		 * is not really needed once we start adding the stat specific PERF_RECORD_
17408b99b1a4SJiri Olsa 		 * records, but the need to suppress the kptr_restrict messages in older
17418b99b1a4SJiri Olsa 		 * tools remain  -acme
17424979d0c7SJiri Olsa 		 */
17434979d0c7SJiri Olsa 		int fd = perf_data_file__fd(&perf_stat.file);
17444979d0c7SJiri Olsa 		int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
17454979d0c7SJiri Olsa 							     process_synthesized_event,
17464979d0c7SJiri Olsa 							     &perf_stat.session->machines.host);
17474979d0c7SJiri Olsa 		if (err) {
17484979d0c7SJiri Olsa 			pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
17494979d0c7SJiri Olsa 				   "older tools may produce warnings about this file\n.");
17504979d0c7SJiri Olsa 		}
17514979d0c7SJiri Olsa 
17527aad0c32SJiri Olsa 		if (!interval) {
17537aad0c32SJiri Olsa 			if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
17547aad0c32SJiri Olsa 				pr_err("failed to write stat round event\n");
17557aad0c32SJiri Olsa 		}
17567aad0c32SJiri Olsa 
1757664c98d4SJiri Olsa 		if (!perf_stat.file.is_pipe) {
17584979d0c7SJiri Olsa 			perf_stat.session->header.data_size += perf_stat.bytes_written;
17594979d0c7SJiri Olsa 			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
1760664c98d4SJiri Olsa 		}
17614979d0c7SJiri Olsa 
17624979d0c7SJiri Olsa 		perf_session__delete(perf_stat.session);
17634979d0c7SJiri Olsa 	}
17644979d0c7SJiri Olsa 
1765544c2ae7SMasami Hiramatsu 	perf_stat__exit_aggr_mode();
1766d134ffb9SArnaldo Carvalho de Melo 	perf_evlist__free_stats(evsel_list);
17670015e2e1SArnaldo Carvalho de Melo out:
17680015e2e1SArnaldo Carvalho de Melo 	perf_evlist__delete(evsel_list);
176942202dd5SIngo Molnar 	return status;
177086470930SIngo Molnar }
1771