builtin-stat.c 42.2 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/cgroup.h"
47
#include "util/util.h"
48
#include <subcmd/parse-options.h>
49
#include "util/parse-events.h"
50
#include "util/pmu.h"
51
#include "util/event.h"
52
#include "util/evlist.h"
53
#include "util/evsel.h"
54
#include "util/debug.h"
55
#include "util/color.h"
56
#include "util/stat.h"
57
#include "util/header.h"
58
#include "util/cpumap.h"
59
#include "util/thread.h"
60
#include "util/thread_map.h"
61
#include "util/counts.h"
J
Jiri Olsa 已提交
62
#include "util/session.h"
63

64
#include <stdlib.h>
65
#include <sys/prctl.h>
66
#include <locale.h>
67

S
Stephane Eranian 已提交
68
#define DEFAULT_SEPARATOR	" "
69 70
#define CNTR_NOT_SUPPORTED	"<not supported>"
#define CNTR_NOT_COUNTED	"<not counted>"
S
Stephane Eranian 已提交
71

72
static void print_counters(struct timespec *ts, int argc, const char **argv);
73

74
/* Default events used for perf stat -T */
75 76
static const char *transaction_attrs = {
	"task-clock,"
77 78 79 80 81 82 83 84 85 86 87
	"{"
	"instructions,"
	"cycles,"
	"cpu/cycles-t/,"
	"cpu/tx-start/,"
	"cpu/el-start/,"
	"cpu/cycles-ct/"
	"}"
};

/* More limited version when the CPU does not have all events. */
88 89
static const char * transaction_limited_attrs = {
	"task-clock,"
90 91 92 93 94 95 96 97
	"{"
	"instructions,"
	"cycles,"
	"cpu/cycles-t/,"
	"cpu/tx-start/"
	"}"
};

98
static struct perf_evlist	*evsel_list;
99

100
static struct target target = {
101 102
	.uid	= UINT_MAX,
};
103

104 105
typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);

106
static int			run_count			=  1;
107
static bool			no_inherit			= false;
108
static volatile pid_t		child_pid			= -1;
109
static bool			null_run			=  false;
110
static int			detailed_run			=  0;
111
static bool			transaction_run;
112
static bool			big_num				=  true;
S
Stephane Eranian 已提交
113 114 115
static int			big_num_opt			=  -1;
static const char		*csv_sep			= NULL;
static bool			csv_output			= false;
116
static bool			group				= false;
117 118 119
static const char		*pre_cmd			= NULL;
static const char		*post_cmd			= NULL;
static bool			sync_run			= false;
120
static unsigned int		initial_delay			= 0;
121
static unsigned int		unit_width			= 4; /* strlen("unit") */
122
static bool			forever				= false;
123
static struct timespec		ref_time;
124
static struct cpu_map		*aggr_map;
125
static aggr_get_id_t		aggr_get_id;
J
Jiri Olsa 已提交
126 127 128
static bool			append_file;
static const char		*output_name;
static int			output_fd;
129

J
Jiri Olsa 已提交
130 131 132 133 134 135 136 137 138 139
struct perf_stat {
	bool			 record;
	struct perf_data_file	 file;
	struct perf_session	*session;
	u64			 bytes_written;
};

static struct perf_stat		perf_stat;
#define STAT_RECORD		perf_stat.record

140 141
static volatile int done = 0;

142 143
static struct perf_stat_config stat_config = {
	.aggr_mode	= AGGR_GLOBAL,
144
	.scale		= true,
145 146
};

147 148 149 150 151 152 153 154 155 156 157 158
static inline void diff_timespec(struct timespec *r, struct timespec *a,
				 struct timespec *b)
{
	r->tv_sec = a->tv_sec - b->tv_sec;
	if (a->tv_nsec < b->tv_nsec) {
		r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec;
		r->tv_sec--;
	} else {
		r->tv_nsec = a->tv_nsec - b->tv_nsec ;
	}
}

159 160 161
static void perf_stat__reset_stats(void)
{
	perf_evlist__reset_stats(evsel_list);
162
	perf_stat__reset_shadow_stats();
163 164
}

165
static int create_perf_stat_counter(struct perf_evsel *evsel)
166
{
167
	struct perf_event_attr *attr = &evsel->attr;
168

169
	if (stat_config.scale)
170 171
		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
				    PERF_FORMAT_TOTAL_TIME_RUNNING;
172

173 174
	attr->inherit = !no_inherit;

175 176 177 178 179
	/*
	 * Some events get initialized with sample_(period/type) set,
	 * like tracepoints. Clear it up for counting.
	 */
	attr->sample_period = 0;
J
Jiri Olsa 已提交
180 181 182 183 184
	/*
	 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
	 * while avoiding that older tools show confusing messages.
	 */
	attr->sample_type   = PERF_SAMPLE_IDENTIFIER;
185

J
Jiri Olsa 已提交
186 187 188 189 190
	/*
	 * Disabling all counters initially, they will be enabled
	 * either manually by us or by kernel via enable_on_exec
	 * set later.
	 */
191
	if (perf_evsel__is_group_leader(evsel)) {
J
Jiri Olsa 已提交
192 193
		attr->disabled = 1;

194 195 196 197 198
		/*
		 * In case of initial_delay we enable tracee
		 * events manually.
		 */
		if (target__none(&target) && !initial_delay)
199
			attr->enable_on_exec = 1;
200
	}
201

202 203 204
	if (target__has_cpu(&target))
		return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));

205
	return perf_evsel__open_per_thread(evsel, evsel_list->threads);
206 207
}

208 209 210
/*
 * Does the counter have nsecs as a unit?
 */
211
static inline int nsec_counter(struct perf_evsel *evsel)
212
{
213 214
	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
215 216 217 218 219
		return 1;

	return 0;
}

220 221 222 223
static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
				     union perf_event *event,
				     struct perf_sample *sample __maybe_unused,
				     struct machine *machine __maybe_unused)
