builtin-stat.c 33.7 KB
Newer Older
1
/*
2 3 4 5 6 7
 * builtin-stat.c
 *
 * Builtin stat command: Give a precise performance counters summary
 * overview about any workload, CPU or specific PID.
 *
 * Sample output:
8

9
   $ perf stat ./hackbench 10
10

11
  Time: 0.118
12

13
  Performance counter stats for './hackbench 10':
14

15 16 17 18 19 20 21 22 23 24 25 26 27
       1708.761321 task-clock                #   11.037 CPUs utilized
            41,190 context-switches          #    0.024 M/sec
             6,735 CPU-migrations            #    0.004 M/sec
            17,318 page-faults               #    0.010 M/sec
     5,205,202,243 cycles                    #    3.046 GHz
     3,856,436,920 stalled-cycles-frontend   #   74.09% frontend cycles idle
     1,600,790,871 stalled-cycles-backend    #   30.75% backend  cycles idle
     2,603,501,247 instructions              #    0.50  insns per cycle
                                             #    1.48  stalled cycles per insn
       484,357,498 branches                  #  283.455 M/sec
         6,388,934 branch-misses             #    1.32% of all branches

        0.154822978  seconds time elapsed
28

29
 *
30
 * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
31 32 33 34 35 36 37 38
 *
 * Improvements and fixes by:
 *
 *   Arjan van de Ven <arjan@linux.intel.com>
 *   Yanmin Zhang <yanmin.zhang@intel.com>
 *   Wu Fengguang <fengguang.wu@intel.com>
 *   Mike Galbraith <efault@gmx.de>
 *   Paul Mackerras <paulus@samba.org>
39
 *   Jaswinder Singh Rajput <jaswinder@kernel.org>
40 41
 *
 * Released under the GPL v2. (and only v2, not any later version)
42 43
 */

44
#include "perf.h"
45
#include "builtin.h"
46
#include "util/util.h"
47 48
#include "util/parse-options.h"
#include "util/parse-events.h"
49
#include "util/event.h"
50
#include "util/evlist.h"
51
#include "util/evsel.h"
52
#include "util/debug.h"
53
#include "util/color.h"
54
#include "util/stat.h"
55
#include "util/header.h"
56
#include "util/cpumap.h"
57
#include "util/thread.h"
58
#include "util/thread_map.h"
59

60
#include <stdlib.h>
61
#include <sys/prctl.h>
62
#include <locale.h>
63

S
Stephane Eranian 已提交
64
#define DEFAULT_SEPARATOR	" "
65 66
#define CNTR_NOT_SUPPORTED	"<not supported>"
#define CNTR_NOT_COUNTED	"<not counted>"
S
Stephane Eranian 已提交
67

68
static struct perf_evlist	*evsel_list;
69

70 71 72
static struct perf_target	target = {
	.uid	= UINT_MAX,
};
73

74
static int			run_count			=  1;
75
static bool			no_inherit			= false;
76
static bool			scale				=  true;
77
static bool			no_aggr				= false;
78
static pid_t			child_pid			= -1;
79
static bool			null_run			=  false;
80
static int			detailed_run			=  0;
81
static bool			big_num				=  true;
S
Stephane Eranian 已提交
82 83 84
static int			big_num_opt			=  -1;
static const char		*csv_sep			= NULL;
static bool			csv_output			= false;
85
static bool			group				= false;
86
static FILE			*output				= NULL;
87 88 89
static const char		*pre_cmd			= NULL;
static const char		*post_cmd			= NULL;
static bool			sync_run			= false;
90

91 92
static volatile int done = 0;

93 94 95 96
struct perf_stat {
	struct stats	  res_stats[3];
};

97
static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
98
{
99
	evsel->priv = zalloc(sizeof(struct perf_stat));
100 101 102 103 104 105 106 107 108
	return evsel->priv == NULL ? -ENOMEM : 0;
}

static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
{
	free(evsel->priv);
	evsel->priv = NULL;
}

Y
Yan, Zheng 已提交
109 110 111 112 113 114 115 116 117 118
static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
{
	return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
}

static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
{
	return perf_evsel__cpus(evsel)->nr;
}

119 120 121 122 123 124 125 126 127 128 129 130
static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS];
static struct stats runtime_branches_stats[MAX_NR_CPUS];
static struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
static struct stats walltime_nsecs_stats;
131

