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

10
   $ perf stat ./hackbench 10
11

12
  Time: 0.118
13

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

16 17 18 19 20 21 22 23 24 25 26 27 28
       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
29

30
 *
31
 * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
32 33 34 35 36 37 38 39
 *
 * 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>
40
 *   Jaswinder Singh Rajput <jaswinder@kernel.org>
41 42
 */

43
#include "builtin.h"
44
#include "perf.h"
45
#include "util/cgroup.h"
46
#include <subcmd/parse-options.h>
47
#include "util/parse-events.h"
48
#include "util/pmu.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_map.h"
58
#include "util/counts.h"
K
Kan Liang 已提交
59
#include "util/topdown.h"
J
Jiri Olsa 已提交
60
#include "util/session.h"
J
Jiri Olsa 已提交
61
#include "util/tool.h"
62
#include "util/string2.h"
63
#include "util/metricgroup.h"
64
#include "util/synthetic-events.h"
65
#include "util/target.h"
66
#include "util/time-utils.h"
67
#include "util/top.h"
68
#include "util/affinity.h"
69
#include "util/pfm.h"
70
#include "util/bpf_counter.h"
J
Jiri Olsa 已提交
71
#include "asm/bug.h"
72

73
#include <linux/time64.h>
74
#include <linux/zalloc.h>
75
#include <api/fs/fs.h>
76
#include <errno.h>
77
#include <signal.h>
78
#include <stdlib.h>
79
#include <sys/prctl.h>
80
#include <inttypes.h>
81
#include <locale.h>
82
#include <math.h>
83 84
#include <sys/types.h>
#include <sys/stat.h>
85
#include <sys/wait.h>
86
#include <unistd.h>
87 88
#include <sys/time.h>
#include <sys/resource.h>
89
#include <linux/err.h>
90

91
#include <linux/ctype.h>
92
#include <perf/evlist.h>
93

S
Stephane Eranian 已提交
94
#define DEFAULT_SEPARATOR	" "
95
#define FREEZE_ON_SMI_PATH	"devices/cpu/freeze_on_smi"
S
Stephane Eranian 已提交
96

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

99
/* Default events used for perf stat -T */
100 101
static const char *transaction_attrs = {
	"task-clock,"
102 103 104 105 106 107 108 109 110 111 112
	"{"
	"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. */
113 114
static const char * transaction_limited_attrs = {
	"task-clock,"
115 116 117 118 119 120 121 122
	"{"
	"instructions,"
	"cycles,"
	"cpu/cycles-t/,"
	"cpu/tx-start/"
	"}"
};

123 124 125 126 127 128 129 130 131
static const char * topdown_attrs[] = {
	"topdown-total-slots",
	"topdown-slots-retired",
	"topdown-recovery-bubbles",
	"topdown-fetch-bubbles",
	"topdown-slots-issued",
	NULL,
};

132 133 134 135 136 137 138 139 140
static const char *topdown_metric_attrs[] = {
	"slots",
	"topdown-retiring",
	"topdown-bad-spec",
	"topdown-fe-bound",
	"topdown-be-bound",
	NULL,
};

K
Kan Liang 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153
static const char *topdown_metric_L2_attrs[] = {
	"slots",
	"topdown-retiring",
	"topdown-bad-spec",
	"topdown-fe-bound",
	"topdown-be-bound",
	"topdown-heavy-ops",
	"topdown-br-mispredict",
	"topdown-fetch-lat",
	"topdown-mem-bound",
	NULL,
};

154 155 156 157 158 159 160 161
static const char *smi_cost_attrs = {
	"{"
	"msr/aperf/,"
	"msr/smi/,"
	"cycles"
	"}"
};

162
static struct evlist	*evsel_list;
163

164
static struct target target = {
165 166
	.uid	= UINT_MAX,
};
167

168 169
#define METRIC_ONLY_LEN 20

170
static volatile pid_t		child_pid			= -1;
171
static int			detailed_run			=  0;
172
static bool			transaction_run;
173
static bool			topdown_run			= false;
174 175
static bool			smi_cost			= false;
static bool			smi_reset			= false;
S
Stephane Eranian 已提交
176
static int			big_num_opt			=  -1;
177
static bool			group				= false;
178 179 180
static const char		*pre_cmd			= NULL;
static const char		*post_cmd			= NULL;
static bool			sync_run			= false;
181
static bool			forever				= false;
182
static bool			force_metric_only		= false;
183
static struct timespec		ref_time;
J
Jiri Olsa 已提交
184
static bool			append_file;
185
static bool			interval_count;
J
Jiri Olsa 已提交
186 187
static const char		*output_name;
static int			output_fd;
188

J
Jiri Olsa 已提交
189 190
struct perf_stat {
	bool			 record;
191
	struct perf_data	 data;
J
Jiri Olsa 已提交
192 193
	struct perf_session	*session;
	u64			 bytes_written;
J
Jiri Olsa 已提交
194
	struct perf_tool	 tool;
195
	bool			 maps_allocated;
196
	struct perf_cpu_map	*cpus;
197
	struct perf_thread_map *threads;
198
	enum aggr_mode		 aggr_mode;
J
Jiri Olsa 已提交
199 200 201 202 203
};

static struct perf_stat		perf_stat;
#define STAT_RECORD		perf_stat.record

204 205
static volatile int done = 0;

206
static struct perf_stat_config stat_config = {
207 208 209 210 211 212
	.aggr_mode		= AGGR_GLOBAL,
	.scale			= true,
	.unit_width		= 4, /* strlen("unit") */
	.run_count		= 1,
	.metric_only_len	= METRIC_ONLY_LEN,
	.walltime_nsecs_stats	= &walltime_nsecs_stats,
213
	.big_num		= true,
214 215
	.ctl_fd			= -1,
	.ctl_fd_ack		= -1
216 217
};

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
static bool cpus_map_matched(struct evsel *a, struct evsel *b)
{
	if (!a->core.cpus && !b->core.cpus)
		return true;

	if (!a->core.cpus || !b->core.cpus)
		return false;

	if (a->core.cpus->nr != b->core.cpus->nr)
		return false;

	for (int i = 0; i < a->core.cpus->nr; i++) {
		if (a->core.cpus->map[i] != b->core.cpus->map[i])
			return false;
	}

	return true;
}

static void evlist__check_cpu_maps(struct evlist *evlist)
{
	struct evsel *evsel, *pos, *leader;
	char buf[1024];

	evlist__for_each_entry(evlist, evsel) {
		leader = evsel->leader;

		/* Check that leader matches cpus with each member. */
		if (leader == evsel)
			continue;
		if (cpus_map_matched(leader, evsel))
			continue;

		/* If there's mismatch disable the group and warn user. */
		WARN_ONCE(1, "WARNING: grouped events cpus do not match, disabling group:\n");
		evsel__group_desc(leader, buf, sizeof(buf));
		pr_warning("  %s\n", buf);

		if (verbose) {
			cpu_map__snprint(leader->core.cpus, buf, sizeof(buf));
			pr_warning("     %s: %s\n", leader->name, buf);
			cpu_map__snprint(evsel->core.cpus, buf, sizeof(buf));
			pr_warning("     %s: %s\n", evsel->name, buf);
		}

		for_each_group_evsel(pos, leader) {
			pos->leader = pos;
			pos->core.nr_members = 0;
		}
		evsel->leader->core.nr_members = 0;
	}
}

271 272 273 274 275
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) {
276
		r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec;
277 278 279 280 281 282
		r->tv_sec--;
	} else {
		r->tv_nsec = a->tv_nsec - b->tv_nsec ;
	}
}

283 284
static void perf_stat__reset_stats(void)
{
285 286
	int i;

287
	evlist__reset_stats(evsel_list);
288
	perf_stat__reset_shadow_stats();
289 290 291

	for (i = 0; i < stat_config.stats_num; i++)
		perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
292 293
}

294 295 296 297
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 已提交
298
{
299
	if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) {
J
Jiri Olsa 已提交
300 301 302 303
		pr_err("failed to write perf data, error: %m\n");
		return -1;
	}

304
	perf_stat.bytes_written += event->header.size;
J
Jiri Olsa 已提交
305 306 307
	return 0;
}

308
static int write_stat_round_event(u64 tm, u64 type)
309
{
310
	return perf_event__synthesize_stat_round(NULL, tm, type,
311 312 313 314 315 316 317
						 process_synthesized_event,
						 NULL);
}

#define WRITE_STAT_ROUND_EVENT(time, interval) \
	write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)

318
#define SID(e, x, y) xyarray__entry(e->core.sample_id, x, y)
319

320 321
static int evsel__write_stat_event(struct evsel *counter, u32 cpu, u32 thread,
				   struct perf_counts_values *count)