J
Jiri Olsa 已提交
224
{
225
	if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) {
J
Jiri Olsa 已提交
226 227 228 229
		pr_err("failed to write perf data, error: %m\n");
		return -1;
	}

230
	perf_stat.bytes_written += event->header.size;
J
Jiri Olsa 已提交
231 232 233
	return 0;
}

234 235 236 237 238 239 240 241 242 243 244 245
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)

static int
perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
			     struct perf_counts_values *count)
{
	struct perf_sample_id *sid = SID(counter, cpu, thread);

	return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
					   process_synthesized_event, NULL);
}

246 247 248 249
/*
 * Read out the results of a single counter:
 * do not aggregate counts across CPUs in system-wide mode
 */
250
static int read_counter(struct perf_evsel *counter)
251
{
252 253 254
	int nthreads = thread_map__nr(evsel_list->threads);
	int ncpus = perf_evsel__nr_cpus(counter);
	int cpu, thread;
255

256 257 258
	if (!counter->supported)
		return -ENOENT;

259 260 261 262 263
	if (counter->system_wide)
		nthreads = 1;

	for (thread = 0; thread < nthreads; thread++) {
		for (cpu = 0; cpu < ncpus; cpu++) {
264 265 266 267
			struct perf_counts_values *count;

			count = perf_counts(counter->counts, cpu, thread);
			if (perf_evsel__read(counter, cpu, thread, count))
268
				return -1;
269 270 271 272 273 274 275

			if (STAT_RECORD) {
				if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
					pr_err("failed to write stat event\n");
					return -1;
				}
			}
276
		}
277
	}
278 279

	return 0;
280 281
}

282
static void read_counters(bool close_counters)
283 284 285
{
	struct perf_evsel *counter;

286
	evlist__for_each(evsel_list, counter) {
287
		if (read_counter(counter))
288
			pr_debug("failed to read counter %s\n", counter->name);
289

290
		if (perf_stat_process_counter(&stat_config, counter))
291
			pr_warning("failed to process counter %s\n", counter->name);
292

293
		if (close_counters) {
294 295
			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
					     thread_map__nr(evsel_list->threads));
296 297
		}
	}
298 299
}

300
static void process_interval(void)
301 302 303 304
{
	struct timespec ts, rs;

	read_counters(false);
305

306 307 308
	clock_gettime(CLOCK_MONOTONIC, &ts);
	diff_timespec(&rs, &ts, &ref_time);

309
	print_counters(&rs, 0, NULL);
310 311
}

J
Jiri Olsa 已提交
312
static void enable_counters(void)
313
{
J
Jiri Olsa 已提交
314
	if (initial_delay)
315
		usleep(initial_delay * 1000);
J
Jiri Olsa 已提交
316 317 318 319 320 321 322

	/*
	 * We need to enable counters only if:
	 * - we don't have tracee (attaching to task or cpu)
	 * - we have initial delay configured
	 */
	if (!target__none(&target) || initial_delay)
323
		perf_evlist__enable(evsel_list);
324 325
}

326
static volatile int workload_exec_errno;
327 328 329 330 331 332

/*
 * perf_evlist__prepare_workload will send a SIGUSR1
 * if the fork fails, since we asked by setting its
 * want_signal to true.
 */
333 334
static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
					void *ucontext __maybe_unused)
335
{
336
	workload_exec_errno = info->si_value.sival_int;
337 338
}

339
static int perf_stat_synthesize_config(bool is_pipe)
340 341 342
{
	int err;

343 344 345 346 347 348 349 350 351
	if (is_pipe) {
		err = perf_event__synthesize_attrs(NULL, perf_stat.session,
						   process_synthesized_event);
		if (err < 0) {
			pr_err("Couldn't synthesize attrs.\n");
			return err;
		}
	}

352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
						process_synthesized_event,
						NULL);
	if (err < 0) {
		pr_err("Couldn't synthesize thread map.\n");
		return err;
	}

	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
					     process_synthesized_event, NULL);
	if (err < 0) {
		pr_err("Couldn't synthesize thread map.\n");
		return err;
	}

	err = perf_event__synthesize_stat_config(NULL, &stat_config,
						 process_synthesized_event, NULL);
	if (err < 0) {
		pr_err("Couldn't synthesize config.\n");
		return err;
	}

	return 0;
}

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))

static int __store_counter_ids(struct perf_evsel *counter,
			       struct cpu_map *cpus,
			       struct thread_map *threads)
{
	int cpu, thread;

	for (cpu = 0; cpu < cpus->nr; cpu++) {
		for (thread = 0; thread < threads->nr; thread++) {
			int fd = FD(counter, cpu, thread);

			if (perf_evlist__id_add_fd(evsel_list, counter,
						   cpu, thread, fd) < 0)
				return -1;
		}
	}

	return 0;
}

static int store_counter_ids(struct perf_evsel *counter)
{
	struct cpu_map *cpus = counter->cpus;
	struct thread_map *threads = counter->threads;

	if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
		return -ENOMEM;

	return __store_counter_ids(counter, cpus, threads);
}

409
static int __run_perf_stat(int argc, const char **argv)
410
{
411
	int interval = stat_config.interval;
412
	char msg[512];
413
	unsigned long long t0, t1;
414
	struct perf_evsel *counter;
415
	struct timespec ts;
416
	size_t l;
417
	int status = 0;
418
	const bool forks = (argc > 0);
419
	bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
420

421 422 423 424 425 426 427 428
	if (interval) {
		ts.tv_sec  = interval / 1000;
		ts.tv_nsec = (interval % 1000) * 1000000;
	} else {
		ts.tv_sec  = 1;
		ts.tv_nsec = 0;
	}

429
	if (forks) {
430
		if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
431
						  workload_exec_failed_signal) < 0) {
432 433
			perror("failed to prepare workload");
			return -1;
434
		}