132
static int create_perf_stat_counter(struct perf_evsel *evsel)
133
{
134
	struct perf_event_attr *attr = &evsel->attr;
135 136
	bool exclude_guest_missing = false;
	int ret;
137

138
	if (scale)
139 140
		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
				    PERF_FORMAT_TOTAL_TIME_RUNNING;
141

142 143
	attr->inherit = !no_inherit;

144 145 146 147
retry:
	if (exclude_guest_missing)
		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;

148
	if (perf_target__has_cpu(&target)) {
Y
Yan, Zheng 已提交
149
		ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
150 151 152 153 154
		if (ret)
			goto check_ret;
		return 0;
	}

155
	if (!perf_target__has_task(&target) && (!evsel->leader)) {
156 157
		attr->disabled = 1;
		attr->enable_on_exec = 1;
158
	}
159

160
	ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
161 162 163 164 165 166 167 168 169 170 171 172 173 174
	if (!ret)
		return 0;
	/* fall through */
check_ret:
	if (ret && errno == EINVAL) {
		if (!exclude_guest_missing &&
		    (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
			pr_debug("Old kernel, cannot exclude "
				 "guest or host samples.\n");
			exclude_guest_missing = true;
			goto retry;
		}
	}
	return ret;
175 176
}

177 178 179
/*
 * Does the counter have nsecs as a unit?
 */
180
static inline int nsec_counter(struct perf_evsel *evsel)
181
{
182 183
	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
184 185 186 187 188
		return 1;

	return 0;
}

I
Ingo Molnar 已提交
189 190 191 192 193 194 195 196 197 198 199
/*
 * Update various tracking values we maintain to print
 * more semantic information such as miss/hit ratios,
 * instruction rates, etc:
 */
static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
{
	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
		update_stats(&runtime_nsecs_stats[0], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
		update_stats(&runtime_cycles_stats[0], count[0]);
200 201
	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
		update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
202
	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
203
		update_stats(&runtime_stalled_cycles_back_stats[0], count[0]);
I
Ingo Molnar 已提交
204 205 206 207
	else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
		update_stats(&runtime_branches_stats[0], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
		update_stats(&runtime_cacherefs_stats[0], count[0]);
208 209
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
		update_stats(&runtime_l1_dcache_stats[0], count[0]);
210 211 212 213 214 215 216 217
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
		update_stats(&runtime_l1_icache_stats[0], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
		update_stats(&runtime_ll_cache_stats[0], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
		update_stats(&runtime_dtlb_cache_stats[0], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
		update_stats(&runtime_itlb_cache_stats[0], count[0]);
I
Ingo Molnar 已提交
218 219
}

220
/*
221
 * Read out the results of a single counter:
222
 * aggregate counts across CPUs in system-wide mode
223
 */
224
static int read_counter_aggr(struct perf_evsel *counter)
225
{
226
	struct perf_stat *ps = counter->priv;
227 228
	u64 *count = counter->counts->aggr.values;
	int i;
229

Y
Yan, Zheng 已提交
230
	if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
231
			       evsel_list->threads->nr, scale) < 0)
232
		return -1;
233 234

	for (i = 0; i < 3; i++)
235
		update_stats(&ps->res_stats[i], count[i]);
236 237

	if (verbose) {
238
		fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
239
			perf_evsel__name(counter), count[0], count[1], count[2]);
240 241
	}

242 243 244
	/*
	 * Save the full runtime - to allow normalization during printout:
	 */
I
Ingo Molnar 已提交
245
	update_shadow_stats(counter, count);
246 247

	return 0;
248 249 250 251 252 253
}

/*
 * Read out the results of a single counter:
 * do not aggregate counts across CPUs in system-wide mode
 */
254
static int read_counter(struct perf_evsel *counter)
255
{
256
	u64 *count;
257 258
	int cpu;

Y
Yan, Zheng 已提交
259
	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
260 261
		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
			return -1;
262

263
		count = counter->counts->cpu[cpu].values;
264

I
Ingo Molnar 已提交
265
		update_shadow_stats(counter, count);
266
	}
267 268

	return 0;
269 270
}

271
static int __run_perf_stat(int argc __maybe_unused, const char **argv)
272 273
{
	unsigned long long t0, t1;
274
	struct perf_evsel *counter;
275
	int status = 0;
276
	int child_ready_pipe[2], go_pipe[2];
277
	const bool forks = (argc > 0);
278
	char buf;
279

280
	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
281
		perror("failed to create pipes");
282
		return -1;
283 284
	}

285
	if (forks) {
286
		if ((child_pid = fork()) < 0)
287 288
			perror("failed to fork");

289
		if (!child_pid) {
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
			close(child_ready_pipe[0]);
			close(go_pipe[1]);
			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);

			/*
			 * Do a dummy execvp to get the PLT entry resolved,
			 * so we avoid the resolver overhead on the real
			 * execvp call.
			 */
			execvp("", (char **)argv);

			/*
			 * Tell the parent we're ready to go
			 */
			close(child_ready_pipe[1]);

			/*
			 * Wait until the parent tells us to go.
			 */
			if (read(go_pipe[0], &buf, 1) == -1)
				perror("unable to read pipe");

			execvp(argv[0], (char **)argv);

			perror(argv[0]);
			exit(-1);
		}
317

318
		if (perf_target__none(&target))
319
			evsel_list->threads->map[0] = child_pid;
320

321
		/*
322
		 * Wait for the child to be ready to exec.
323 324
		 */
		close(child_ready_pipe[1]);
325 326
		close(go_pipe[0]);
		if (read(child_ready_pipe[0], &buf, 1) == -1)
327
			perror("unable to read pipe");
328
		close(child_ready_pipe[0]);
329 330
	}

331
	if (group)
332
		perf_evlist__set_leader(evsel_list);
333

334
	list_for_each_entry(counter, &evsel_list->entries, node) {
335
		if (create_perf_stat_counter(counter) < 0) {
336 337 338 339
			/*
			 * PPC returns ENXIO for HW counters until 2.6.37
			 * (behavior changed with commit b0a873e).
			 */
340
			if (errno == EINVAL || errno == ENOSYS ||
341 342
			    errno == ENOENT || errno == EOPNOTSUPP ||
			    errno == ENXIO) {
343 344
				if (verbose)
					ui__warning("%s event is not supported by the kernel.\n",
345
						    perf_evsel__name(counter));
346
				counter->supported = false;
347
				continue;
348
			}
349 350

			if (errno == EPERM || errno == EACCES) {
351 352 353
				error("You may not have permission to collect %sstats.\n"
				      "\t Consider tweaking"
				      " /proc/sys/kernel/perf_event_paranoid or running as root.",
354
				      target.system_wide ? "system-wide " : "");
355 356 357 358 359 360 361
			} else {
				error("open_counter returned with %d (%s). "
				      "/bin/dmesg may provide additional information.\n",
				       errno, strerror(errno));
			}
			if (child_pid != -1)
				kill(child_pid, SIGTERM);
362 363

			pr_err("Not all events could be opened.\n");
364 365
			return -1;
		}
366
		counter->supported = true;
367
	}
368

369
	if (perf_evlist__apply_filters(evsel_list)) {
370 371 372 373 374
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		return -1;
	}

375 376 377 378 379
	/*
	 * Enable counters and exec the command:
	 */
	t0 = rdclock();

380 381 382
	if (forks) {
		close(go_pipe[1]);
		wait(&status);
383 384
		if (WIFSIGNALED(status))
			psignal(WTERMSIG(status), argv[0]);
385
	} else {
386
		while(!done) sleep(1);
387
	}
388 389 390

	t1 = rdclock();

391
	update_stats(&walltime_nsecs_stats, t1 - t0);
392

393
	if (no_aggr) {
394
		list_for_each_entry(counter, &evsel_list->entries, node) {
395
			read_counter(counter);
Y
Yan, Zheng 已提交
396
			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
397
		}
398
	} else {
399
		list_for_each_entry(counter, &evsel_list->entries, node) {
400
			read_counter_aggr(counter);
Y
Yan, Zheng 已提交
401
			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
402
					     evsel_list->threads->nr);
403
		}
404
	}