322 323 324 325 326 327 328
{
	struct perf_sample_id *sid = SID(counter, cpu, thread);

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

329
static int read_single_counter(struct evsel *counter, int cpu,
330 331 332 333 334 335 336 337 338 339
			       int thread, struct timespec *rs)
{
	if (counter->tool_event == PERF_TOOL_DURATION_TIME) {
		u64 val = rs->tv_nsec + rs->tv_sec*1000000000ULL;
		struct perf_counts_values *count =
			perf_counts(counter->counts, cpu, thread);
		count->ena = count->run = val;
		count->val = val;
		return 0;
	}
340
	return evsel__read_counter(counter, cpu, thread);
341 342
}

343 344 345 346
/*
 * Read out the results of a single counter:
 * do not aggregate counts across CPUs in system-wide mode
 */
A
Andi Kleen 已提交
347
static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu)
348
{
349
	int nthreads = perf_thread_map__nr(evsel_list->core.threads);
A
Andi Kleen 已提交
350
	int thread;
351

352 353 354
	if (!counter->supported)
		return -ENOENT;

355
	if (counter->core.system_wide)
356 357 358
		nthreads = 1;

	for (thread = 0; thread < nthreads; thread++) {
A
Andi Kleen 已提交
359 360 361 362 363 364
		struct perf_counts_values *count;

		count = perf_counts(counter->counts, cpu, thread);

		/*
		 * The leader's group read loads data into its group members
365
		 * (via evsel__read_counter()) and sets their count->loaded.
A
Andi Kleen 已提交
366 367 368 369 370 371 372 373
		 */
		if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
		    read_single_counter(counter, cpu, thread, rs)) {
			counter->counts->scaled = -1;
			perf_counts(counter->counts, cpu, thread)->ena = 0;
			perf_counts(counter->counts, cpu, thread)->run = 0;
			return -1;
		}
374

A
Andi Kleen 已提交
375
		perf_counts__set_loaded(counter->counts, cpu, thread, false);
376

A
Andi Kleen 已提交
377
		if (STAT_RECORD) {
378
			if (evsel__write_stat_event(counter, cpu, thread, count)) {
A
Andi Kleen 已提交
379 380
				pr_err("failed to write stat event\n");
				return -1;
381
			}
A
Andi Kleen 已提交
382
		}
383

A
Andi Kleen 已提交
384 385 386
		if (verbose > 1) {
			fprintf(stat_config.output,
				"%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
387
					evsel__name(counter),
A
Andi Kleen 已提交
388 389
					cpu,
					count->val, count->ena, count->run);
390
		}
391
	}
392 393

	return 0;
394 395
}

396
static int read_affinity_counters(struct timespec *rs)
397
{
398
	struct evsel *counter;
A
Andi Kleen 已提交
399 400 401 402
	struct affinity affinity;
	int i, ncpus, cpu;

	if (affinity__setup(&affinity) < 0)
403
		return -1;
A
Andi Kleen 已提交
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422

	ncpus = perf_cpu_map__nr(evsel_list->core.all_cpus);
	if (!target__has_cpu(&target) || target__has_per_thread(&target))
		ncpus = 1;
	evlist__for_each_cpu(evsel_list, i, cpu) {
		if (i >= ncpus)
			break;
		affinity__set(&affinity, cpu);

		evlist__for_each_entry(evsel_list, counter) {
			if (evsel__cpu_iter_skip(counter, cpu))
				continue;
			if (!counter->err) {
				counter->err = read_counter_cpu(counter, rs,
								counter->cpu_iter - 1);
			}
		}
	}
	affinity__cleanup(&affinity);
423 424 425
	return 0;
}

426 427 428 429 430 431 432 433 434 435 436 437 438
static int read_bpf_map_counters(void)
{
	struct evsel *counter;
	int err;

	evlist__for_each_entry(evsel_list, counter) {
		err = bpf_counter__read(counter);
		if (err)
			return err;
	}
	return 0;
}

439 440 441
static void read_counters(struct timespec *rs)
{
	struct evsel *counter;
442
	int err;
443

444 445 446 447 448 449 450 451
	if (!stat_config.stop_read_counter) {
		if (target__has_bpf(&target))
			err = read_bpf_map_counters();
		else
			err = read_affinity_counters(rs);
		if (err < 0)
			return;
	}
452

453
	evlist__for_each_entry(evsel_list, counter) {
A
Andi Kleen 已提交
454
		if (counter->err)
455
			pr_debug("failed to read counter %s\n", counter->name);
A
Andi Kleen 已提交
456
		if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))
457
			pr_warning("failed to process counter %s\n", counter->name);
A
Andi Kleen 已提交
458
		counter->err = 0;
459
	}
460 461
}

462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
static int runtime_stat_new(struct perf_stat_config *config, int nthreads)
{
	int i;

	config->stats = calloc(nthreads, sizeof(struct runtime_stat));
	if (!config->stats)
		return -1;

	config->stats_num = nthreads;

	for (i = 0; i < nthreads; i++)
		runtime_stat__init(&config->stats[i]);

	return 0;
}

static void runtime_stat_delete(struct perf_stat_config *config)
{
	int i;

	if (!config->stats)
		return;

	for (i = 0; i < config->stats_num; i++)
		runtime_stat__exit(&config->stats[i]);

	zfree(&config->stats);
}

static void runtime_stat_reset(struct perf_stat_config *config)
{
	int i;

	if (!config->stats)
		return;

	for (i = 0; i < config->stats_num; i++)
		perf_stat__reset_shadow_per_stat(&config->stats[i]);
}

502
static void process_interval(void)
503 504 505
{
	struct timespec ts, rs;

506 507 508
	clock_gettime(CLOCK_MONOTONIC, &ts);
	diff_timespec(&rs, &ts, &ref_time);

509
	perf_stat__reset_shadow_per_stat(&rt_stat);
510
	runtime_stat_reset(&stat_config);
511 512
	read_counters(&rs);

513
	if (STAT_RECORD) {
514
		if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL))
515 516 517
			pr_err("failed to write stat round event\n");
	}

518
	init_stats(&walltime_nsecs_stats);
519
	update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000ULL);
520
	print_counters(&rs, 0, NULL);
521 522
}

523 524 525 526 527 528 529 530 531 532
static bool handle_interval(unsigned int interval, int *times)
{
	if (interval) {
		process_interval();
		if (interval_count && !(--(*times)))
			return true;
	}
	return false;
}

533
static int enable_counters(void)
534
{
535 536 537 538 539 540 541 542 543 544 545
	struct evsel *evsel;
	int err;

	if (target__has_bpf(&target)) {
		evlist__for_each_entry(evsel_list, evsel) {
			err = bpf_counter__enable(evsel);
			if (err)
				return err;
		}
	}

546 547
	if (stat_config.initial_delay < 0) {
		pr_info(EVLIST_DISABLED_MSG);
548
		return 0;
549 550 551 552
	}

	if (stat_config.initial_delay > 0) {
		pr_info(EVLIST_DISABLED_MSG);
553
		usleep(stat_config.initial_delay * USEC_PER_MSEC);
554
	}
J
Jiri Olsa 已提交
555 556 557 558 559 560

	/*
	 * We need to enable counters only if:
	 * - we don't have tracee (attaching to task or cpu)
	 * - we have initial delay configured
	 */
561
	if (!target__none(&target) || stat_config.initial_delay) {
562
		evlist__enable(evsel_list);
563 564 565
		if (stat_config.initial_delay > 0)
			pr_info(EVLIST_ENABLED_MSG);
	}
566
	return 0;
567 568
}

569 570 571 572 573 574 575 576
static void disable_counters(void)
{
	/*
	 * If we don't have tracee (attaching to task or cpu), counters may
	 * still be running. To get accurate group ratios, we must stop groups
	 * from counting before reading their constituent counters.
	 */
	if (!target__none(&target))
577
		evlist__disable(evsel_list);
578 579
}

580
static volatile int workload_exec_errno;
581 582

/*
583
 * evlist__prepare_workload will send a SIGUSR1
584 585 586
 * if the fork fails, since we asked by setting its
 * want_signal to true.
 */
587 588
static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
					void *ucontext __maybe_unused)
589
{
590
	workload_exec_errno = info->si_value.sival_int;
591 592
}

593
static bool evsel__should_store_id(struct evsel *counter)
594
{
595
	return STAT_RECORD || counter->core.attr.read_format & PERF_FORMAT_ID;
596 597
}

598
static bool is_target_alive(struct target *_target,
599
			    struct perf_thread_map *threads)
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
{
	struct stat st;
	int i;

	if (!target__has_task(_target))
		return true;

	for (i = 0; i < threads->nr; i++) {
		char path[PATH_MAX];

		scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),
			  threads->map[i].pid);

		if (!stat(path, &st))
			return true;
	}

	return false;
}

620 621 622 623 624 625 626 627 628 629 630 631 632 633
static void process_evlist(struct evlist *evlist, unsigned int interval)
{
	enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;

	if (evlist__ctlfd_process(evlist, &cmd) > 0) {
		switch (cmd) {
		case EVLIST_CTL_CMD_ENABLE:
			if (interval)
				process_interval();
			break;
		case EVLIST_CTL_CMD_DISABLE:
			if (interval)
				process_interval();
			break;
634
		case EVLIST_CTL_CMD_SNAPSHOT:
635 636
		case EVLIST_CTL_CMD_ACK:
		case EVLIST_CTL_CMD_UNSUPPORTED:
637
		case EVLIST_CTL_CMD_EVLIST:
638
		case EVLIST_CTL_CMD_STOP:
639
		case EVLIST_CTL_CMD_PING:
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
		default:
			break;
		}
	}
}

static void compute_tts(struct timespec *time_start, struct timespec *time_stop,
			int *time_to_sleep)
{
	int tts = *time_to_sleep;
	struct timespec time_diff;

	diff_timespec(&time_diff, time_stop, time_start);

	tts -= time_diff.tv_sec * MSEC_PER_SEC +
	       time_diff.tv_nsec / NSEC_PER_MSEC;

	if (tts < 0)
		tts = 0;

	*time_to_sleep = tts;
}

static int dispatch_events(bool forks, int timeout, int interval, int *times)
664 665
{
	int child_exited = 0, status = 0;
666 667 668 669 670 671 672 673 674 675 676
	int time_to_sleep, sleep_time;
	struct timespec time_start, time_stop;

	if (interval)
		sleep_time = interval;
	else if (timeout)
		sleep_time = timeout;
	else
		sleep_time = 1000;

	time_to_sleep = sleep_time;
677 678 679 680 681 682 683 684 685 686

	while (!done) {
		if (forks)
			child_exited = waitpid(child_pid, &status, WNOHANG);
		else
			child_exited = !is_target_alive(&target, evsel_list->core.threads) ? 1 : 0;

		if (child_exited)
			break;

687 688 689 690 691 692 693 694 695 696
		clock_gettime(CLOCK_MONOTONIC, &time_start);
		if (!(evlist__poll(evsel_list, time_to_sleep) > 0)) { /* poll timeout or EINTR */
			if (timeout || handle_interval(interval, times))
				break;
			time_to_sleep = sleep_time;
		} else { /* fd revent */
			process_evlist(evsel_list, interval);
			clock_gettime(CLOCK_MONOTONIC, &time_stop);
			compute_tts(&time_start, &time_stop, &time_to_sleep);
		}
697 698 699 700 701
	}

	return status;
}