435
		child_pid = evsel_list->workload.pid;
436 437
	}

438
	if (group)
439
		perf_evlist__set_leader(evsel_list);
440

441
	evlist__for_each(evsel_list, counter) {
442
		if (create_perf_stat_counter(counter) < 0) {
443 444 445 446
			/*
			 * PPC returns ENXIO for HW counters until 2.6.37
			 * (behavior changed with commit b0a873e).
			 */
447
			if (errno == EINVAL || errno == ENOSYS ||
448 449
			    errno == ENOENT || errno == EOPNOTSUPP ||
			    errno == ENXIO) {
450 451
				if (verbose)
					ui__warning("%s event is not supported by the kernel.\n",
452
						    perf_evsel__name(counter));
453
				counter->supported = false;
454 455 456 457

				if ((counter->leader != counter) ||
				    !(counter->leader->nr_members > 1))
					continue;
458
			}
459

460 461 462 463
			perf_evsel__open_strerror(counter, &target,
						  errno, msg, sizeof(msg));
			ui__error("%s\n", msg);

464 465
			if (child_pid != -1)
				kill(child_pid, SIGTERM);
466

467 468
			return -1;
		}
469
		counter->supported = true;
470 471 472 473

		l = strlen(counter->unit);
		if (l > unit_width)
			unit_width = l;
474 475 476

		if (STAT_RECORD && store_counter_ids(counter))
			return -1;
477
	}
478

479 480 481
	if (perf_evlist__apply_filters(evsel_list, &counter)) {
		error("failed to set filter \"%s\" on event %s with %d (%s)\n",
			counter->filter, perf_evsel__name(counter), errno,
482
			strerror_r(errno, msg, sizeof(msg)));
483 484 485
		return -1;
	}

J
Jiri Olsa 已提交
486 487 488
	if (STAT_RECORD) {
		int err, fd = perf_data_file__fd(&perf_stat.file);

489 490 491 492 493 494 495
		if (is_pipe) {
			err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file));
		} else {
			err = perf_session__write_header(perf_stat.session, evsel_list,
							 fd, false);
		}

J
Jiri Olsa 已提交
496 497
		if (err < 0)
			return err;
498

499
		err = perf_stat_synthesize_config(is_pipe);
500 501
		if (err < 0)
			return err;
J
Jiri Olsa 已提交
502 503
	}

504 505 506 507
	/*
	 * Enable counters and exec the command:
	 */
	t0 = rdclock();
508
	clock_gettime(CLOCK_MONOTONIC, &ref_time);
509

510
	if (forks) {
511
		perf_evlist__start_workload(evsel_list);
J
Jiri Olsa 已提交
512
		enable_counters();
513

514 515 516
		if (interval) {
			while (!waitpid(child_pid, &status, WNOHANG)) {
				nanosleep(&ts, NULL);
517
				process_interval();
518 519
			}
		}
520
		wait(&status);
521

522 523 524
		if (workload_exec_errno) {
			const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
			pr_err("Workload failed: %s\n", emsg);
525
			return -1;
526
		}
527

528 529
		if (WIFSIGNALED(status))
			psignal(WTERMSIG(status), argv[0]);
530
	} else {
J
Jiri Olsa 已提交
531
		enable_counters();
532 533 534
		while (!done) {
			nanosleep(&ts, NULL);
			if (interval)
535
				process_interval();
536
		}
537
	}
538 539 540

	t1 = rdclock();

541
	update_stats(&walltime_nsecs_stats, t1 - t0);
542

543
	read_counters(true);
544

545 546 547
	return WEXITSTATUS(status);
}

548
static int run_perf_stat(int argc, const char **argv)
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
{
	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;
}

574 575 576
static void print_running(u64 run, u64 ena)
{
	if (csv_output) {
577
		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
578 579 580 581 582
					csv_sep,
					run,
					csv_sep,
					ena ? 100.0 * run / ena : 100.0);
	} else if (run != ena) {
583
		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
584 585 586
	}
}

587 588
static void print_noise_pct(double total, double avg)
{
589
	double pct = rel_stddev_stats(total, avg);
590

591
	if (csv_output)
592
		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
593
	else if (pct)
594
		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
595 596
}

597
static void print_noise(struct perf_evsel *evsel, double avg)
598
{
599
	struct perf_stat_evsel *ps;
600

601 602 603
	if (run_count == 1)
		return;

604
	ps = evsel->priv;
605
	print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
606 607
}

608
static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
I
Ingo Molnar 已提交
609
{
610
	switch (stat_config.aggr_mode) {
611
	case AGGR_CORE:
612
		fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
613 614 615 616 617 618 619 620
			cpu_map__id_to_socket(id),
			csv_output ? 0 : -8,
			cpu_map__id_to_cpu(id),
			csv_sep,
			csv_output ? 0 : 4,
			nr,
			csv_sep);
		break;
621
	case AGGR_SOCKET:
622
		fprintf(stat_config.output, "S%*d%s%*d%s",
623
			csv_output ? 0 : -5,
624
			id,
625 626 627 628
			csv_sep,
			csv_output ? 0 : 4,
			nr,
			csv_sep);
629 630
			break;
	case AGGR_NONE:
631
		fprintf(stat_config.output, "CPU%*d%s",
S
Stephane Eranian 已提交
632
			csv_output ? 0 : -4,
633
			perf_evsel__cpus(evsel)->map[id], csv_sep);
634
		break;
635
	case AGGR_THREAD:
636
		fprintf(stat_config.output, "%*s-%*d%s",
637 638 639 640 641 642
			csv_output ? 0 : 16,
			thread_map__comm(evsel->threads, id),
			csv_output ? 0 : -8,
			thread_map__pid(evsel->threads, id),
			csv_sep);
		break;
643
	case AGGR_GLOBAL:
J
Jiri Olsa 已提交
644
	case AGGR_UNSET:
645 646 647 648 649
	default:
		break;
	}
}