405

406 407 408
	return WEXITSTATUS(status);
}

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
static int run_perf_stat(int argc __maybe_unused, const char **argv)
{
	int ret;

	if (pre_cmd) {
		ret = system(pre_cmd);
		if (ret)
			return ret;
	}

	if (sync_run)
		sync();

	ret = __run_perf_stat(argc, argv);
	if (ret)
		return ret;

	if (post_cmd) {
		ret = system(post_cmd);
		if (ret)
			return ret;
	}

	return ret;
}

435 436
static void print_noise_pct(double total, double avg)
{
437
	double pct = rel_stddev_stats(total, avg);
438

439
	if (csv_output)
440
		fprintf(output, "%s%.2f%%", csv_sep, pct);
441
	else if (pct)
442
		fprintf(output, "  ( +-%6.2f%% )", pct);
443 444
}

445
static void print_noise(struct perf_evsel *evsel, double avg)
446
{
447 448
	struct perf_stat *ps;

449 450 451
	if (run_count == 1)
		return;

452
	ps = evsel->priv;
453
	print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
454 455
}

456
static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
I
Ingo Molnar 已提交
457
{
458
	double msecs = avg / 1e6;
S
Stephane Eranian 已提交
459
	char cpustr[16] = { '\0', };
460
	const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s";
I
Ingo Molnar 已提交
461

462
	if (no_aggr)
S
Stephane Eranian 已提交
463 464
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
Y
Yan, Zheng 已提交
465
			perf_evsel__cpus(evsel)->map[cpu], csv_sep);