702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
enum counter_recovery {
	COUNTER_SKIP,
	COUNTER_RETRY,
	COUNTER_FATAL,
};

static enum counter_recovery stat_handle_error(struct evsel *counter)
{
	char msg[BUFSIZ];
	/*
	 * PPC returns ENXIO for HW counters until 2.6.37
	 * (behavior changed with commit b0a873e).
	 */
	if (errno == EINVAL || errno == ENOSYS ||
	    errno == ENOENT || errno == EOPNOTSUPP ||
	    errno == ENXIO) {
		if (verbose > 0)
			ui__warning("%s event is not supported by the kernel.\n",
720
				    evsel__name(counter));
721
		counter->supported = false;
722 723 724 725 726
		/*
		 * errored is a sticky flag that means one of the counter's
		 * cpu event had a problem and needs to be reexamined.
		 */
		counter->errored = true;
727 728 729 730

		if ((counter->leader != counter) ||
		    !(counter->leader->core.nr_members > 1))
			return COUNTER_SKIP;
731
	} else if (evsel__fallback(counter, errno, msg, sizeof(msg))) {
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
		if (verbose > 0)
			ui__warning("%s\n", msg);
		return COUNTER_RETRY;
	} else if (target__has_per_thread(&target) &&
		   evsel_list->core.threads &&
		   evsel_list->core.threads->err_thread != -1) {
		/*
		 * For global --per-thread case, skip current
		 * error thread.
		 */
		if (!thread_map__remove(evsel_list->core.threads,
					evsel_list->core.threads->err_thread)) {
			evsel_list->core.threads->err_thread = -1;
			return COUNTER_RETRY;
		}
	}

749
	evsel__open_strerror(counter, &target, errno, msg, sizeof(msg));
750 751 752 753 754 755 756
	ui__error("%s\n", msg);

	if (child_pid != -1)
		kill(child_pid, SIGTERM);
	return COUNTER_FATAL;
}

757
static int __run_perf_stat(int argc, const char **argv, int run_idx)
758
{
759
	int interval = stat_config.interval;
760
	int times = stat_config.times;
761
	int timeout = stat_config.timeout;
762
	char msg[BUFSIZ];
763
	unsigned long long t0, t1;
764
	struct evsel *counter;
765
	size_t l;
766
	int status = 0;
767
	const bool forks = (argc > 0);
768
	bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
769
	struct affinity affinity;
770
	int i, cpu, err;
771
	bool second_pass = false;
772

773
	if (forks) {
774
		if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {
775 776
			perror("failed to prepare workload");
			return -1;
777
		}
778
		child_pid = evsel_list->workload.pid;
779 780
	}

781
	if (group)
782
		evlist__set_leader(evsel_list);
783

784 785 786
	if (affinity__setup(&affinity) < 0)
		return -1;

787 788 789 790 791 792 793
	if (target__has_bpf(&target)) {
		evlist__for_each_entry(evsel_list, counter) {
			if (bpf_counter__load(counter, &target))
				return -1;
		}
	}

794
	evlist__for_each_cpu (evsel_list, i, cpu) {
795 796 797 798 799 800
		/*
		 * bperf calls evsel__open_per_cpu() in bperf__load(), so
		 * no need to call it again here.
		 */
		if (target.use_bpf)
			break;
801 802 803 804 805 806 807
		affinity__set(&affinity, cpu);

		evlist__for_each_entry(evsel_list, counter) {
			if (evsel__cpu_iter_skip(counter, cpu))
				continue;
			if (counter->reset_group || counter->errored)
				continue;
808
try_again:
809 810 811 812 813 814 815 816 817 818 819 820 821
			if (create_perf_stat_counter(counter, &stat_config, &target,
						     counter->cpu_iter - 1) < 0) {

				/*
				 * Weak group failed. We cannot just undo this here
				 * because earlier CPUs might be in group mode, and the kernel
				 * doesn't support mixing group and non group reads. Defer
				 * it to later.
				 * Don't close here because we're in the wrong affinity.
				 */
				if ((errno == EINVAL || errno == EBADF) &&
				    counter->leader != counter &&
				    counter->weak_group) {
822
					evlist__reset_weak_group(evsel_list, counter, false);
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
					assert(counter->reset_group);
					second_pass = true;
					continue;
				}

				switch (stat_handle_error(counter)) {
				case COUNTER_FATAL:
					return -1;
				case COUNTER_RETRY:
					goto try_again;
				case COUNTER_SKIP:
					continue;
				default:
					break;
				}

839
			}
840 841 842
			counter->supported = true;
		}
	}
843

844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
	if (second_pass) {
		/*
		 * Now redo all the weak group after closing them,
		 * and also close errored counters.
		 */

		evlist__for_each_cpu(evsel_list, i, cpu) {
			affinity__set(&affinity, cpu);
			/* First close errored or weak retry */
			evlist__for_each_entry(evsel_list, counter) {
				if (!counter->reset_group && !counter->errored)
					continue;
				if (evsel__cpu_iter_skip_no_inc(counter, cpu))
					continue;
				perf_evsel__close_cpu(&counter->core, counter->cpu_iter);
859
			}
860 861 862 863 864 865 866 867 868
			/* Now reopen weak */
			evlist__for_each_entry(evsel_list, counter) {
				if (!counter->reset_group && !counter->errored)
					continue;
				if (evsel__cpu_iter_skip(counter, cpu))
					continue;
				if (!counter->reset_group)
					continue;
try_again_reset:
869
				pr_debug2("reopening weak %s\n", evsel__name(counter));
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
				if (create_perf_stat_counter(counter, &stat_config, &target,
							     counter->cpu_iter - 1) < 0) {

					switch (stat_handle_error(counter)) {
					case COUNTER_FATAL:
						return -1;
					case COUNTER_RETRY:
						goto try_again_reset;
					case COUNTER_SKIP:
						continue;
					default:
						break;
					}
				}
				counter->supported = true;
			}
		}
	}
	affinity__cleanup(&affinity);

	evlist__for_each_entry(evsel_list, counter) {
		if (!counter->supported) {
			perf_evsel__free_fd(&counter->core);
			continue;
894
		}
895 896

		l = strlen(counter->unit);
897 898
		if (l > stat_config.unit_width)
			stat_config.unit_width = l;
899

900
		if (evsel__should_store_id(counter) &&
901
		    evsel__store_ids(counter, evsel_list))
902
			return -1;
903
	}
904

905
	if (evlist__apply_filters(evsel_list, &counter)) {
906
		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
907
			counter->filter, evsel__name(counter), errno,
908
			str_error_r(errno, msg, sizeof(msg)));
909 910 911
		return -1;
	}

J
Jiri Olsa 已提交
912
	if (STAT_RECORD) {
913
		int fd = perf_data__fd(&perf_stat.data);
J
Jiri Olsa 已提交
914

915
		if (is_pipe) {
916
			err = perf_header__write_pipe(perf_data__fd(&perf_stat.data));
917 918 919 920 921
		} else {
			err = perf_session__write_header(perf_stat.session, evsel_list,
							 fd, false);
		}

J
Jiri Olsa 已提交
922 923
		if (err < 0)
			return err;
924

925 926
		err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list,
							 process_synthesized_event, is_pipe);
927 928
		if (err < 0)
			return err;
J
Jiri Olsa 已提交
929 930
	}

931 932 933
	/*
	 * Enable counters and exec the command:
	 */
934
	if (forks) {
935
		evlist__start_workload(evsel_list);
936 937 938
		err = enable_counters();
		if (err)
			return -1;
939

940 941 942
		t0 = rdclock();
		clock_gettime(CLOCK_MONOTONIC, &ref_time);

943
		if (interval || timeout || evlist__ctlfd_initialized(evsel_list))
944
			status = dispatch_events(forks, timeout, interval, &times);
945 946 947
		if (child_pid != -1) {
			if (timeout)
				kill(child_pid, SIGTERM);
948
			wait4(child_pid, &status, 0, &stat_config.ru_data);
949
		}
950

951
		if (workload_exec_errno) {
952
			const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
953
			pr_err("Workload failed: %s\n", emsg);
954
			return -1;
955
		}
956

957 958
		if (WIFSIGNALED(status))
			psignal(WTERMSIG(status), argv[0]);
959
	} else {
960 961 962
		err = enable_counters();
		if (err)
			return -1;
963 964 965 966

		t0 = rdclock();
		clock_gettime(CLOCK_MONOTONIC, &ref_time);

967
		status = dispatch_events(forks, timeout, interval, &times);
968
	}
969

970 971
	disable_counters();

972 973
	t1 = rdclock();

974 975
	if (stat_config.walltime_run_table)
		stat_config.walltime_run[run_idx] = t1 - t0;
976

977
	if (interval && stat_config.summary) {
978
		stat_config.interval = 0;
979
		stat_config.stop_read_counter = true;
980 981 982 983
		init_stats(&walltime_nsecs_stats);
		update_stats(&walltime_nsecs_stats, t1 - t0);

		if (stat_config.aggr_mode == AGGR_GLOBAL)
984
			evlist__save_aggr_prev_raw_counts(evsel_list);
985

986 987
		evlist__copy_prev_raw_counts(evsel_list);
		evlist__reset_prev_raw_counts(evsel_list);
988 989 990 991
		runtime_stat_reset(&stat_config);
		perf_stat__reset_shadow_per_stat(&rt_stat);
	} else
		update_stats(&walltime_nsecs_stats, t1 - t0);