650
static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
651
{
652
	FILE *output = stat_config.output;
653
	double msecs = avg / 1e6;
654
	const char *fmt_v, *fmt_n;
655
	char name[25];
656

657 658 659
	fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
	fmt_n = csv_output ? "%s" : "%-25s";

660
	aggr_printout(evsel, id, nr);
S
Stephane Eranian 已提交
661

662 663
	scnprintf(name, sizeof(name), "%s%s",
		  perf_evsel__name(evsel), csv_output ? "" : " (msec)");
664 665 666 667 668 669 670 671 672

	fprintf(output, fmt_v, msecs, csv_sep);

	if (csv_output)
		fprintf(output, "%s%s", evsel->unit, csv_sep);
	else
		fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep);

	fprintf(output, fmt_n, name);
S
Stephane Eranian 已提交
673

S
Stephane Eranian 已提交
674
	if (evsel->cgrp)
675
		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
I
Ingo Molnar 已提交
676 677
}

678 679
static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
{
680
	FILE *output = stat_config.output;
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	double sc =  evsel->scale;
	const char *fmt;

	if (csv_output) {
		fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
	} else {
		if (big_num)
			fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
		else
			fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
	}

	aggr_printout(evsel, id, nr);

	fprintf(output, fmt, avg, csv_sep);

	if (evsel->unit)
		fprintf(output, "%-*s%s",
			csv_output ? 0 : unit_width,
			evsel->unit, csv_sep);

	fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));

	if (evsel->cgrp)
		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
706
}
707

708 709 710 711 712 713 714 715 716 717 718
static void printout(int id, int nr, struct perf_evsel *counter, double uval)
{
	int cpu = cpu_map__id_to_cpu(id);

	if (stat_config.aggr_mode == AGGR_GLOBAL)
		cpu = 0;

	if (nsec_counter(counter))
		nsec_printout(id, nr, counter, uval);
	else
		abs_printout(id, nr, counter, uval);
719

720 721 722 723
	if (!csv_output && !stat_config.interval)
		perf_stat__print_shadow_stats(stat_config.output, counter,
					      uval, cpu,
					      stat_config.aggr_mode);
724 725
}

726
static void print_aggr(char *prefix)
727
{
728
	FILE *output = stat_config.output;
729
	struct perf_evsel *counter;
730
	int cpu, s, s2, id, nr;
731
	double uval;
732 733
	u64 ena, run, val;

734
	if (!(aggr_map || aggr_get_id))
735 736
		return;

737 738
	for (s = 0; s < aggr_map->nr; s++) {
		id = aggr_map->map[s];
739
		evlist__for_each(evsel_list, counter) {
740 741 742
			val = ena = run = 0;
			nr = 0;
			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
743
				s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
744
				if (s2 != id)
745
					continue;
746 747 748
				val += perf_counts(counter->counts, cpu, 0)->val;
				ena += perf_counts(counter->counts, cpu, 0)->ena;
				run += perf_counts(counter->counts, cpu, 0)->run;
749 750 751 752 753 754
				nr++;
			}
			if (prefix)
				fprintf(output, "%s", prefix);

			if (run == 0 || ena == 0) {
755
				aggr_printout(counter, id, nr);
756

757
				fprintf(output, "%*s%s",
758 759
					csv_output ? 0 : 18,
					counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
760 761 762 763 764 765 766 767
					csv_sep);

				fprintf(output, "%-*s%s",
					csv_output ? 0 : unit_width,
					counter->unit, csv_sep);

				fprintf(output, "%*s",
					csv_output ? 0 : -25,
768
					perf_evsel__name(counter));
769

770 771 772 773
				if (counter->cgrp)
					fprintf(output, "%s%s",
						csv_sep, counter->cgrp->name);

774
				print_running(run, ena);
775 776 777
				fputc('\n', output);
				continue;
			}
778
			uval = val * counter->scale;
779
			printout(id, nr, counter, uval);
780
			if (!csv_output)
781 782
				print_noise(counter, 1.0);

783
			print_running(run, ena);
784 785 786 787 788
			fputc('\n', output);
		}
	}
}

789 790
static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
{
791
	FILE *output = stat_config.output;
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
	int nthreads = thread_map__nr(counter->threads);
	int ncpus = cpu_map__nr(counter->cpus);
	int cpu, thread;
	double uval;

	for (thread = 0; thread < nthreads; thread++) {
		u64 ena = 0, run = 0, val = 0;

		for (cpu = 0; cpu < ncpus; cpu++) {
			val += perf_counts(counter->counts, cpu, thread)->val;
			ena += perf_counts(counter->counts, cpu, thread)->ena;
			run += perf_counts(counter->counts, cpu, thread)->run;
		}

		if (prefix)
			fprintf(output, "%s", prefix);

		uval = val * counter->scale;
810
		printout(thread, 0, counter, uval);
811 812 813 814 815 816 817 818 819

		if (!csv_output)
			print_noise(counter, 1.0);

		print_running(run, ena);
		fputc('\n', output);
	}
}

820 821
/*
 * Print out the results of a single counter:
822
 * aggregated counts in system-wide mode
823
 */
824
static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
825
{
826
	FILE *output = stat_config.output;
827
	struct perf_stat_evsel *ps = counter->priv;
828
	double avg = avg_stats(&ps->res_stats[0]);
829
	int scaled = counter->counts->scaled;
830
	double uval;
831 832 833 834
	double avg_enabled, avg_running;

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

836 837 838
	if (prefix)
		fprintf(output, "%s", prefix);

839
	if (scaled == -1 || !counter->supported) {
840
		fprintf(output, "%*s%s",
S
Stephane Eranian 已提交
841
			csv_output ? 0 : 18,
842
			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
843 844 845 846 847 848
			csv_sep);
		fprintf(output, "%-*s%s",
			csv_output ? 0 : unit_width,
			counter->unit, csv_sep);
		fprintf(output, "%*s",
			csv_output ? 0 : -25,
849
			perf_evsel__name(counter));
S
Stephane Eranian 已提交
850 851

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

854
		print_running(avg_running, avg_enabled);
855
		fputc('\n', output);
856 857
		return;
	}
858

859
	uval = avg * counter->scale;
860
	printout(-1, 0, counter, uval);
861

862 863
	print_noise(counter, avg);

864
	print_running(avg_running, avg_enabled);
865
	fprintf(output, "\n");
866 867
}