S
Stephane Eranian 已提交
466

467
	fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
S
Stephane Eranian 已提交
468

S
Stephane Eranian 已提交
469
	if (evsel->cgrp)
470
		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
S
Stephane Eranian 已提交
471

S
Stephane Eranian 已提交
472 473
	if (csv_output)
		return;
I
Ingo Molnar 已提交
474

475
	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
476 477
		fprintf(output, " # %8.3f CPUs utilized          ",
			avg / avg_stats(&walltime_nsecs_stats));
478 479
	else
		fprintf(output, "                                   ");
I
Ingo Molnar 已提交
480 481
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
/* used for get_ratio_color() */
enum grc_type {
	GRC_STALLED_CYCLES_FE,
	GRC_STALLED_CYCLES_BE,
	GRC_CACHE_MISSES,
	GRC_MAX_NR
};

static const char *get_ratio_color(enum grc_type type, double ratio)
{
	static const double grc_table[GRC_MAX_NR][3] = {
		[GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 },
		[GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 },
		[GRC_CACHE_MISSES] 	= { 20.0, 10.0, 5.0 },
	};
	const char *color = PERF_COLOR_NORMAL;

	if (ratio > grc_table[type][0])
		color = PERF_COLOR_RED;
	else if (ratio > grc_table[type][1])
		color = PERF_COLOR_MAGENTA;
	else if (ratio > grc_table[type][2])
		color = PERF_COLOR_YELLOW;

	return color;
}

509 510 511
static void print_stalled_cycles_frontend(int cpu,
					  struct perf_evsel *evsel
					  __maybe_unused, double avg)
512 513 514 515 516 517 518 519 520
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_cycles_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

521
	color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
522

523 524 525
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " frontend cycles idle   ");
526 527
}

528 529 530
static void print_stalled_cycles_backend(int cpu,
					 struct perf_evsel *evsel
					 __maybe_unused, double avg)
531 532 533 534 535 536 537 538 539
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_cycles_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

540
	color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
541

542 543 544
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " backend  cycles idle   ");
545 546
}

547 548 549
static void print_branch_misses(int cpu,
				struct perf_evsel *evsel __maybe_unused,
				double avg)
550 551 552 553 554 555 556 557 558
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_branches_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

559
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
560

561 562 563
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all branches        ");
564 565
}

566 567 568
static void print_l1_dcache_misses(int cpu,
				   struct perf_evsel *evsel __maybe_unused,
				   double avg)
569 570 571 572 573 574 575 576 577
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_l1_dcache_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

578
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
579

580 581 582
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all L1-dcache hits  ");
583 584
}

585 586 587
static void print_l1_icache_misses(int cpu,
				   struct perf_evsel *evsel __maybe_unused,
				   double avg)
588 589 590 591 592 593 594 595 596
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_l1_icache_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

597
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
598

599 600 601
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all L1-icache hits  ");
602 603
}

604 605 606
static void print_dtlb_cache_misses(int cpu,
				    struct perf_evsel *evsel __maybe_unused,
				    double avg)
607 608 609 610 611 612 613 614 615
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_dtlb_cache_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

616
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
617

618 619 620
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all dTLB cache hits ");
621 622
}

623 624 625
static void print_itlb_cache_misses(int cpu,
				    struct perf_evsel *evsel __maybe_unused,
				    double avg)
626 627 628 629 630 631 632 633 634
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_itlb_cache_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

635
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
636

637 638 639
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all iTLB cache hits ");
640 641
}

642 643 644
static void print_ll_cache_misses(int cpu,
				  struct perf_evsel *evsel __maybe_unused,
				  double avg)
645 646 647 648 649 650 651 652 653
{
	double total, ratio = 0.0;
	const char *color;

	total = avg_stats(&runtime_ll_cache_stats[cpu]);

	if (total)
		ratio = avg / total * 100.0;

654
	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
655

656 657 658
	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all LL-cache hits   ");
659 660
}

