Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 028c63b5 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

 into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

  - Fix perf.data size reporting in 'perf record' in no-buildid mode (He Kuang)

Infrastructure changes:

  - Protect accesses the DSO rbtrees/lists with a rw lock and reference
    count struct dso instances (Arnaldo Carvalho de Melo)

  - Export dynamic symbols used by traceevent plugins (He Kuang)

  - Add libtrace-dynamic-list file to libtraceevent's .gitignore (He Kuang)

  - Refactor shadow stats code in 'perf stat', prep work for further
    patchkits (Jiri Olsa)

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents a3d86542 d3a7c489
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
TRACEEVENT-CFLAGS
libtraceevent-dynamic-list
+13 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ endef
# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
$(call allow-override,AR,$(CROSS_COMPILE)ar)
$(call allow-override,NM,$(CROSS_COMPILE)nm)

EXT = -std=gnu99
INSTALL = install
@@ -157,8 +158,9 @@ PLUGINS_IN := $(PLUGINS:.so=-in.o)

TE_IN    := $(OUTPUT)libtraceevent-in.o
LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list

CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
CMD_TARGETS = $(LIB_FILE) $(PLUGINS) $(DYNAMIC_LIST_FILE)

TARGETS = $(CMD_TARGETS)

@@ -175,6 +177,9 @@ $(OUTPUT)libtraceevent.so: $(TE_IN)
$(OUTPUT)libtraceevent.a: $(TE_IN)
	$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^

$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS)
	$(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@)

plugins: $(PLUGINS)

__plugin_obj = $(notdir $@)
@@ -244,6 +249,13 @@ define do_install_plugins
	done
endef

define do_generate_dynamic_list_file
	(echo '{';							\
	$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;	\
	echo '};';							\
	) > $2
endef

install_lib: all_cmd install_plugins
	$(call QUIET_INSTALL, $(LIB_FILE)) \
		$(call do_install,$(LIB_FILE),$(libdir_SQ))
+12 −2
Original line number Diff line number Diff line
@@ -173,6 +173,9 @@ endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
export LIBTRACEEVENT

LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
LDFLAGS += -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)

LIBAPI = $(LIB_PATH)libapi.a
export LIBAPI

@@ -278,7 +281,7 @@ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
	$(Q)$(MAKE) $(build)=perf

$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN)
$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
	$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@

$(GTK_IN): FORCE
@@ -373,7 +376,13 @@ $(LIB_FILE): $(LIBPERF_IN)
LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)

$(LIBTRACEEVENT): FORCE
	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a plugins
	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a

libtraceevent_plugins: FORCE
	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins

$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
	$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent-dynamic-list

$(LIBTRACEEVENT)-clean:
	$(call QUIET_CLEAN, libtraceevent)