868 869 870 871
/*
 * Print out the results of a single counter:
 * does not use aggregated count in system-wide
 */
872
static void print_counter(struct perf_evsel *counter, char *prefix)
873
{
874
	FILE *output = stat_config.output;
875
	u64 ena, run, val;
876
	double uval;
877 878
	int cpu;

Y
Yan, Zheng 已提交
879
	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
880 881 882
		val = perf_counts(counter->counts, cpu, 0)->val;
		ena = perf_counts(counter->counts, cpu, 0)->ena;
		run = perf_counts(counter->counts, cpu, 0)->run;
883 884 885 886

		if (prefix)
			fprintf(output, "%s", prefix);

887
		if (run == 0 || ena == 0) {
888
			fprintf(output, "CPU%*d%s%*s%s",
S
Stephane Eranian 已提交
889
				csv_output ? 0 : -4,
Y
Yan, Zheng 已提交
890
				perf_evsel__cpus(counter)->map[cpu], csv_sep,
S
Stephane Eranian 已提交
891
				csv_output ? 0 : 18,
892
				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
893 894 895 896 897 898 899 900 901
				csv_sep);

				fprintf(output, "%-*s%s",
					csv_output ? 0 : unit_width,
					counter->unit, csv_sep);

				fprintf(output, "%*s",
					csv_output ? 0 : -25,
					perf_evsel__name(counter));
902

S
Stephane Eranian 已提交
903
			if (counter->cgrp)
904 905
				fprintf(output, "%s%s",
					csv_sep, counter->cgrp->name);
S
Stephane Eranian 已提交
906

907
			print_running(run, ena);
908
			fputc('\n', output);
909 910 911
			continue;
		}

912
		uval = val * counter->scale;
913
		printout(cpu, 0, counter, uval);
914
		if (!csv_output)
S
Stephane Eranian 已提交
915
			print_noise(counter, 1.0);
916
		print_running(run, ena);
917

918
		fputc('\n', output);
919 920 921
	}
}

922 923
static void print_interval(char *prefix, struct timespec *ts)
{
924
	FILE *output = stat_config.output;
925 926 927 928 929
	static int num_print_interval;

	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);

	if (num_print_interval == 0 && !csv_output) {
930
		switch (stat_config.aggr_mode) {
931 932 933 934 935 936 937 938 939
		case AGGR_SOCKET:
			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
			break;
		case AGGR_CORE:
			fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
			break;
		case AGGR_NONE:
			fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
			break;
940 941 942
		case AGGR_THREAD:
			fprintf(output, "#           time             comm-pid                  counts %*s events\n", unit_width, "unit");
			break;
943 944 945
		case AGGR_GLOBAL:
		default:
			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
J
Jiri Olsa 已提交
946 947
		case AGGR_UNSET:
			break;
948 949 950 951 952 953 954 955
		}
	}

	if (++num_print_interval == 25)
		num_print_interval = 0;
}

static void print_header(int argc, const char **argv)
956
{
957
	FILE *output = stat_config.output;
958
	int i;
959

960 961
	fflush(stdout);

S
Stephane Eranian 已提交
962
	if (!csv_output) {
963 964
		fprintf(output, "\n");
		fprintf(output, " Performance counter stats for ");
965 966 967 968
		if (target.system_wide)
			fprintf(output, "\'system wide");
		else if (target.cpu_list)
			fprintf(output, "\'CPU(s) %s", target.cpu_list);
969
		else if (!target__has_task(&target)) {
970
			fprintf(output, "\'%s", argv[0]);
S
Stephane Eranian 已提交
971
			for (i = 1; i < argc; i++)
972
				fprintf(output, " %s", argv[i]);
973 974
		} else if (target.pid)
			fprintf(output, "process id \'%s", target.pid);
S
Stephane Eranian 已提交
975
		else
976
			fprintf(output, "thread id \'%s", target.tid);
I
Ingo Molnar 已提交
977

978
		fprintf(output, "\'");
S
Stephane Eranian 已提交
979
		if (run_count > 1)
980 981
			fprintf(output, " (%d runs)", run_count);
		fprintf(output, ":\n\n");
S
Stephane Eranian 已提交
982
	}
983 984 985 986
}

static void print_footer(void)
{
987 988
	FILE *output = stat_config.output;

989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
	if (!null_run)
		fprintf(output, "\n");
	fprintf(output, " %17.9f seconds time elapsed",
			avg_stats(&walltime_nsecs_stats)/1e9);
	if (run_count > 1) {
		fprintf(output, "                                        ");
		print_noise_pct(stddev_stats(&walltime_nsecs_stats),
				avg_stats(&walltime_nsecs_stats));
	}
	fprintf(output, "\n\n");
}