661
static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
I
Ingo Molnar 已提交
662
{
663
	double total, ratio = 0.0;
664
	char cpustr[16] = { '\0', };
S
Stephane Eranian 已提交
665 666 667 668 669
	const char *fmt;

	if (csv_output)
		fmt = "%s%.0f%s%s";
	else if (big_num)
670
		fmt = "%s%'18.0f%s%-25s";
S
Stephane Eranian 已提交
671
	else
672
		fmt = "%s%18.0f%s%-25s";
673 674

	if (no_aggr)
S
Stephane Eranian 已提交
675 676
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
Y
Yan, Zheng 已提交
677
			perf_evsel__cpus(evsel)->map[cpu], csv_sep);
678 679
	else
		cpu = 0;
680

681
	fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
S
Stephane Eranian 已提交
682

S
Stephane Eranian 已提交
683
	if (evsel->cgrp)
684
		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
S
Stephane Eranian 已提交
685

S
Stephane Eranian 已提交
686 687
	if (csv_output)
		return;
I
Ingo Molnar 已提交
688

689
	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
690
		total = avg_stats(&runtime_cycles_stats[cpu]);
691 692 693 694

		if (total)
			ratio = avg / total;

695
		fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
696

697 698
		total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
		total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
699 700 701

		if (total && avg) {
			ratio = total / avg;
702
			fprintf(output, "\n                                             #   %5.2f  stalled cycles per insn", ratio);
703 704
		}

705
	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
706
			runtime_branches_stats[cpu].n != 0) {
707
		print_branch_misses(cpu, evsel, avg);
708 709 710 711 712
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
713
			runtime_l1_dcache_stats[cpu].n != 0) {
714
		print_l1_dcache_misses(cpu, evsel, avg);
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_l1_icache_stats[cpu].n != 0) {
		print_l1_icache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_dtlb_cache_stats[cpu].n != 0) {
		print_dtlb_cache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_itlb_cache_stats[cpu].n != 0) {
		print_itlb_cache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_ll_cache_stats[cpu].n != 0) {
		print_ll_cache_misses(cpu, evsel, avg);
743 744 745 746 747 748 749
	} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
			runtime_cacherefs_stats[cpu].n != 0) {
		total = avg_stats(&runtime_cacherefs_stats[cpu]);

		if (total)
			ratio = avg * 100 / total;

750
		fprintf(output, " # %8.3f %% of all cache refs    ", ratio);
751

752 753
	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
		print_stalled_cycles_frontend(cpu, evsel, avg);
754
	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
755
		print_stalled_cycles_backend(cpu, evsel, avg);
756
	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
757
		total = avg_stats(&runtime_nsecs_stats[cpu]);
758 759

		if (total)
760
			ratio = 1.0 * avg / total;
761

762
		fprintf(output, " # %8.3f GHz                    ", ratio);
763
	} else if (runtime_nsecs_stats[cpu].n != 0) {
N
Namhyung Kim 已提交
764 765
		char unit = 'M';

766
		total = avg_stats(&runtime_nsecs_stats[cpu]);
767 768

		if (total)
769
			ratio = 1000.0 * avg / total;
N
Namhyung Kim 已提交
770 771 772 773
		if (ratio < 0.001) {
			ratio *= 1000;
			unit = 'K';
		}
774

N
Namhyung Kim 已提交
775
		fprintf(output, " # %8.3f %c/sec                  ", ratio, unit);
776
	} else {
777
		fprintf(output, "                                   ");
I
Ingo Molnar 已提交
778 779 780
	}
}

781 782
/*
 * Print out the results of a single counter:
783
 * aggregated counts in system-wide mode
784
 */
785
static void print_counter_aggr(struct perf_evsel *counter)
786
{
787 788
	struct perf_stat *ps = counter->priv;
	double avg = avg_stats(&ps->res_stats[0]);
789
	int scaled = counter->counts->scaled;
790 791

	if (scaled == -1) {
792
		fprintf(output, "%*s%s%*s",
S
Stephane Eranian 已提交
793
			csv_output ? 0 : 18,
794
			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
S
Stephane Eranian 已提交
795 796
			csv_sep,
			csv_output ? 0 : -24,
797
			perf_evsel__name(counter));
S
Stephane Eranian 已提交
798 799

		if (counter->cgrp)
800
			fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
S
Stephane Eranian 已提交
801

802
		fputc('\n', output);
803 804
		return;
	}
805

I
Ingo Molnar 已提交
806
	if (nsec_counter(counter))
807
		nsec_printout(-1, counter, avg);
I
Ingo Molnar 已提交
808
	else
809
		abs_printout(-1, counter, avg);
810

811 812
	print_noise(counter, avg);

S
Stephane Eranian 已提交
813
	if (csv_output) {
814
		fputc('\n', output);
S
Stephane Eranian 已提交
815 816 817
		return;
	}

818 819 820
	if (scaled) {
		double avg_enabled, avg_running;

821 822
		avg_enabled = avg_stats(&ps->res_stats[1]);
		avg_running = avg_stats(&ps->res_stats[2]);
823

824
		fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
825
	}
826
	fprintf(output, "\n");
827 828
}