992

993 994 995 996 997 998
	/*
	 * Closing a group leader splits the group, and as we only disable
	 * group leaders, results in remaining events becoming enabled. To
	 * avoid arbitrary skew, we must read all counters before closing any
	 * group leaders.
	 */
999
	read_counters(&(struct timespec) { .tv_nsec = t1-t0 });
1000 1001 1002 1003 1004 1005

	/*
	 * We need to keep evsel_list alive, because it's processed
	 * later the evsel_list will be closed after.
	 */
	if (!STAT_RECORD)
1006
		evlist__close(evsel_list);
1007

1008 1009 1010
	return WEXITSTATUS(status);
}

1011
static int run_perf_stat(int argc, const char **argv, int run_idx)
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
{
	int ret;

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

	if (sync_run)
		sync();

1024
	ret = __run_perf_stat(argc, argv, run_idx);
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
	if (ret)
		return ret;

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

	return ret;
}

1037 1038
static void print_counters(struct timespec *ts, int argc, const char **argv)
{
1039 1040 1041
	/* Do not print anything if we record to the pipe. */
	if (STAT_RECORD && perf_stat.data.is_pipe)
		return;
A
Andi Kleen 已提交
1042 1043
	if (stat_config.quiet)
		return;
1044

1045
	evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);
1046 1047
}

1048 1049
static volatile int signr = -1;

1050
static void skip_signal(int signo)
1051
{
1052
	if ((child_pid == -1) || stat_config.interval)
1053 1054
		done = 1;

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

static void sig_atexit(void)
{
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
	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);

1079 1080 1081
	if (child_pid != -1)
		kill(child_pid, SIGTERM);

1082 1083
	sigprocmask(SIG_SETMASK, &oset, NULL);

1084 1085 1086 1087 1088
	if (signr == -1)
		return;

	signal(signr, SIG_DFL);
	kill(getpid(), signr);
1089 1090
}

1091 1092 1093 1094 1095
void perf_stat__set_big_num(int set)
{
	stat_config.big_num = (set != 0);
}

1096 1097 1098 1099 1100
void perf_stat__set_no_csv_summary(int set)
{
	stat_config.no_csv_summary = (set != 0);
}

1101 1102
static int stat__set_big_num(const struct option *opt __maybe_unused,
			     const char *s __maybe_unused, int unset)
S
Stephane Eranian 已提交
1103 1104
{
	big_num_opt = unset ? 0 : 1;
1105
	perf_stat__set_big_num(!unset);
S
Stephane Eranian 已提交
1106 1107 1108
	return 0;
}

1109 1110 1111 1112
static int enable_metric_only(const struct option *opt __maybe_unused,
			      const char *s __maybe_unused, int unset)
{
	force_metric_only = true;
1113
	stat_config.metric_only = !unset;
1114 1115 1116
	return 0;
}

1117 1118 1119 1120
static int parse_metric_groups(const struct option *opt,
			       const char *str,
			       int unset __maybe_unused)
{
1121 1122 1123 1124
	return metricgroup__parse_groups(opt, str,
					 stat_config.metric_no_group,
					 stat_config.metric_no_merge,
					 &stat_config.metric_events);
1125 1126
}

1127 1128 1129 1130
static int parse_control_option(const struct option *opt,
				const char *str,
				int unset __maybe_unused)
{
1131
	struct perf_stat_config *config = opt->value;
1132

1133 1134 1135
	return evlist__parse_control(str, &config->ctl_fd, &config->ctl_fd_ack, &config->ctl_fd_close);
}

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
static int parse_stat_cgroups(const struct option *opt,
			      const char *str, int unset)
{
	if (stat_config.cgroup_list) {
		pr_err("--cgroup and --for-each-cgroup cannot be used together\n");
		return -1;
	}

	return parse_cgroups(opt, str, unset);
}

1147
static struct option stat_options[] = {
J
Jiri Olsa 已提交
1148 1149 1150 1151 1152 1153 1154
	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),
1155
	OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
J
Jiri Olsa 已提交
1156 1157 1158 1159 1160
		    "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"),
1161 1162 1163
#ifdef HAVE_BPF_SKEL
	OPT_STRING('b', "bpf-prog", &target.bpf_str, "bpf-prog-id",
		   "stat events on existing bpf program id"),
1164 1165 1166 1167
	OPT_BOOLEAN(0, "bpf-counters", &target.use_bpf,
		    "use bpf program to count events"),
	OPT_STRING(0, "bpf-attr-map", &target.attr_map, "attr-map-path",
		   "path to perf_event_attr map"),
1168
#endif
J
Jiri Olsa 已提交
1169 1170 1171 1172
	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"),
A
Andi Kleen 已提交
1173 1174
	OPT_BOOLEAN(0, "scale", &stat_config.scale,
		    "Use --no-scale to disable counter scaling for multiplexing"),
J
Jiri Olsa 已提交
1175 1176
	OPT_INCR('v', "verbose", &verbose,
		    "be more verbose (show counter open errors, etc)"),
1177
	OPT_INTEGER('r', "repeat", &stat_config.run_count,
J
Jiri Olsa 已提交
1178
		    "repeat command and print average + stddev (max: 100, forever: 0)"),
1179
	OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
1180
		    "display details about each run (only with -r option)"),
1181
	OPT_BOOLEAN('n', "null", &stat_config.null_run,
J
Jiri Olsa 已提交
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
		    "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),
1194
	OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
1195
	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
J
Jiri Olsa 已提交
1196 1197
		   "print counts with custom separator"),
	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1198 1199 1200
		     "monitor event in cgroup name only", parse_stat_cgroups),
	OPT_STRING(0, "for-each-cgroup", &stat_config.cgroup_list, "name",
		    "expand events for each cgroup"),
J
Jiri Olsa 已提交
1201 1202 1203 1204 1205 1206 1207 1208 1209
	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,
1210 1211
		    "print counts at regular interval in ms "
		    "(overhead is possible for values <= 100ms)"),
1212 1213
	OPT_INTEGER(0, "interval-count", &stat_config.times,
		    "print counts for fixed number of times"),
1214
	OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
1215
		    "clear screen in between new interval"),
1216 1217
	OPT_UINTEGER(0, "timeout", &stat_config.timeout,
		    "stop workload and print counts after a timeout period in ms (>= 10ms)"),
J
Jiri Olsa 已提交
1218 1219
	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
		     "aggregate counts per processor socket", AGGR_SOCKET),
1220 1221
	OPT_SET_UINT(0, "per-die", &stat_config.aggr_mode,
		     "aggregate counts per processor die", AGGR_DIE),
J
Jiri Olsa 已提交
1222 1223 1224 1225
	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),
1226 1227
	OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode,
		     "aggregate counts per numa node", AGGR_NODE),
1228 1229
	OPT_INTEGER('D', "delay", &stat_config.initial_delay,
		    "ms to wait before starting measurement after program start (-1: start with events disabled)"),
1230
	OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
1231
			"Only print computed metrics. No raw values", enable_metric_only),
1232 1233 1234 1235
	OPT_BOOLEAN(0, "metric-no-group", &stat_config.metric_no_group,
		       "don't group metric events, impacts multiplexing"),
	OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge,
		       "don't try to share events between metrics in a group"),
1236
	OPT_BOOLEAN(0, "topdown", &topdown_run,
K
Kan Liang 已提交
1237 1238 1239
			"measure top-down statistics"),
	OPT_UINTEGER(0, "td-level", &stat_config.topdown_level,
			"Set the metrics level for the top-down statistics (0: max level)"),
1240 1241
	OPT_BOOLEAN(0, "smi-cost", &smi_cost,
			"measure SMI cost"),
1242 1243 1244
	OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list",
		     "monitor specified metrics or metric groups (separated by ,)",
		     parse_metric_groups),
1245 1246 1247 1248 1249 1250
	OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel,
			 "Configure all used events to run in kernel space.",
			 PARSE_OPT_EXCLUSIVE),
	OPT_BOOLEAN_FLAG(0, "all-user", &stat_config.all_user,
			 "Configure all used events to run in user space.",
			 PARSE_OPT_EXCLUSIVE),
1251 1252 1253 1254
	OPT_BOOLEAN(0, "percore-show-thread", &stat_config.percore_show_thread,
		    "Use with 'percore' event qualifier to show the event "
		    "counts of one hardware thread by sum up total hardware "
		    "threads of same physical core"),
1255 1256
	OPT_BOOLEAN(0, "summary", &stat_config.summary,
		       "print summary for interval mode"),
1257 1258
	OPT_BOOLEAN(0, "no-csv-summary", &stat_config.no_csv_summary,
		       "don't print 'summary' for CSV summary output"),
A
Andi Kleen 已提交
1259 1260
	OPT_BOOLEAN(0, "quiet", &stat_config.quiet,
			"don't print output (useful with record)"),
1261 1262 1263 1264 1265
#ifdef HAVE_LIBPFM
	OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",
		"libpfm4 event selector. use 'perf list' to list available events",
		parse_libpfm_events_option),
#endif
1266
	OPT_CALLBACK(0, "control", &stat_config, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]",
1267
		     "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n"
1268 1269
		     "\t\t\t  Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n"
		     "\t\t\t  Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",
1270
		      parse_control_option),
J
Jiri Olsa 已提交
1271 1272 1273
	OPT_END()
};

1274
static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
1275
				 struct perf_cpu_map *map, int cpu)
1276 1277 1278 1279
{
	return cpu_map__get_socket(map, cpu, NULL);
}

1280
static struct aggr_cpu_id perf_stat__get_die(struct perf_stat_config *config __maybe_unused,
1281
			      struct perf_cpu_map *map, int cpu)