static void print_counters(struct timespec *ts, int argc, const char **argv)
{
1003
	int interval = stat_config.interval;
1004 1005 1006
	struct perf_evsel *counter;
	char buf[64], *prefix = NULL;

1007 1008 1009 1010
	/* Do not print anything if we record to the pipe. */
	if (STAT_RECORD && perf_stat.file.is_pipe)
		return;

1011 1012 1013 1014
	if (interval)
		print_interval(prefix = buf, ts);
	else
		print_header(argc, argv);
1015

1016
	switch (stat_config.aggr_mode) {
1017
	case AGGR_CORE:
1018
	case AGGR_SOCKET:
1019
		print_aggr(prefix);
1020
		break;
1021 1022 1023 1024
	case AGGR_THREAD:
		evlist__for_each(evsel_list, counter)
			print_aggr_thread(counter, prefix);
		break;
1025
	case AGGR_GLOBAL:
1026
		evlist__for_each(evsel_list, counter)
1027
			print_counter_aggr(counter, prefix);
1028 1029
		break;
	case AGGR_NONE:
1030
		evlist__for_each(evsel_list, counter)
1031
			print_counter(counter, prefix);
1032
		break;
J
Jiri Olsa 已提交
1033
	case AGGR_UNSET:
1034 1035
	default:
		break;
1036
	}
1037

1038 1039 1040
	if (!interval && !csv_output)
		print_footer();

1041
	fflush(stat_config.output);
1042 1043
}

1044 1045
static volatile int signr = -1;

1046
static void skip_signal(int signo)
1047
{
1048
	if ((child_pid == -1) || stat_config.interval)
1049 1050
		done = 1;

1051
	signr = signo;
1052 1053 1054 1055 1056 1057 1058
	/*
	 * render child_pid harmless
	 * won't send SIGTERM to a random
	 * process in case of race condition
	 * and fast PID recycling
	 */
	child_pid = -1;
1059 1060 1061 1062
}

static void sig_atexit(void)
{
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
	sigset_t set, oset;

	/*
	 * avoid race condition with SIGCHLD handler
	 * in skip_signal() which is modifying child_pid
	 * goal is to avoid send SIGTERM to a random
	 * process
	 */
	sigemptyset(&set);
	sigaddset(&set, SIGCHLD);
	sigprocmask(SIG_BLOCK, &set, &oset);

1075 1076 1077
	if (child_pid != -1)
		kill(child_pid, SIGTERM);

1078 1079
	sigprocmask(SIG_SETMASK, &oset, NULL);

1080 1081 1082 1083 1084
	if (signr == -1)
		return;

	signal(signr, SIG_DFL);
	kill(getpid(), signr);
1085 1086
}

1087 1088
static int stat__set_big_num(const struct option *opt __maybe_unused,
			     const char *s __maybe_unused, int unset)
S
Stephane Eranian 已提交
1089 1090 1091 1092 1093
{
	big_num_opt = unset ? 0 : 1;
	return 0;
}

J
Jiri Olsa 已提交
1094 1095 1096 1097 1098 1099 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 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
static const struct option stat_options[] = {
	OPT_BOOLEAN('T', "transaction", &transaction_run,
		    "hardware transaction statistics"),
	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", &stat_config.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, forever: 0)"),
	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_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
		    "disable CPU count aggregation", AGGR_NONE),
	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"),
	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"),
	OPT_UINTEGER('I', "interval-print", &stat_config.interval,
		    "print counts at regular interval in ms (>= 10)"),
	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
		     "aggregate counts per processor socket", AGGR_SOCKET),
	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
		     "aggregate counts per physical processor core", AGGR_CORE),
	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
		     "aggregate counts per thread", AGGR_THREAD),
	OPT_UINTEGER('D', "delay", &initial_delay,
		     "ms to wait before starting measurement after program start"),
	OPT_END()
};

1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
static int perf_stat__get_socket(struct cpu_map *map, int cpu)
{
	return cpu_map__get_socket(map, cpu, NULL);
}

static int perf_stat__get_core(struct cpu_map *map, int cpu)
{
	return cpu_map__get_core(map, cpu, NULL);
}

1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
static int cpu_map__get_max(struct cpu_map *map)
{
	int i, max = -1;

	for (i = 0; i < map->nr; i++) {
		if (map->map[i] > max)
			max = map->map[i];
	}

	return max;
}

static struct cpu_map *cpus_aggr_map;

static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
{
	int cpu;

	if (idx >= map->nr)
		return -1;

	cpu = map->map[idx];

	if (cpus_aggr_map->map[cpu] == -1)
		cpus_aggr_map->map[cpu] = get_id(map, idx);

	return cpus_aggr_map->map[cpu];
}

static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
{
	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
}

static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
{
	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
}

1204 1205
static int perf_stat_init_aggr_mode(void)
{
1206 1207
	int nr;

1208
	switch (stat_config.aggr_mode) {
1209 1210 1211 1212 1213
	case AGGR_SOCKET:
		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
			perror("cannot build socket map");
			return -1;
		}
1214
		aggr_get_id = perf_stat__get_socket_cached;
1215
		break;
1216 1217 1218 1219 1220
	case AGGR_CORE:
		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
			perror("cannot build core map");
			return -1;
		}
1221
		aggr_get_id = perf_stat__get_core_cached;
1222
		break;
1223 1224
	case AGGR_NONE:
	case AGGR_GLOBAL:
1225
	case AGGR_THREAD:
J
Jiri Olsa 已提交
1226
	case AGGR_UNSET:
1227 1228 1229
	default:
		break;
	}
1230 1231 1232 1233 1234 1235 1236 1237 1238

	/*
	 * The evsel_list->cpus is the base we operate on,
	 * taking the highest cpu number to be the size of
	 * the aggregation translate cpumap.
	 */
	nr = cpu_map__get_max(evsel_list->cpus);
	cpus_aggr_map = cpu_map__empty_new(nr + 1);
	return cpus_aggr_map ? 0 : -ENOMEM;
1239 1240
}

1241 1242 1243 1244 1245 1246 1247 1248
static void perf_stat__exit_aggr_mode(void)
{
	cpu_map__put(aggr_map);
	cpu_map__put(cpus_aggr_map);
	aggr_map = NULL;
	cpus_aggr_map = NULL;
}

1249 1250 1251 1252 1253 1254
/*
 * 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)
{
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
	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)				},
};

1362 1363 1364 1365
	/* Set attrs if no event is selected and !null_run: */
	if (null_run)
		return 0;