829 830 831 832
/*
 * Print out the results of a single counter:
 * does not use aggregated count in system-wide
 */
833
static void print_counter(struct perf_evsel *counter)
834 835 836 837
{
	u64 ena, run, val;
	int cpu;

Y
Yan, Zheng 已提交
838
	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
839 840 841
		val = counter->counts->cpu[cpu].val;
		ena = counter->counts->cpu[cpu].ena;
		run = counter->counts->cpu[cpu].run;
842
		if (run == 0 || ena == 0) {
843
			fprintf(output, "CPU%*d%s%*s%s%*s",
S
Stephane Eranian 已提交
844
				csv_output ? 0 : -4,
Y
Yan, Zheng 已提交
845
				perf_evsel__cpus(counter)->map[cpu], csv_sep,
S
Stephane Eranian 已提交
846
				csv_output ? 0 : 18,
847 848
				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
				csv_sep,
S
Stephane Eranian 已提交
849
				csv_output ? 0 : -24,
850
				perf_evsel__name(counter));
851

S
Stephane Eranian 已提交
852
			if (counter->cgrp)
853 854
				fprintf(output, "%s%s",
					csv_sep, counter->cgrp->name);
S
Stephane Eranian 已提交
855

856
			fputc('\n', output);
857 858 859 860 861 862 863 864
			continue;
		}

		if (nsec_counter(counter))
			nsec_printout(cpu, counter, val);
		else
			abs_printout(cpu, counter, val);

S
Stephane Eranian 已提交
865 866
		if (!csv_output) {
			print_noise(counter, 1.0);
867

868
			if (run != ena)
869 870
				fprintf(output, "  (%.2f%%)",
					100.0 * run / ena);
871
		}
872
		fputc('\n', output);
873 874 875
	}
}

876 877
static void print_stat(int argc, const char **argv)
{
878 879
	struct perf_evsel *counter;
	int i;
880

881 882
	fflush(stdout);

S
Stephane Eranian 已提交
883
	if (!csv_output) {
884 885
		fprintf(output, "\n");
		fprintf(output, " Performance counter stats for ");
886
		if (!perf_target__has_task(&target)) {
887
			fprintf(output, "\'%s", argv[0]);
S
Stephane Eranian 已提交
888
			for (i = 1; i < argc; i++)
889
				fprintf(output, " %s", argv[i]);
890 891
		} else if (target.pid)
			fprintf(output, "process id \'%s", target.pid);
S
Stephane Eranian 已提交
892
		else
893
			fprintf(output, "thread id \'%s", target.tid);
I
Ingo Molnar 已提交
894

895
		fprintf(output, "\'");
S
Stephane Eranian 已提交
896
		if (run_count > 1)
897 898
			fprintf(output, " (%d runs)", run_count);
		fprintf(output, ":\n\n");
S
Stephane Eranian 已提交
899
	}
900

901
	if (no_aggr) {
902
		list_for_each_entry(counter, &evsel_list->entries, node)
903 904
			print_counter(counter);
	} else {
905
		list_for_each_entry(counter, &evsel_list->entries, node)
906 907
			print_counter_aggr(counter);
	}
908

S
Stephane Eranian 已提交
909
	if (!csv_output) {
910
		if (!null_run)
911 912
			fprintf(output, "\n");
		fprintf(output, " %17.9f seconds time elapsed",
S
Stephane Eranian 已提交
913 914
				avg_stats(&walltime_nsecs_stats)/1e9);
		if (run_count > 1) {
915
			fprintf(output, "                                        ");
916 917
			print_noise_pct(stddev_stats(&walltime_nsecs_stats),
					avg_stats(&walltime_nsecs_stats));
S
Stephane Eranian 已提交
918
		}
919
		fprintf(output, "\n\n");
I
Ingo Molnar 已提交
920
	}
921 922
}

923 924
static volatile int signr = -1;

925
static void skip_signal(int signo)
926
{
927
	if(child_pid == -1)
928 929
		done = 1;

930 931 932 933 934
	signr = signo;
}

static void sig_atexit(void)
{
935 936 937
	if (child_pid != -1)
		kill(child_pid, SIGTERM);

938 939 940 941 942
	if (signr == -1)
		return;

	signal(signr, SIG_DFL);
	kill(getpid(), signr);
943 944
}