@@ -555,4 +564,5 @@ FORCE:
.PHONY: all install clean config-clean strip install-gtk
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
.PHONY: libtraceevent_plugins
+2 −4
Original line number Diff line number Diff line
@@ -345,12 +345,9 @@ static int process_buildids(struct record *rec)
	struct perf_data_file *file  = &rec->file;
	struct perf_session *session = rec->session;

	u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
	if (size == 0)
	if (file->size == 0)
		return 0;

	file->size = size;

	/*
	 * During this process, it'll load kernel map and replace the
	 * dso->long_name to a real pathname it found.  In this case
@@ -719,6 +716,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)

	if (!err && !file->is_pipe) {
		rec->session->header.data_size += rec->bytes_written;
		file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);

		if (!rec->no_buildid) {
			process_buildids(rec);
+13 −493
Original line number Diff line number Diff line
@@ -73,8 +73,8 @@ static void print_counter(struct perf_evsel *counter, char *prefix);
static void print_aggr(char *prefix);

/* Default events used for perf stat -T */
static const char * const transaction_attrs[] = {
	"task-clock",
static const char *transaction_attrs = {
	"task-clock,"
	"{"
	"instructions,"
	"cycles,"
@@ -86,8 +86,8 @@ static const char * const transaction_attrs[] = {
};

/* More limited version when the CPU does not have all events. */
static const char * const transaction_limited_attrs[] = {
	"task-clock",
static const char * transaction_limited_attrs = {
	"task-clock,"
	"{"
	"instructions,"
	"cycles,"
@@ -96,30 +96,12 @@ static const char * const transaction_limited_attrs[] = {
	"}"
};

/* must match transaction_attrs and the beginning limited_attrs */
enum {
	T_TASK_CLOCK,
	T_INSTRUCTIONS,
	T_CYCLES,
	T_CYCLES_IN_TX,
	T_TRANSACTION_START,
	T_ELISION_START,
	T_CYCLES_IN_TX_CP,
};

static struct perf_evlist	*evsel_list;

static struct target target = {
	.uid	= UINT_MAX,
};

enum aggr_mode {
	AGGR_NONE,
	AGGR_GLOBAL,
	AGGR_SOCKET,
	AGGR_CORE,
};

static int			run_count			=  1;
static bool			no_inherit			= false;
static bool			scale				=  true;
@@ -147,10 +129,6 @@ static int (*aggr_get_id)(struct cpu_map *m, int cpu);

static volatile int done = 0;

struct perf_stat {
	struct stats	  res_stats[3];
};

static inline void diff_timespec(struct timespec *r, struct timespec *a,
				 struct timespec *b)
{
@@ -180,6 +158,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)

	for (i = 0; i < 3; i++)
		init_stats(&ps->res_stats[i]);

	perf_stat_evsel_id_init(evsel);
}

static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
@@ -247,51 +227,6 @@ static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
	return -1;
}

enum {
	CTX_BIT_USER	= 1 << 0,
	CTX_BIT_KERNEL	= 1 << 1,
	CTX_BIT_HV	= 1 << 2,
	CTX_BIT_HOST	= 1 << 3,
	CTX_BIT_IDLE	= 1 << 4,
	CTX_BIT_MAX	= 1 << 5,
};

#define NUM_CTX CTX_BIT_MAX

static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_back_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_branches_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_cacherefs_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_l1_dcache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_l1_icache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_ll_cache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_itlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats walltime_nsecs_stats;
static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];

static int evsel_context(struct perf_evsel *evsel)
{
	int ctx = 0;

	if (evsel->attr.exclude_kernel)
		ctx |= CTX_BIT_KERNEL;
	if (evsel->attr.exclude_user)
		ctx |= CTX_BIT_USER;
	if (evsel->attr.exclude_hv)
		ctx |= CTX_BIT_HV;
	if (evsel->attr.exclude_host)
		ctx |= CTX_BIT_HOST;
	if (evsel->attr.exclude_idle)
		ctx |= CTX_BIT_IDLE;

	return ctx;
}

static void perf_stat__reset_stats(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel;
@@ -301,23 +236,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
		perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel));
	}

	memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
	memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
	memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats));
	memset(runtime_stalled_cycles_back_stats, 0, sizeof(runtime_stalled_cycles_back_stats));
	memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats));
	memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats));
	memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats));
	memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats));
	memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
	memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
	memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
	memset(runtime_cycles_in_tx_stats, 0,
			sizeof(runtime_cycles_in_tx_stats));
	memset(runtime_transaction_stats, 0,
		sizeof(runtime_transaction_stats));
	memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
	memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
	perf_stat__reset_shadow_stats();
}

static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -354,72 +273,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)
	return 0;
}

static struct perf_evsel *nth_evsel(int n)
{
	static struct perf_evsel **array;
	static int array_len;
	struct perf_evsel *ev;
	int j;

	/* Assumes this only called when evsel_list does not change anymore. */
	if (!array) {
		evlist__for_each(evsel_list, ev)
			array_len++;
		array = malloc(array_len * sizeof(void *));
		if (!array)
			exit(ENOMEM);
		j = 0;
		evlist__for_each(evsel_list, ev)
			array[j++] = ev;
	}
	if (n < array_len)
		return array[n];
	return NULL;
}