1366 1367 1368 1369
	if (transaction_run) {
		int err;
		if (pmu_have_event("cpu", "cycles-ct") &&
		    pmu_have_event("cpu", "el-start"))
1370
			err = parse_events(evsel_list, transaction_attrs, NULL);
1371
		else
1372 1373
			err = parse_events(evsel_list, transaction_limited_attrs, NULL);
		if (err) {
1374 1375 1376 1377 1378 1379
			fprintf(stderr, "Cannot set up transaction events\n");
			return -1;
		}
		return 0;
	}

1380
	if (!evsel_list->nr_entries) {
1381
		if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
1382
			return -1;
1383 1384 1385 1386 1387 1388 1389 1390
	}

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

	if (detailed_run <  1)
		return 0;

	/* Append detailed run extra attributes: */
1391
	if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
1392
		return -1;
1393 1394 1395 1396 1397

	if (detailed_run < 2)
		return 0;

	/* Append very detailed run extra attributes: */
1398
	if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
1399
		return -1;
1400 1401 1402 1403 1404

	if (detailed_run < 3)
		return 0;

	/* Append very, very detailed run extra attributes: */
1405
	return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1406 1407
}

J
Jiri Olsa 已提交
1408 1409 1410 1411 1412
static const char * const recort_usage[] = {
	"perf stat record [<options>]",
	NULL,
};

1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
static void init_features(struct perf_session *session)
{
	int feat;

	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
		perf_header__set_feat(&session->header, feat);

	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
}

J
Jiri Olsa 已提交
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
static int __cmd_record(int argc, const char **argv)
{
	struct perf_session *session;
	struct perf_data_file *file = &perf_stat.file;

	argc = parse_options(argc, argv, stat_options, record_usage,
			     PARSE_OPT_STOP_AT_NON_OPTION);

	if (output_name)
		file->path = output_name;

	session = perf_session__new(file, false, NULL);
	if (session == NULL) {
		pr_err("Perf session creation failed.\n");
		return -1;
	}

1443 1444
	init_features(session);

J
Jiri Olsa 已提交
1445 1446 1447 1448 1449 1450
	session->evlist   = evsel_list;
	perf_stat.session = session;
	perf_stat.record  = true;
	return argc;
}

1451
int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1452
{
1453 1454 1455 1456
	const char * const stat_usage[] = {
		"perf stat [<options>] [<command>]",
		NULL
	};
1457
	int status = -EINVAL, run_idx;
1458
	const char *mode;
1459
	FILE *output = stderr;
1460
	unsigned int interval;
J
Jiri Olsa 已提交
1461
	const char * const stat_subcommands[] = { "record" };
1462

1463 1464
	setlocale(LC_ALL, "");

1465
	evsel_list = perf_evlist__new();
1466 1467 1468
	if (evsel_list == NULL)
		return -ENOMEM;

J
Jiri Olsa 已提交
1469 1470 1471 1472 1473 1474 1475 1476 1477
	argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
					(const char **) stat_usage,
					PARSE_OPT_STOP_AT_NON_OPTION);

	if (argc && !strncmp(argv[0], "rec", 3)) {
		argc = __cmd_record(argc, argv);
		if (argc < 0)
			return -1;
	}
S
Stephane Eranian 已提交
1478

1479 1480
	interval = stat_config.interval;

J
Jiri Olsa 已提交
1481 1482 1483 1484
	/*
	 * For record command the -o is already taken care of.
	 */
	if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
1485 1486
		output = NULL;

1487 1488
	if (output_name && output_fd) {
		fprintf(stderr, "cannot use both --output and --log-fd\n");
J
Jiri Olsa 已提交
1489 1490
		parse_options_usage(stat_usage, stat_options, "o", 1);
		parse_options_usage(NULL, stat_options, "log-fd", 0);
1491
		goto out;
1492
	}
1493 1494 1495

	if (output_fd < 0) {
		fprintf(stderr, "argument to --log-fd must be a > 0\n");
J
Jiri Olsa 已提交
1496
		parse_options_usage(stat_usage, stat_options, "log-fd", 0);
1497
		goto out;
1498 1499
	}

1500 1501 1502 1503 1504 1505 1506
	if (!output) {
		struct timespec tm;
		mode = append_file ? "a" : "w";

		output = fopen(output_name, mode);
		if (!output) {
			perror("failed to create output file");
1507
			return -1;
1508 1509 1510
		}
		clock_gettime(CLOCK_REALTIME, &tm);
		fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1511
	} else if (output_fd > 0) {
1512 1513 1514 1515 1516 1517
		mode = append_file ? "a" : "w";
		output = fdopen(output_fd, mode);
		if (!output) {
			perror("Failed opening logfd");
			return -errno;
		}
1518 1519
	}

1520 1521
	stat_config.output = output;

1522
	if (csv_sep) {
S
Stephane Eranian 已提交
1523
		csv_output = true;
1524 1525 1526
		if (!strcmp(csv_sep, "\\t"))
			csv_sep = "\t";
	} else
S
Stephane Eranian 已提交
1527 1528 1529 1530 1531 1532
		csv_sep = DEFAULT_SEPARATOR;

	/*
	 * let the spreadsheet do the pretty-printing
	 */
	if (csv_output) {
J
Jim Cromie 已提交
1533
		/* User explicitly passed -B? */
S
Stephane Eranian 已提交
1534 1535
		if (big_num_opt == 1) {
			fprintf(stderr, "-B option not supported with -x\n");
J
Jiri Olsa 已提交
1536 1537
			parse_options_usage(stat_usage, stat_options, "B", 1);
			parse_options_usage(NULL, stat_options, "x", 1);
1538
			goto out;
S
Stephane Eranian 已提交
1539 1540 1541 1542 1543
		} else /* Nope, so disable big number formatting */
			big_num = false;
	} else if (big_num_opt == 0) /* User passed --no-big-num */
		big_num = false;