1282 1283 1284 1285
{
	return cpu_map__get_die(map, cpu, NULL);
}

1286
static struct aggr_cpu_id perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
1287
			       struct perf_cpu_map *map, int cpu)
1288 1289 1290 1291
{
	return cpu_map__get_core(map, cpu, NULL);
}

1292
static struct aggr_cpu_id perf_stat__get_node(struct perf_stat_config *config __maybe_unused,
1293 1294 1295 1296 1297
			       struct perf_cpu_map *map, int cpu)
{
	return cpu_map__get_node(map, cpu, NULL);
}

1298
static struct aggr_cpu_id perf_stat__get_aggr(struct perf_stat_config *config,
1299
			       aggr_get_id_t get_id, struct perf_cpu_map *map, int idx)
1300 1301
{
	int cpu;
1302
	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
1303 1304

	if (idx >= map->nr)
1305
		return id;
1306 1307 1308

	cpu = map->map[idx];

1309 1310
	if (cpu_map__aggr_cpu_id_is_empty(config->cpus_aggr_map->map[cpu]))
		config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
1311

1312
	id = config->cpus_aggr_map->map[cpu];
1313
	return id;
1314 1315
}

1316
static struct aggr_cpu_id perf_stat__get_socket_cached(struct perf_stat_config *config,
1317
					struct perf_cpu_map *map, int idx)
1318
{
1319
	return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
1320 1321
}

1322
static struct aggr_cpu_id perf_stat__get_die_cached(struct perf_stat_config *config,
1323
					struct perf_cpu_map *map, int idx)
1324 1325 1326 1327
{
	return perf_stat__get_aggr(config, perf_stat__get_die, map, idx);
}

1328
static struct aggr_cpu_id perf_stat__get_core_cached(struct perf_stat_config *config,
1329
				      struct perf_cpu_map *map, int idx)
1330
{
1331
	return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
1332 1333
}

1334
static struct aggr_cpu_id perf_stat__get_node_cached(struct perf_stat_config *config,
1335 1336 1337 1338 1339
				      struct perf_cpu_map *map, int idx)
{
	return perf_stat__get_aggr(config, perf_stat__get_node, map, idx);
}

1340 1341
static bool term_percore_set(void)
{
1342
	struct evsel *counter;
1343 1344 1345 1346 1347 1348 1349 1350 1351

	evlist__for_each_entry(evsel_list, counter) {
		if (counter->percore)
			return true;
	}

	return false;
}

1352 1353
static int perf_stat_init_aggr_mode(void)
{
1354 1355
	int nr;

1356
	switch (stat_config.aggr_mode) {
1357
	case AGGR_SOCKET:
1358
		if (cpu_map__build_socket_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
1359 1360 1361
			perror("cannot build socket map");
			return -1;
		}
1362
		stat_config.aggr_get_id = perf_stat__get_socket_cached;
1363
		break;
1364
	case AGGR_DIE:
1365
		if (cpu_map__build_die_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
1366 1367 1368 1369 1370
			perror("cannot build die map");
			return -1;
		}
		stat_config.aggr_get_id = perf_stat__get_die_cached;
		break;
1371
	case AGGR_CORE:
1372
		if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
1373 1374 1375
			perror("cannot build core map");
			return -1;
		}
1376
		stat_config.aggr_get_id = perf_stat__get_core_cached;
1377
		break;
1378 1379 1380 1381 1382 1383 1384
	case AGGR_NODE:
		if (cpu_map__build_node_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
			perror("cannot build core map");
			return -1;
		}
		stat_config.aggr_get_id = perf_stat__get_node_cached;
		break;
1385
	case AGGR_NONE:
1386
		if (term_percore_set()) {
1387
			if (cpu_map__build_core_map(evsel_list->core.cpus,
1388 1389 1390 1391 1392 1393 1394
						    &stat_config.aggr_map)) {
				perror("cannot build core map");
				return -1;
			}
			stat_config.aggr_get_id = perf_stat__get_core_cached;
		}
		break;
1395
	case AGGR_GLOBAL:
1396
	case AGGR_THREAD:
J
Jiri Olsa 已提交
1397
	case AGGR_UNSET:
1398 1399 1400
	default:
		break;
	}
1401 1402 1403 1404 1405 1406

	/*
	 * The evsel_list->cpus is the base we operate on,
	 * taking the highest cpu number to be the size of
	 * the aggregation translate cpumap.
	 */
1407
	nr = perf_cpu_map__max(evsel_list->core.cpus);
1408
	stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr + 1);
1409
	return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
1410 1411
}

1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
static void cpu_aggr_map__delete(struct cpu_aggr_map *map)
{
	if (map) {
		WARN_ONCE(refcount_read(&map->refcnt) != 0,
			  "cpu_aggr_map refcnt unbalanced\n");
		free(map);
	}
}

static void cpu_aggr_map__put(struct cpu_aggr_map *map)
{
	if (map && refcount_dec_and_test(&map->refcnt))
		cpu_aggr_map__delete(map);
}

1427 1428
static void perf_stat__exit_aggr_mode(void)
{
1429 1430
	cpu_aggr_map__put(stat_config.aggr_map);
	cpu_aggr_map__put(stat_config.cpus_aggr_map);
1431 1432
	stat_config.aggr_map = NULL;
	stat_config.cpus_aggr_map = NULL;
1433 1434
}

1435
static inline int perf_env__get_cpu(struct perf_env *env, struct perf_cpu_map *map, int idx)
1436 1437 1438 1439 1440 1441 1442 1443
{
	int cpu;

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

	cpu = map->map[idx];

1444
	if (cpu >= env->nr_cpus_avail)
1445 1446 1447 1448 1449
		return -1;

	return cpu;
}

1450
static struct aggr_cpu_id perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data)
1451 1452 1453
{
	struct perf_env *env = data;
	int cpu = perf_env__get_cpu(env, map, idx);
1454 1455 1456
	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();

	if (cpu != -1)
1457
		id.socket = env->cpu[cpu].socket_id;
1458

1459
	return id;
1460 1461
}

1462
static struct aggr_cpu_id perf_env__get_die(struct perf_cpu_map *map, int idx, void *data)
1463 1464
{
	struct perf_env *env = data;
1465 1466
	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
	int cpu = perf_env__get_cpu(env, map, idx);
1467 1468 1469

	if (cpu != -1) {
		/*
1470 1471 1472
		 * die_id is relative to socket, so start
		 * with the socket ID and then add die to
		 * make a unique ID.
1473
		 */
1474
		id.socket = env->cpu[cpu].socket_id;
1475
		id.die = env->cpu[cpu].die_id;
1476 1477
	}

1478
	return id;
1479 1480
}

1481
static struct aggr_cpu_id perf_env__get_core(struct perf_cpu_map *map, int idx, void *data)
1482 1483
{
	struct perf_env *env = data;
1484 1485
	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
	int cpu = perf_env__get_cpu(env, map, idx);
1486 1487 1488

	if (cpu != -1) {
		/*
1489
		 * core_id is relative to socket and die,
1490 1491
		 * we need a global id. So we set
		 * socket, die id and core id
1492
		 */
1493
		id.socket = env->cpu[cpu].socket_id;
1494
		id.die = env->cpu[cpu].die_id;
1495
		id.core = env->cpu[cpu].core_id;
1496 1497
	}

1498
	return id;
1499 1500
}

1501
static struct aggr_cpu_id perf_env__get_node(struct perf_cpu_map *map, int idx, void *data)
1502 1503
{
	int cpu = perf_env__get_cpu(data, map, idx);
1504
	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
1505

1506
	id.node = perf_env__numa_node(data, cpu);
1507
	return id;
1508 1509
}

1510
static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus,
1511
				      struct cpu_aggr_map **sockp)
1512 1513 1514 1515
{
	return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
}

1516
static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus,
1517
				   struct cpu_aggr_map **diep)
1518 1519 1520 1521
{
	return cpu_map__build_map(cpus, diep, perf_env__get_die, env);
}

1522
static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus,
1523
				    struct cpu_aggr_map **corep)
1524 1525 1526 1527
{
	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
}

1528
static int perf_env__build_node_map(struct perf_env *env, struct perf_cpu_map *cpus,
1529
				    struct cpu_aggr_map **nodep)
1530 1531 1532 1533
{
	return cpu_map__build_map(cpus, nodep, perf_env__get_node, env);
}

1534
static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
1535
				      struct perf_cpu_map *map, int idx)
1536 1537 1538
{
	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
}
1539
static struct aggr_cpu_id perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,
1540
				   struct perf_cpu_map *map, int idx)
1541 1542 1543
{
	return perf_env__get_die(map, idx, &perf_stat.session->header.env);
}
1544

1545
static struct aggr_cpu_id perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
1546
				    struct perf_cpu_map *map, int idx)
1547 1548 1549 1550
{
	return perf_env__get_core(map, idx, &perf_stat.session->header.env);
}

1551
static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,
1552 1553 1554 1555 1556
				    struct perf_cpu_map *map, int idx)
{
	return perf_env__get_node(map, idx, &perf_stat.session->header.env);
}