/*
 * Update various tracking values we maintain to print
 * more semantic information such as miss/hit ratios,
 * instruction rates, etc:
 */
static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
				int cpu)
{
	int ctx = evsel_context(counter);

	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
		update_stats(&runtime_nsecs_stats[cpu], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
		update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
	else if (transaction_run &&
		 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
		update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
	else if (transaction_run &&
		 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
		update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
	else if (transaction_run &&
		 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
		update_stats(&runtime_elision_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
		update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
		update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
		update_stats(&runtime_branches_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
		update_stats(&runtime_cacherefs_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
		update_stats(&runtime_l1_dcache_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
		update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
		update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
		update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]);
	else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
		update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]);
}

static void zero_per_pkg(struct perf_evsel *counter)
{
	if (counter->per_pkg_mask)
@@ -480,7 +333,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
		perf_counts_values__scale(count, scale, NULL);
		evsel->counts->cpu[cpu] = *count;
		if (aggr_mode == AGGR_NONE)
			update_shadow_stats(evsel, count->values, cpu);
			perf_stat__update_shadow_stats(evsel, count->values, cpu);
		break;
	case AGGR_GLOBAL:
		aggr->val += count->val;
@@ -528,7 +381,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
	/*
	 * Save the full runtime - to allow normalization during printout:
	 */
	update_shadow_stats(counter, count, 0);
	perf_stat__update_shadow_stats(counter, count, 0);

	return 0;
}
@@ -906,200 +759,11 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
		fprintf(output, "                                   ");
}

/* used for get_ratio_color() */
enum grc_type {
	GRC_STALLED_CYCLES_FE,
	GRC_STALLED_CYCLES_BE,
	GRC_CACHE_MISSES,
	GRC_MAX_NR
};

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

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

	return color;
}

static void print_stalled_cycles_frontend(int cpu,
					  struct perf_evsel *evsel
					  __maybe_unused, double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_cycles_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);

	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " frontend cycles idle   ");
}

static void print_stalled_cycles_backend(int cpu,
					 struct perf_evsel *evsel
					 __maybe_unused, double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_cycles_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);

	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " backend  cycles idle   ");
}

static void print_branch_misses(int cpu,
				struct perf_evsel *evsel __maybe_unused,
				double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_branches_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

	fprintf(output, " #  ");
	color_fprintf(output, color, "%6.2f%%", ratio);
	fprintf(output, " of all branches        ");
}