945 946
static int stat__set_big_num(const struct option *opt __maybe_unused,
			     const char *s __maybe_unused, int unset)
S
Stephane Eranian 已提交
947 948 949 950 951
{
	big_num_opt = unset ? 0 : 1;
	return 0;
}

952 953 954 955 956 957
/*
 * Add default attributes, if there were no attributes specified or
 * if -d/--detailed, -d -d or -d -d -d is used:
 */
static int add_default_attributes(void)
{
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
	struct perf_event_attr default_attrs[] = {

  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},

  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},

};

/*
 * Detailed stats (-d), covering the L1 and last level data caches:
 */
	struct perf_event_attr detailed_attrs[] = {

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_LL			<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_LL			<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
};

/*
 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
 */
	struct perf_event_attr very_detailed_attrs[] = {

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},

};

/*
 * Very, very detailed stats (-d -d -d), adding prefetch events:
 */
	struct perf_event_attr very_very_detailed_attrs[] = {

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},

  { .type = PERF_TYPE_HW_CACHE,
    .config =
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
};

1065 1066 1067 1068 1069
	/* Set attrs if no event is selected and !null_run: */
	if (null_run)
		return 0;

	if (!evsel_list->nr_entries) {
1070
		if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
1071
			return -1;
1072 1073 1074 1075 1076 1077 1078 1079
	}

	/* Detailed events get appended to the event list: */

	if (detailed_run <  1)
		return 0;

	/* Append detailed run extra attributes: */
1080
	if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
1081
		return -1;
1082 1083 1084 1085 1086

	if (detailed_run < 2)
		return 0;

	/* Append very detailed run extra attributes: */
1087
	if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
1088
		return -1;
1089 1090 1091 1092 1093

	if (detailed_run < 3)
		return 0;

	/* Append very, very detailed run extra attributes: */
1094
	return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1095 1096
}

1097
int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1098
{
1099
	bool append_file = false;
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
	int output_fd = 0;
	const char *output_name	= NULL;
	const struct option options[] = {
	OPT_CALLBACK('e', "event", &evsel_list, "event",
		     "event selector. use 'perf list' to list available events",
		     parse_events_option),
	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
		     "event filter", parse_filter),
	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
		    "child tasks do not inherit counters"),
	OPT_STRING('p', "pid", &target.pid, "pid",
		   "stat events on existing process id"),
	OPT_STRING('t', "tid", &target.tid, "tid",
		   "stat events on existing thread id"),
	OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
		    "system-wide collection from all CPUs"),
	OPT_BOOLEAN('g', "group", &group,
		    "put the counters into a counter group"),
	OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
	OPT_INCR('v', "verbose", &verbose,
		    "be more verbose (show counter open errors, etc)"),
	OPT_INTEGER('r', "repeat", &run_count,
		    "repeat command and print average + stddev (max: 100)"),
	OPT_BOOLEAN('n', "null", &null_run,
		    "null run - dont start any counters"),
	OPT_INCR('d', "detailed", &detailed_run,
		    "detailed run - start a lot of events"),
	OPT_BOOLEAN('S', "sync", &sync_run,
		    "call sync() before starting a run"),
	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
			   "print large numbers with thousands\' separators",
			   stat__set_big_num),
	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
		    "list of cpus to monitor in system-wide"),
	OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
	OPT_STRING('x', "field-separator", &csv_sep, "separator",
		   "print counts with custom separator"),
	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
		     "monitor event in cgroup name only", parse_cgroups),
	OPT_STRING('o', "output", &output_name, "file", "output file name"),
	OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
	OPT_INTEGER(0, "log-fd", &output_fd,
		    "log output to fd, instead of stderr"),
1143 1144 1145 1146
	OPT_STRING(0, "pre", &pre_cmd, "command",
			"command to run prior to the measured command"),
	OPT_STRING(0, "post", &post_cmd, "command",
			"command to run after to the measured command"),
1147 1148 1149 1150 1151 1152
	OPT_END()
	};
	const char * const stat_usage[] = {
		"perf stat [<options>] [<command>]",
		NULL
	};
1153
	struct perf_evsel *pos;
1154
	int status = -ENOMEM, run_idx;
1155
	const char *mode;
1156

1157 1158
	setlocale(LC_ALL, "");

1159
	evsel_list = perf_evlist__new(NULL, NULL);
1160 1161 1162
	if (evsel_list == NULL)
		return -ENOMEM;

1163 1164
	argc = parse_options(argc, argv, options, stat_usage,
		PARSE_OPT_STOP_AT_NON_OPTION);
S
Stephane Eranian 已提交
1165