1544
	if (!argc && target__none(&target))
J
Jiri Olsa 已提交
1545
		usage_with_options(stat_usage, stat_options);
1546

1547
	if (run_count < 0) {
1548
		pr_err("Run count must be a positive number\n");
J
Jiri Olsa 已提交
1549
		parse_options_usage(stat_usage, stat_options, "r", 1);
1550
		goto out;
1551 1552 1553 1554
	} else if (run_count == 0) {
		forever = true;
		run_count = 1;
	}
1555

1556
	if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
1557 1558
		fprintf(stderr, "The --per-thread option is only available "
			"when monitoring via -p -t options.\n");
J
Jiri Olsa 已提交
1559 1560
		parse_options_usage(NULL, stat_options, "p", 1);
		parse_options_usage(NULL, stat_options, "t", 1);
1561 1562 1563 1564 1565 1566 1567
		goto out;
	}

	/*
	 * no_aggr, cgroup are for system-wide only
	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
	 */
1568 1569
	if (((stat_config.aggr_mode != AGGR_GLOBAL &&
	      stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
1570
	    !target__has_cpu(&target)) {
S
Stephane Eranian 已提交
1571 1572 1573
		fprintf(stderr, "both cgroup and no-aggregation "
			"modes only available in system-wide mode\n");

J
Jiri Olsa 已提交
1574 1575 1576
		parse_options_usage(stat_usage, stat_options, "G", 1);
		parse_options_usage(NULL, stat_options, "A", 1);
		parse_options_usage(NULL, stat_options, "a", 1);
1577
		goto out;
1578 1579
	}

1580 1581
	if (add_default_attributes())
		goto out;
1582

1583
	target__validate(&target);
1584

1585
	if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1586
		if (target__has_task(&target)) {
1587
			pr_err("Problems finding threads of monitor\n");
J
Jiri Olsa 已提交
1588 1589
			parse_options_usage(stat_usage, stat_options, "p", 1);
			parse_options_usage(NULL, stat_options, "t", 1);
1590
		} else if (target__has_cpu(&target)) {
1591
			perror("failed to parse CPUs map");
J
Jiri Olsa 已提交
1592 1593
			parse_options_usage(stat_usage, stat_options, "C", 1);
			parse_options_usage(NULL, stat_options, "a", 1);
1594 1595
		}
		goto out;
1596
	}
1597 1598 1599 1600 1601

	/*
	 * Initialize thread_map with comm names,
	 * so we could print it out on output.
	 */
1602
	if (stat_config.aggr_mode == AGGR_THREAD)
1603 1604
		thread_map__read_comms(evsel_list->threads);

1605
	if (interval && interval < 100) {
1606 1607
		if (interval < 10) {
			pr_err("print interval must be >= 10ms\n");
J
Jiri Olsa 已提交
1608
			parse_options_usage(stat_usage, stat_options, "I", 1);
1609 1610 1611 1612 1613
			goto out;
		} else
			pr_warning("print interval < 100ms. "
				   "The overhead percentage could be high in some cases. "
				   "Please proceed with caution.\n");
1614
	}
1615

1616
	if (perf_evlist__alloc_stats(evsel_list, interval))
1617
		goto out;
1618

1619
	if (perf_stat_init_aggr_mode())
1620
		goto out;
1621

I
Ingo Molnar 已提交
1622 1623 1624 1625 1626 1627
	/*
	 * 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:
	 */
1628
	atexit(sig_atexit);
1629 1630
	if (!forever)
		signal(SIGINT,  skip_signal);
1631
	signal(SIGCHLD, skip_signal);
I
Ingo Molnar 已提交
1632 1633 1634
	signal(SIGALRM, skip_signal);
	signal(SIGABRT, skip_signal);

1635
	status = 0;
1636
	for (run_idx = 0; forever || run_idx < run_count; run_idx++) {
1637
		if (run_count != 1 && verbose)
1638 1639
			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
				run_idx + 1);
I
Ingo Molnar 已提交
1640

1641
		status = run_perf_stat(argc, argv);
1642
		if (forever && status != -1) {
1643
			print_counters(NULL, argc, argv);
1644
			perf_stat__reset_stats();
1645
		}
1646 1647
	}

1648
	if (!forever && status != -1 && !interval)
1649
		print_counters(NULL, argc, argv);
1650

J
Jiri Olsa 已提交
1651 1652 1653 1654 1655 1656 1657 1658
	if (STAT_RECORD) {
		/*
		 * We synthesize the kernel mmap record just so that older tools
		 * don't emit warnings about not being able to resolve symbols
		 * due to /proc/sys/kernel/kptr_restrict settings and instear provide
		 * a saner message about no samples being in the perf.data file.
		 *
		 * This also serves to suppress a warning about f_header.data.size == 0
1659 1660 1661 1662
		 * in header.c at the moment 'perf stat record' gets introduced, which
		 * is not really needed once we start adding the stat specific PERF_RECORD_
		 * records, but the need to suppress the kptr_restrict messages in older
		 * tools remain  -acme
J
Jiri Olsa 已提交
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
		 */
		int fd = perf_data_file__fd(&perf_stat.file);
		int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
							     process_synthesized_event,
							     &perf_stat.session->machines.host);
		if (err) {
			pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
				   "older tools may produce warnings about this file\n.");
		}

1673 1674 1675 1676
		if (!perf_stat.file.is_pipe) {
			perf_stat.session->header.data_size += perf_stat.bytes_written;
			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
		}
J
Jiri Olsa 已提交
1677 1678 1679 1680

		perf_session__delete(perf_stat.session);
	}

1681
	perf_stat__exit_aggr_mode();
1682
	perf_evlist__free_stats(evsel_list);
1683 1684
out:
	perf_evlist__delete(evsel_list);
1685
	return status;
1686
}