1557 1558 1559 1560 1561 1562
static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
{
	struct perf_env *env = &st->session->header.env;

	switch (stat_config.aggr_mode) {
	case AGGR_SOCKET:
1563
		if (perf_env__build_socket_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
1564 1565 1566
			perror("cannot build socket map");
			return -1;
		}
1567
		stat_config.aggr_get_id = perf_stat__get_socket_file;
1568
		break;
1569
	case AGGR_DIE:
1570
		if (perf_env__build_die_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
1571 1572 1573 1574 1575
			perror("cannot build die map");
			return -1;
		}
		stat_config.aggr_get_id = perf_stat__get_die_file;
		break;
1576
	case AGGR_CORE:
1577
		if (perf_env__build_core_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
1578 1579 1580
			perror("cannot build core map");
			return -1;
		}
1581
		stat_config.aggr_get_id = perf_stat__get_core_file;
1582
		break;
1583 1584 1585 1586 1587 1588 1589
	case AGGR_NODE:
		if (perf_env__build_node_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
			perror("cannot build core map");
			return -1;
		}
		stat_config.aggr_get_id = perf_stat__get_node_file;
		break;
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600
	case AGGR_NONE:
	case AGGR_GLOBAL:
	case AGGR_THREAD:
	case AGGR_UNSET:
	default:
		break;
	}

	return 0;
}

1601 1602 1603 1604 1605 1606
/*
 * 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)
{
1607
	int err;
1608
	struct perf_event_attr default_attrs0[] = {
1609 1610 1611 1612 1613 1614 1615

  { .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		},
1616 1617
};
	struct perf_event_attr frontend_attrs[] = {
1618
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},
1619 1620
};
	struct perf_event_attr backend_attrs[] = {
1621
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},
1622 1623
};
	struct perf_event_attr default_attrs1[] = {
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
  { .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)				},
};
1720
	struct parse_events_error errinfo;
1721

1722
	/* Set attrs if no event is selected and !null_run: */
1723
	if (stat_config.null_run)
1724 1725
		return 0;

1726
	bzero(&errinfo, sizeof(errinfo));
1727
	if (transaction_run) {
1728
		/* Handle -T as -M transaction. Once platform specific metrics
1729
		 * support has been added to the json files, all architectures
1730 1731 1732 1733 1734 1735 1736
		 * will use this approach. To determine transaction support
		 * on an architecture test for such a metric name.
		 */
		if (metricgroup__has_metric("transaction")) {
			struct option opt = { .value = &evsel_list };

			return metricgroup__parse_groups(&opt, "transaction",
1737 1738
							 stat_config.metric_no_group,
							stat_config.metric_no_merge,
1739
							 &stat_config.metric_events);
1740 1741
		}

1742 1743
		if (pmu_have_event("cpu", "cycles-ct") &&
		    pmu_have_event("cpu", "el-start"))
1744 1745
			err = parse_events(evsel_list, transaction_attrs,
					   &errinfo);
1746
		else
1747 1748 1749
			err = parse_events(evsel_list,
					   transaction_limited_attrs,
					   &errinfo);
1750
		if (err) {
1751
			fprintf(stderr, "Cannot set up transaction events\n");
1752
			parse_events_print_error(&errinfo, transaction_attrs);
1753 1754 1755 1756 1757
			return -1;
		}
		return 0;
	}

1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776
	if (smi_cost) {
		int smi;

		if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {
			fprintf(stderr, "freeze_on_smi is not supported.\n");
			return -1;
		}

		if (!smi) {
			if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) {
				fprintf(stderr, "Failed to set freeze_on_smi.\n");
				return -1;
			}
			smi_reset = true;
		}

		if (pmu_have_event("msr", "aperf") &&
		    pmu_have_event("msr", "smi")) {
			if (!force_metric_only)
1777
				stat_config.metric_only = true;
1778
			err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
1779 1780 1781
		} else {
			fprintf(stderr, "To measure SMI cost, it needs "
				"msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
1782
			parse_events_print_error(&errinfo, smi_cost_attrs);
1783 1784 1785
			return -1;
		}
		if (err) {
1786
			parse_events_print_error(&errinfo, smi_cost_attrs);
1787 1788 1789 1790 1791 1792
			fprintf(stderr, "Cannot set up SMI cost events\n");
			return -1;
		}
		return 0;
	}

1793
	if (topdown_run) {
K
Kan Liang 已提交
1794 1795
		const char **metric_attrs = topdown_metric_attrs;
		unsigned int max_level = 1;
1796 1797 1798
		char *str = NULL;
		bool warn = false;

1799 1800 1801
		if (!force_metric_only)
			stat_config.metric_only = true;

K
Kan Liang 已提交
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813
		if (pmu_have_event("cpu", topdown_metric_L2_attrs[5])) {
			metric_attrs = topdown_metric_L2_attrs;
			max_level = 2;
		}

		if (stat_config.topdown_level > max_level) {
			pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level);
			return -1;
		} else if (!stat_config.topdown_level)
			stat_config.topdown_level = max_level;

		if (topdown_filter_events(metric_attrs, &str, 1) < 0) {
1814 1815 1816
			pr_err("Out of memory\n");
			return -1;
		}
K
Kan Liang 已提交
1817
		if (metric_attrs[0] && str) {
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
			if (!stat_config.interval && !stat_config.metric_only) {
				fprintf(stat_config.output,
					"Topdown accuracy may decrease when measuring long periods.\n"
					"Please print the result regularly, e.g. -I1000\n");
			}
			goto setup_metrics;
		}

		zfree(&str);

1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
		if (stat_config.aggr_mode != AGGR_GLOBAL &&
		    stat_config.aggr_mode != AGGR_CORE) {
			pr_err("top down event configuration requires --per-core mode\n");
			return -1;
		}
		stat_config.aggr_mode = AGGR_CORE;
		if (nr_cgroups || !target__has_cpu(&target)) {
			pr_err("top down event configuration requires system-wide mode (-a)\n");
			return -1;
		}

		if (topdown_filter_events(topdown_attrs, &str,
				arch_topdown_check_group(&warn)) < 0) {
			pr_err("Out of memory\n");
			return -1;
		}
		if (topdown_attrs[0] && str) {
			if (warn)
				arch_topdown_group_warn();
1847
setup_metrics:
1848
			err = parse_events(evsel_list, str, &errinfo);
1849 1850 1851 1852
			if (err) {
				fprintf(stderr,
					"Cannot set up top down events %s: %d\n",
					str, err);
1853
				parse_events_print_error(&errinfo, str);
1854
				free(str);
1855 1856 1857 1858 1859 1860 1861 1862 1863
				return -1;
			}
		} else {
			fprintf(stderr, "System does not support topdown\n");
			return -1;
		}
		free(str);
	}

1864
	if (!evsel_list->core.nr_entries) {
1865 1866 1867
		if (target__has_cpu(&target))
			default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;

1868
		if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0)
1869 1870
			return -1;
		if (pmu_have_event("cpu", "stalled-cycles-frontend")) {
1871
			if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0)
1872 1873 1874
				return -1;
		}
		if (pmu_have_event("cpu", "stalled-cycles-backend")) {
1875
			if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0)
1876 1877
				return -1;
		}
1878
		if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0)
1879
			return -1;
1880 1881 1882

		if (arch_evlist__add_default_attrs(evsel_list) < 0)
			return -1;
1883 1884 1885 1886 1887 1888 1889 1890
	}

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

	if (detailed_run <  1)
		return 0;

	/* Append detailed run extra attributes: */
1891
	if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
1892
		return -1;
1893 1894 1895 1896 1897

	if (detailed_run < 2)
		return 0;

	/* Append very detailed run extra attributes: */
1898
	if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
1899
		return -1;
1900 1901 1902 1903 1904

	if (detailed_run < 3)
		return 0;

	/* Append very, very detailed run extra attributes: */
1905
	return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1906 1907
}

J
Jiri Olsa 已提交
1908
static const char * const stat_record_usage[] = {
J
Jiri Olsa 已提交
1909 1910 1911 1912
	"perf stat record [<options>]",
	NULL,
};

1913 1914 1915 1916 1917 1918 1919
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);

1920
	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
1921 1922 1923 1924 1925 1926
	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 已提交
1927 1928 1929
static int __cmd_record(int argc, const char **argv)
{
	struct perf_session *session;
1930
	struct perf_data *data = &perf_stat.data;
J
Jiri Olsa 已提交
1931

J
Jiri Olsa 已提交
1932
	argc = parse_options(argc, argv, stat_options, stat_record_usage,
J
Jiri Olsa 已提交
1933 1934 1935
			     PARSE_OPT_STOP_AT_NON_OPTION);

	if (output_name)
J
Jiri Olsa 已提交
1936
		data->path = output_name;
J
Jiri Olsa 已提交
1937

1938
	if (stat_config.run_count != 1 || forever) {
1939 1940 1941 1942
		pr_err("Cannot use -r option with perf stat record.\n");
		return -1;
	}

1943
	session = perf_session__new(data, false, NULL);
1944 1945 1946
	if (IS_ERR(session)) {
		pr_err("Perf session creation failed\n");
		return PTR_ERR(session);
J
Jiri Olsa 已提交
1947 1948
	}

1949 1950
	init_features(session);

J
Jiri Olsa 已提交
1951 1952 1953 1954 1955 1956
	session->evlist   = evsel_list;
	perf_stat.session = session;
	perf_stat.record  = true;
	return argc;
}

1957 1958
static int process_stat_round_event(struct perf_session *session,
				    union perf_event *event)
1959
{
1960
	struct perf_record_stat_round *stat_round = &event->stat_round;
1961
	struct evsel *counter;
1962 1963 1964 1965
	struct timespec tsh, *ts = NULL;
	const char **argv = session->header.env.cmdline_argv;
	int argc = session->header.env.nr_cmdline;

1966
	evlist__for_each_entry(evsel_list, counter)
1967 1968
		perf_stat_process_counter(&stat_config, counter);

1969 1970
	if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)
		update_stats(&walltime_nsecs_stats, stat_round->time);
1971

1972
	if (stat_config.interval && stat_round->time) {
1973 1974
		tsh.tv_sec  = stat_round->time / NSEC_PER_SEC;
		tsh.tv_nsec = stat_round->time % NSEC_PER_SEC;
1975 1976 1977 1978 1979 1980 1981
		ts = &tsh;
	}

	print_counters(ts, argc, argv);
	return 0;
}