static void print_l1_dcache_misses(int cpu,
				   struct perf_evsel *evsel __maybe_unused,
				   double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_l1_dcache_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

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

static void print_l1_icache_misses(int cpu,
				   struct perf_evsel *evsel __maybe_unused,
				   double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_l1_icache_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

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

static void print_dtlb_cache_misses(int cpu,
				    struct perf_evsel *evsel __maybe_unused,
				    double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_dtlb_cache_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

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

static void print_itlb_cache_misses(int cpu,
				    struct perf_evsel *evsel __maybe_unused,
				    double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_itlb_cache_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

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

static void print_ll_cache_misses(int cpu,
				  struct perf_evsel *evsel __maybe_unused,
				  double avg)
{
	double total, ratio = 0.0;
	const char *color;
	int ctx = evsel_context(evsel);

	total = avg_stats(&runtime_ll_cache_stats[ctx][cpu]);

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

	color = get_ratio_color(GRC_CACHE_MISSES, ratio);

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

static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
{
	double total, ratio = 0.0, total2;
	double sc =  evsel->scale;
	const char *fmt;
	int cpu = cpu_map__id_to_cpu(id);
	int ctx = evsel_context(evsel);

	if (csv_output) {
		fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
@@ -1130,138 +794,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
	if (csv_output || interval)
		return;

	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
		total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
		if (total) {
			ratio = avg / total;
			fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
		} else {
			fprintf(output, "                                   ");
		}
		total = avg_stats(&runtime_stalled_cycles_front_stats[ctx][cpu]);
		total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[ctx][cpu]));

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

	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
			runtime_branches_stats[ctx][cpu].n != 0) {
		print_branch_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_l1_dcache_stats[ctx][cpu].n != 0) {
		print_l1_dcache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_l1_icache_stats[ctx][cpu].n != 0) {
		print_l1_icache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_dtlb_cache_stats[ctx][cpu].n != 0) {
		print_dtlb_cache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_itlb_cache_stats[ctx][cpu].n != 0) {
		print_itlb_cache_misses(cpu, evsel, avg);
	} else if (
		evsel->attr.type == PERF_TYPE_HW_CACHE &&
		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
					((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
					((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
			runtime_ll_cache_stats[ctx][cpu].n != 0) {
		print_ll_cache_misses(cpu, evsel, avg);
	} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
			runtime_cacherefs_stats[ctx][cpu].n != 0) {
		total = avg_stats(&runtime_cacherefs_stats[ctx][cpu]);

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

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

	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
		print_stalled_cycles_frontend(cpu, evsel, avg);
	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
		print_stalled_cycles_backend(cpu, evsel, avg);
	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
		total = avg_stats(&runtime_nsecs_stats[cpu]);

		if (total) {
			ratio = avg / total;
			fprintf(output, " # %8.3f GHz                    ", ratio);
		} else {
			fprintf(output, "                                   ");
		}
	} else if (transaction_run &&
		   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
		total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
		if (total)
			fprintf(output,
				" #   %5.2f%% transactional cycles   ",
				100.0 * (avg / total));
	} else if (transaction_run &&
		   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX_CP))) {
		total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
		total2 = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
		if (total2 < avg)
			total2 = avg;
		if (total)
			fprintf(output,
				" #   %5.2f%% aborted cycles         ",
				100.0 * ((total2-avg) / total));
	} else if (transaction_run &&
		   perf_evsel__cmp(evsel, nth_evsel(T_TRANSACTION_START)) &&
		   avg > 0 &&
		   runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
		total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);

		if (total)
			ratio = total / avg;

		fprintf(output, " # %8.0f cycles / transaction   ", ratio);
	} else if (transaction_run &&
		   perf_evsel__cmp(evsel, nth_evsel(T_ELISION_START)) &&
		   avg > 0 &&
		   runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
		total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);

		if (total)
			ratio = total / avg;

		fprintf(output, " # %8.0f cycles / elision       ", ratio);
	} else if (runtime_nsecs_stats[cpu].n != 0) {
		char unit = 'M';

		total = avg_stats(&runtime_nsecs_stats[cpu]);

		if (total)
			ratio = 1000.0 * avg / total;
		if (ratio < 0.001) {
			ratio *= 1000;
			unit = 'K';
		}

		fprintf(output, " # %8.3f %c/sec                  ", ratio, unit);
	} else {
		fprintf(output, "                                   ");
	}
	perf_stat__print_shadow_stats(output, evsel, avg, cpu, aggr_mode);
}

static void print_aggr(char *prefix)
@@ -1576,17 +1109,6 @@ static int perf_stat_init_aggr_mode(void)
	return 0;
}

static int setup_events(const char * const *attrs, unsigned len)
{
	unsigned i;

	for (i = 0; i < len; i++) {
		if (parse_events(evsel_list, attrs[i], NULL))
			return -1;
	}
	return 0;
}

/*
 * Add default attributes, if there were no attributes specified or
 * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1708,12 +1230,10 @@ static int add_default_attributes(void)
		int err;
		if (pmu_have_event("cpu", "cycles-ct") &&
		    pmu_have_event("cpu", "el-start"))
			err = setup_events(transaction_attrs,
					ARRAY_SIZE(transaction_attrs));
			err = parse_events(evsel_list, transaction_attrs, NULL);
		else
			err = setup_events(transaction_limited_attrs,
				 ARRAY_SIZE(transaction_limited_attrs));
		if (err < 0) {
			err = parse_events(evsel_list, transaction_limited_attrs, NULL);
		if (err) {
			fprintf(stderr, "Cannot set up transaction events\n");
			return -1;
		}
Loading