1166 1167 1168 1169
	output = stderr;
	if (output_name && strcmp(output_name, "-"))
		output = NULL;

1170 1171 1172 1173
	if (output_name && output_fd) {
		fprintf(stderr, "cannot use both --output and --log-fd\n");
		usage_with_options(stat_usage, options);
	}
1174 1175 1176 1177 1178 1179

	if (output_fd < 0) {
		fprintf(stderr, "argument to --log-fd must be a > 0\n");
		usage_with_options(stat_usage, options);
	}

1180 1181 1182 1183 1184 1185 1186
	if (!output) {
		struct timespec tm;
		mode = append_file ? "a" : "w";

		output = fopen(output_name, mode);
		if (!output) {
			perror("failed to create output file");
1187
			return -1;
1188 1189 1190
		}
		clock_gettime(CLOCK_REALTIME, &tm);
		fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1191
	} else if (output_fd > 0) {
1192 1193 1194 1195 1196 1197
		mode = append_file ? "a" : "w";
		output = fdopen(output_fd, mode);
		if (!output) {
			perror("Failed opening logfd");
			return -errno;
		}
1198 1199
	}

1200
	if (csv_sep) {
S
Stephane Eranian 已提交
1201
		csv_output = true;
1202 1203 1204
		if (!strcmp(csv_sep, "\\t"))
			csv_sep = "\t";
	} else
S
Stephane Eranian 已提交
1205 1206 1207 1208 1209 1210
		csv_sep = DEFAULT_SEPARATOR;

	/*
	 * let the spreadsheet do the pretty-printing
	 */
	if (csv_output) {
J
Jim Cromie 已提交
1211
		/* User explicitly passed -B? */
S
Stephane Eranian 已提交
1212 1213 1214 1215 1216 1217 1218 1219
		if (big_num_opt == 1) {
			fprintf(stderr, "-B option not supported with -x\n");
			usage_with_options(stat_usage, options);
		} else /* Nope, so disable big number formatting */
			big_num = false;
	} else if (big_num_opt == 0) /* User passed --no-big-num */
		big_num = false;

1220
	if (!argc && !perf_target__has_task(&target))
1221
		usage_with_options(stat_usage, options);
1222
	if (run_count <= 0)
1223
		usage_with_options(stat_usage, options);
1224

S
Stephane Eranian 已提交
1225
	/* no_aggr, cgroup are for system-wide only */
1226
	if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) {
S
Stephane Eranian 已提交
1227 1228 1229
		fprintf(stderr, "both cgroup and no-aggregation "
			"modes only available in system-wide mode\n");

1230
		usage_with_options(stat_usage, options);
S
Stephane Eranian 已提交
1231
	}
1232

1233 1234
	if (add_default_attributes())
		goto out;
1235

1236
	perf_target__validate(&target);
1237

1238
	if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1239
		if (perf_target__has_task(&target))
1240
			pr_err("Problems finding threads of monitor\n");
1241
		if (perf_target__has_cpu(&target))
1242
			perror("failed to parse CPUs map");
1243

1244
		usage_with_options(stat_usage, options);
1245 1246
		return -1;
	}
1247

1248
	list_for_each_entry(pos, &evsel_list->entries, node) {
1249
		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
Y
Yan, Zheng 已提交
1250
		    perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
1251
			goto out_free_fd;
1252 1253
	}

I
Ingo Molnar 已提交
1254 1255 1256 1257 1258 1259
	/*
	 * We dont want to block the signals - that would cause
	 * child tasks to inherit that and Ctrl-C would not work.
	 * What we want is for Ctrl-C to work in the exec()-ed
	 * task, but being ignored by perf stat itself:
	 */
1260
	atexit(sig_atexit);
I
Ingo Molnar 已提交
1261 1262 1263 1264
	signal(SIGINT,  skip_signal);
	signal(SIGALRM, skip_signal);
	signal(SIGABRT, skip_signal);

1265 1266 1267
	status = 0;
	for (run_idx = 0; run_idx < run_count; run_idx++) {
		if (run_count != 1 && verbose)
1268 1269
			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
				run_idx + 1);
I
Ingo Molnar 已提交
1270

1271 1272 1273
		status = run_perf_stat(argc, argv);
	}

1274 1275
	if (status != -1)
		print_stat(argc, argv);
1276
out_free_fd:
1277
	list_for_each_entry(pos, &evsel_list->entries, node)
1278
		perf_evsel__free_stat_priv(pos);
1279
	perf_evlist__delete_maps(evsel_list);
1280 1281
out:
	perf_evlist__delete(evsel_list);
1282
	return status;
1283
}