1982
static
1983 1984
int process_stat_config_event(struct perf_session *session,
			      union perf_event *event)
1985
{
1986
	struct perf_tool *tool = session->tool;
1987 1988
	struct perf_stat *st = container_of(tool, struct perf_stat, tool);

1989
	perf_event__read_stat_config(&stat_config, &event->stat_config);
1990

1991
	if (perf_cpu_map__empty(st->cpus)) {
1992 1993 1994 1995 1996 1997 1998 1999
		if (st->aggr_mode != AGGR_UNSET)
			pr_warning("warning: processing task data, aggregation mode not set\n");
		return 0;
	}

	if (st->aggr_mode != AGGR_UNSET)
		stat_config.aggr_mode = st->aggr_mode;

2000
	if (perf_stat.data.is_pipe)
2001 2002 2003 2004
		perf_stat_init_aggr_mode();
	else
		perf_stat_init_aggr_mode_file(st);

2005 2006 2007
	return 0;
}

2008 2009 2010 2011 2012 2013 2014 2015
static int set_maps(struct perf_stat *st)
{
	if (!st->cpus || !st->threads)
		return 0;

	if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
		return -EINVAL;

2016
	perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
2017

2018
	if (evlist__alloc_stats(evsel_list, true))
2019 2020 2021 2022 2023 2024 2025
		return -ENOMEM;

	st->maps_allocated = true;
	return 0;
}

static
2026 2027
int process_thread_map_event(struct perf_session *session,
			     union perf_event *event)
2028
{
2029
	struct perf_tool *tool = session->tool;
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044
	struct perf_stat *st = container_of(tool, struct perf_stat, tool);

	if (st->threads) {
		pr_warning("Extra thread map event, ignoring.\n");
		return 0;
	}

	st->threads = thread_map__new_event(&event->thread_map);
	if (!st->threads)
		return -ENOMEM;

	return set_maps(st);
}

static
2045 2046
int process_cpu_map_event(struct perf_session *session,
			  union perf_event *event)
2047
{
2048
	struct perf_tool *tool = session->tool;
2049
	struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2050
	struct perf_cpu_map *cpus;
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064

	if (st->cpus) {
		pr_warning("Extra cpu map event, ignoring.\n");
		return 0;
	}

	cpus = cpu_map__new_data(&event->cpu_map.data);
	if (!cpus)
		return -ENOMEM;

	st->cpus = cpus;
	return set_maps(st);
}

J
Jiri Olsa 已提交
2065
static const char * const stat_report_usage[] = {
J
Jiri Olsa 已提交
2066 2067 2068 2069 2070 2071 2072
	"perf stat report [<options>]",
	NULL,
};

static struct perf_stat perf_stat = {
	.tool = {
		.attr		= perf_event__process_attr,
2073
		.event_update	= perf_event__process_event_update,
2074 2075
		.thread_map	= process_thread_map_event,
		.cpu_map	= process_cpu_map_event,
2076
		.stat_config	= process_stat_config_event,
2077 2078
		.stat		= perf_event__process_stat_event,
		.stat_round	= process_stat_round_event,
J
Jiri Olsa 已提交
2079
	},
2080
	.aggr_mode = AGGR_UNSET,
J
Jiri Olsa 已提交
2081 2082 2083 2084 2085 2086 2087
};

static int __cmd_report(int argc, const char **argv)
{
	struct perf_session *session;
	const struct option options[] = {
	OPT_STRING('i', "input", &input_name, "file", "input file name"),
2088 2089
	OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,
		     "aggregate counts per processor socket", AGGR_SOCKET),
2090 2091
	OPT_SET_UINT(0, "per-die", &perf_stat.aggr_mode,
		     "aggregate counts per processor die", AGGR_DIE),
2092 2093
	OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,
		     "aggregate counts per physical processor core", AGGR_CORE),
2094 2095
	OPT_SET_UINT(0, "per-node", &perf_stat.aggr_mode,
		     "aggregate counts per numa node", AGGR_NODE),
2096 2097
	OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,
		     "disable CPU count aggregation", AGGR_NONE),
J
Jiri Olsa 已提交
2098 2099 2100 2101 2102
	OPT_END()
	};
	struct stat st;
	int ret;

J
Jiri Olsa 已提交
2103
	argc = parse_options(argc, argv, options, stat_report_usage, 0);
J
Jiri Olsa 已提交
2104 2105 2106 2107 2108 2109 2110 2111

	if (!input_name || !strlen(input_name)) {
		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
			input_name = "-";
		else
			input_name = "perf.data";
	}

J
Jiri Olsa 已提交
2112 2113
	perf_stat.data.path = input_name;
	perf_stat.data.mode = PERF_DATA_MODE_READ;
J
Jiri Olsa 已提交
2114

2115
	session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
2116 2117
	if (IS_ERR(session))
		return PTR_ERR(session);
J
Jiri Olsa 已提交
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130

	perf_stat.session  = session;
	stat_config.output = stderr;
	evsel_list         = session->evlist;

	ret = perf_session__process_events(session);
	if (ret)
		return ret;

	perf_session__delete(session);
	return 0;
}

2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147
static void setup_system_wide(int forks)
{
	/*
	 * Make system wide (-a) the default target if
	 * no target was specified and one of following
	 * conditions is met:
	 *
	 *   - there's no workload specified
	 *   - there is workload specified but all requested
	 *     events are system wide events
	 */
	if (!target__none(&target))
		return;

	if (!forks)
		target.system_wide = true;
	else {
2148
		struct evsel *counter;
2149 2150

		evlist__for_each_entry(evsel_list, counter) {
2151 2152
			if (!counter->core.system_wide &&
			    strcmp(counter->name, "duration_time")) {
2153
				return;
2154
			}
2155 2156
		}

2157
		if (evsel_list->core.nr_entries)
2158 2159 2160 2161
			target.system_wide = true;
	}
}

2162
int cmd_stat(int argc, const char **argv)
2163
{
2164 2165 2166 2167
	const char * const stat_usage[] = {
		"perf stat [<options>] [<command>]",
		NULL
	};
2168
	int status = -EINVAL, run_idx, err;
2169
	const char *mode;
2170
	FILE *output = stderr;
2171
	unsigned int interval, timeout;
J
Jiri Olsa 已提交
2172
	const char * const stat_subcommands[] = { "record", "report" };
2173
	char errbuf[BUFSIZ];
2174

2175 2176
	setlocale(LC_ALL, "");

2177
	evsel_list = evlist__new();
2178 2179 2180
	if (evsel_list == NULL)
		return -ENOMEM;

2181
	parse_events__shrink_config_terms();
2182 2183 2184 2185 2186 2187

	/* String-parsing callback-based options would segfault when negated */
	set_option_flag(stat_options, 'e', "event", PARSE_OPT_NONEG);
	set_option_flag(stat_options, 'M', "metrics", PARSE_OPT_NONEG);
	set_option_flag(stat_options, 'G', "cgroup", PARSE_OPT_NONEG);

J
Jiri Olsa 已提交
2188 2189 2190
	argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
					(const char **) stat_usage,
					PARSE_OPT_STOP_AT_NON_OPTION);
2191
	perf_stat__collect_metric_expr(evsel_list);
2192
	perf_stat__init_shadow_stats();
J
Jiri Olsa 已提交
2193

2194 2195 2196 2197
	if (stat_config.csv_sep) {
		stat_config.csv_output = true;
		if (!strcmp(stat_config.csv_sep, "\\t"))
			stat_config.csv_sep = "\t";
2198
	} else
2199
		stat_config.csv_sep = DEFAULT_SEPARATOR;
2200

J
Jiri Olsa 已提交
2201 2202 2203 2204
	if (argc && !strncmp(argv[0], "rec", 3)) {
		argc = __cmd_record(argc, argv);
		if (argc < 0)
			return -1;
J
Jiri Olsa 已提交
2205 2206
	} else if (argc && !strncmp(argv[0], "rep", 3))
		return __cmd_report(argc, argv);
S
Stephane Eranian 已提交
2207

2208
	interval = stat_config.interval;
2209
	timeout = stat_config.timeout;
2210

J
Jiri Olsa 已提交
2211 2212 2213 2214
	/*
	 * For record command the -o is already taken care of.
	 */
	if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
2215 2216
		output = NULL;

2217 2218
	if (output_name && output_fd) {
		fprintf(stderr, "cannot use both --output and --log-fd\n");
J
Jiri Olsa 已提交
2219 2220
		parse_options_usage(stat_usage, stat_options, "o", 1);
		parse_options_usage(NULL, stat_options, "log-fd", 0);
2221
		goto out;
2222
	}
2223

2224
	if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
2225 2226 2227 2228
		fprintf(stderr, "--metric-only is not supported with --per-thread\n");
		goto out;
	}

2229
	if (stat_config.metric_only && stat_config.run_count > 1) {
2230 2231 2232 2233
		fprintf(stderr, "--metric-only is not supported with -r\n");
		goto out;
	}

2234
	if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
2235 2236 2237 2238 2239 2240
		fprintf(stderr, "--table is only supported with -r\n");
		parse_options_usage(stat_usage, stat_options, "r", 1);
		parse_options_usage(NULL, stat_options, "table", 0);
		goto out;
	}

2241 2242
	if (output_fd < 0) {
		fprintf(stderr, "argument to --log-fd must be a > 0\n");
J
Jiri Olsa 已提交
2243
		parse_options_usage(stat_usage, stat_options, "log-fd", 0);
2244
		goto out;
2245 2246
	}

A
Andi Kleen 已提交
2247
	if (!output && !stat_config.quiet) {
2248 2249 2250 2251 2252 2253
		struct timespec tm;
		mode = append_file ? "a" : "w";

		output = fopen(output_name, mode);
		if (!output) {
			perror("failed to create output file");
2254
			return -1;
2255 2256 2257
		}
		clock_gettime(CLOCK_REALTIME, &tm);
		fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
2258
	} else if (output_fd > 0) {
2259 2260 2261 2262 2263 2264
		mode = append_file ? "a" : "w";
		output = fdopen(output_fd, mode);
		if (!output) {
			perror("Failed opening logfd");
			return -errno;
		}
2265 2266
	}

2267 2268
	stat_config.output = output;

S
Stephane Eranian 已提交
2269 2270 2271
	/*
	 * let the spreadsheet do the pretty-printing
	 */
2272
	if (stat_config.csv_output) {
J
Jim Cromie 已提交
2273
		/* User explicitly passed -B? */
S
Stephane Eranian 已提交
2274 2275
		if (big_num_opt == 1) {
			fprintf(stderr, "-B option not supported with -x\n");
J
Jiri Olsa 已提交
2276 2277
			parse_options_usage(stat_usage, stat_options, "B", 1);
			parse_options_usage(NULL, stat_options, "x", 1);
2278
			goto out;
S
Stephane Eranian 已提交
2279
		} else /* Nope, so disable big number formatting */
2280
			stat_config.big_num = false;
S
Stephane Eranian 已提交
2281
	} else if (big_num_opt == 0) /* User passed --no-big-num */
2282
		stat_config.big_num = false;
S
Stephane Eranian 已提交
2283

2284 2285 2286 2287 2288 2289
	err = target__validate(&target);
	if (err) {
		target__strerror(&target, err, errbuf, BUFSIZ);
		pr_warning("%s\n", errbuf);
	}

2290
	setup_system_wide(argc);
2291

2292 2293 2294 2295
	/*
	 * Display user/system times only for single
	 * run and when there's specified tracee.
	 */
2296
	if ((stat_config.run_count == 1) && target__none(&target))
2297
		stat_config.ru_display = true;
2298

2299
	if (stat_config.run_count < 0) {
2300
		pr_err("Run count must be a positive number\n");
J
Jiri Olsa 已提交
2301
		parse_options_usage(stat_usage, stat_options, "r", 1);
2302
		goto out;
2303
	} else if (stat_config.run_count == 0) {
2304
		forever = true;
2305
		stat_config.run_count = 1;
2306
	}
2307

2308 2309 2310
	if (stat_config.walltime_run_table) {
		stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
		if (!stat_config.walltime_run) {
2311 2312 2313 2314 2315
			pr_err("failed to setup -r option");
			goto out;
		}
	}

2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
	if ((stat_config.aggr_mode == AGGR_THREAD) &&
		!target__has_task(&target)) {
		if (!target.system_wide || target.cpu_list) {
			fprintf(stderr, "The --per-thread option is only "
				"available when monitoring via -p -t -a "
				"options or only --per-thread.\n");
			parse_options_usage(NULL, stat_options, "p", 1);
			parse_options_usage(NULL, stat_options, "t", 1);
			goto out;
		}
2326 2327 2328 2329 2330 2331
	}

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

J
Jiri Olsa 已提交
2338 2339 2340
		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);
2341
		goto out;
2342 2343
	}

2344 2345
	if (add_default_attributes())
		goto out;
2346

2347 2348 2349 2350 2351 2352 2353 2354
	if (stat_config.cgroup_list) {
		if (nr_cgroups > 0) {
			pr_err("--cgroup and --for-each-cgroup cannot be used together\n");
			parse_options_usage(stat_usage, stat_options, "G", 1);
			parse_options_usage(NULL, stat_options, "for-each-cgroup", 0);
			goto out;
		}

2355
		if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,
2356 2357 2358
					  &stat_config.metric_events, true) < 0) {
			parse_options_usage(stat_usage, stat_options,
					    "for-each-cgroup", 0);
2359
			goto out;
2360
		}
2361 2362
	}

2363 2364 2365
	if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
		target.per_thread = true;

2366
	if (evlist__create_maps(evsel_list, &target) < 0) {
2367
		if (target__has_task(&target)) {
2368
			pr_err("Problems finding threads of monitor\n");
J
Jiri Olsa 已提交
2369 2370
			parse_options_usage(stat_usage, stat_options, "p", 1);
			parse_options_usage(NULL, stat_options, "t", 1);
2371
		} else if (target__has_cpu(&target)) {
2372
			perror("failed to parse CPUs map");
J
Jiri Olsa 已提交
2373 2374
			parse_options_usage(stat_usage, stat_options, "C", 1);
			parse_options_usage(NULL, stat_options, "a", 1);
2375 2376
		}
		goto out;
2377
	}
2378

2379 2380
	evlist__check_cpu_maps(evsel_list);

2381 2382 2383 2384
	/*
	 * Initialize thread_map with comm names,
	 * so we could print it out on output.
	 */
2385
	if (stat_config.aggr_mode == AGGR_THREAD) {
2386
		thread_map__read_comms(evsel_list->core.threads);
2387 2388
		if (target.system_wide) {
			if (runtime_stat_new(&stat_config,
2389
				perf_thread_map__nr(evsel_list->core.threads))) {
2390 2391 2392 2393
				goto out;
			}
		}
	}
2394

2395 2396 2397
	if (stat_config.aggr_mode == AGGR_NODE)
		cpu__setup_cpunode_map();

2398 2399 2400 2401 2402 2403 2404 2405 2406
	if (stat_config.times && interval)
		interval_count = true;
	else if (stat_config.times && !interval) {
		pr_err("interval-count option should be used together with "
				"interval-print.\n");
		parse_options_usage(stat_usage, stat_options, "interval-count", 0);
		parse_options_usage(stat_usage, stat_options, "I", 1);
		goto out;
	}
2407

2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424
	if (timeout && timeout < 100) {
		if (timeout < 10) {
			pr_err("timeout must be >= 10ms.\n");
			parse_options_usage(stat_usage, stat_options, "timeout", 0);
			goto out;
		} else
			pr_warning("timeout < 100ms. "
				   "The overhead percentage could be high in some cases. "
				   "Please proceed with caution.\n");
	}
	if (timeout && interval) {
		pr_err("timeout option is not supported with interval-print.\n");
		parse_options_usage(stat_usage, stat_options, "timeout", 0);
		parse_options_usage(stat_usage, stat_options, "I", 1);
		goto out;
	}

2425
	if (evlist__alloc_stats(evsel_list, interval))
2426
		goto out;
2427

2428
	if (perf_stat_init_aggr_mode())
2429
		goto out;
2430

2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
	/*
	 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
	 * while avoiding that older tools show confusing messages.
	 *
	 * However for pipe sessions we need to keep it zero,
	 * because script's perf_evsel__check_attr is triggered
	 * by attr->sample_type != 0, and we can't run it on
	 * stat sessions.
	 */
	stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);

I
Ingo Molnar 已提交
2442 2443 2444 2445 2446 2447
	/*
	 * 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:
	 */
2448
	atexit(sig_atexit);
2449 2450
	if (!forever)
		signal(SIGINT,  skip_signal);
2451
	signal(SIGCHLD, skip_signal);
I
Ingo Molnar 已提交
2452 2453 2454
	signal(SIGALRM, skip_signal);
	signal(SIGABRT, skip_signal);

2455 2456 2457
	if (evlist__initialize_ctlfd(evsel_list, stat_config.ctl_fd, stat_config.ctl_fd_ack))
		goto out;

2458
	status = 0;
2459 2460
	for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
		if (stat_config.run_count != 1 && verbose > 0)
2461 2462
			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
				run_idx + 1);
I
Ingo Molnar 已提交
2463

2464
		if (run_idx != 0)
2465
			evlist__reset_prev_raw_counts(evsel_list);
2466

2467
		status = run_perf_stat(argc, argv, run_idx);
2468
		if (forever && status != -1 && !interval) {
2469
			print_counters(NULL, argc, argv);
2470
			perf_stat__reset_stats();
2471
		}
2472 2473
	}

2474
	if (!forever && status != -1 && (!interval || stat_config.summary))
2475
		print_counters(NULL, argc, argv);
2476

2477 2478
	evlist__finalize_ctlfd(evsel_list);

J
Jiri Olsa 已提交
2479 2480 2481 2482
	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
2483
		 * due to /proc/sys/kernel/kptr_restrict settings and instead provide
J
Jiri Olsa 已提交
2484 2485 2486
		 * 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
2487 2488 2489 2490
		 * 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 已提交
2491
		 */
2492
		int fd = perf_data__fd(&perf_stat.data);
2493 2494 2495 2496

		err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
							 process_synthesized_event,
							 &perf_stat.session->machines.host);
J
Jiri Olsa 已提交
2497 2498 2499 2500 2501
		if (err) {
			pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
				   "older tools may produce warnings about this file\n.");
		}

2502 2503 2504 2505 2506
		if (!interval) {
			if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
				pr_err("failed to write stat round event\n");
		}

2507
		if (!perf_stat.data.is_pipe) {
2508 2509 2510
			perf_stat.session->header.data_size += perf_stat.bytes_written;
			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
		}
J
Jiri Olsa 已提交
2511

2512
		evlist__close(evsel_list);
J
Jiri Olsa 已提交
2513 2514 2515
		perf_session__delete(perf_stat.session);
	}

2516
	perf_stat__exit_aggr_mode();
2517
	evlist__free_stats(evsel_list);
2518
out:
2519
	zfree(&stat_config.walltime_run);
2520

2521 2522 2523
	if (smi_cost && smi_reset)
		sysfs__write_int(FREEZE_ON_SMI_PATH, 0);

2524
	evlist__delete(evsel_list);
2525

2526
	metricgroup__rblist_exit(&stat_config.metric_events);
2527
	runtime_stat_delete(&stat_config);
2528
	evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);
2529

2530
	return status;
2531
}