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

Commit 7ae92e74 authored by Yan, Zheng's avatar Yan, Zheng Committed by Arnaldo Carvalho de Melo
Browse files

perf stat: Check PMU cpumask file



If user doesn't explicitly specify CPU list, perf-stat only collects
events on CPUs listed in the PMU cpumask file.

Signed-off-by: default avatar"Yah, Zheng" <zheng.z.yan@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1347263631-23175-3-git-send-email-zheng.z.yan@intel.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 314d9f63
Loading
Loading
Loading
Loading
+20 −10
Original line number Original line Diff line number Diff line
@@ -215,6 +215,16 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
	evsel->priv = NULL;
	evsel->priv = NULL;
}
}


static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
{
	return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
}

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

static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[MAX_NR_CPUS];
static struct stats runtime_cycles_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
@@ -246,7 +256,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;


	if (perf_target__has_cpu(&target)) {
	if (perf_target__has_cpu(&target)) {
		ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus);
		ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
		if (ret)
		if (ret)
			goto check_ret;
			goto check_ret;
		return 0;
		return 0;
@@ -327,7 +337,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
	u64 *count = counter->counts->aggr.values;
	u64 *count = counter->counts->aggr.values;
	int i;
	int i;


	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
	if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
			       evsel_list->threads->nr, scale) < 0)
			       evsel_list->threads->nr, scale) < 0)
		return -1;
		return -1;


@@ -356,7 +366,7 @@ static int read_counter(struct perf_evsel *counter)
	u64 *count;
	u64 *count;
	int cpu;
	int cpu;


	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
			return -1;
			return -1;


@@ -495,12 +505,12 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
	if (no_aggr) {
	if (no_aggr) {
		list_for_each_entry(counter, &evsel_list->entries, node) {
		list_for_each_entry(counter, &evsel_list->entries, node) {
			read_counter(counter);
			read_counter(counter);
			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
		}
		}
	} else {
	} else {
		list_for_each_entry(counter, &evsel_list->entries, node) {
		list_for_each_entry(counter, &evsel_list->entries, node) {
			read_counter_aggr(counter);
			read_counter_aggr(counter);
			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
					     evsel_list->threads->nr);
					     evsel_list->threads->nr);
		}
		}
	}
	}
@@ -538,7 +548,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
	if (no_aggr)
	if (no_aggr)
		sprintf(cpustr, "CPU%*d%s",
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
			csv_output ? 0 : -4,
			evsel_list->cpus->map[cpu], csv_sep);
			perf_evsel__cpus(evsel)->map[cpu], csv_sep);


	fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
	fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));


@@ -750,7 +760,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
	if (no_aggr)
	if (no_aggr)
		sprintf(cpustr, "CPU%*d%s",
		sprintf(cpustr, "CPU%*d%s",
			csv_output ? 0 : -4,
			csv_output ? 0 : -4,
			evsel_list->cpus->map[cpu], csv_sep);
			perf_evsel__cpus(evsel)->map[cpu], csv_sep);
	else
	else
		cpu = 0;
		cpu = 0;


@@ -911,14 +921,14 @@ static void print_counter(struct perf_evsel *counter)
	u64 ena, run, val;
	u64 ena, run, val;
	int cpu;
	int cpu;


	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
		val = counter->counts->cpu[cpu].val;
		val = counter->counts->cpu[cpu].val;
		ena = counter->counts->cpu[cpu].ena;
		ena = counter->counts->cpu[cpu].ena;
		run = counter->counts->cpu[cpu].run;
		run = counter->counts->cpu[cpu].run;
		if (run == 0 || ena == 0) {
		if (run == 0 || ena == 0) {
			fprintf(output, "CPU%*d%s%*s%s%*s",
			fprintf(output, "CPU%*d%s%*s%s%*s",
				csv_output ? 0 : -4,
				csv_output ? 0 : -4,
				evsel_list->cpus->map[cpu], csv_sep,
				perf_evsel__cpus(counter)->map[cpu], csv_sep,
				csv_output ? 0 : 18,
				csv_output ? 0 : 18,
				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
				csv_sep,
				csv_sep,
@@ -1217,7 +1227,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)


	list_for_each_entry(pos, &evsel_list->entries, node) {
	list_for_each_entry(pos, &evsel_list->entries, node) {
		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0)
		    perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
			goto out_free_fd;
			goto out_free_fd;
	}
	}


+15 −7
Original line number Original line Diff line number Diff line
@@ -38,24 +38,19 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
	return cpus;
	return cpus;
}
}


static struct cpu_map *cpu_map__read_all_cpu_map(void)
struct cpu_map *cpu_map__read(FILE *file)
{
{
	struct cpu_map *cpus = NULL;
	struct cpu_map *cpus = NULL;
	FILE *onlnf;
	int nr_cpus = 0;
	int nr_cpus = 0;
	int *tmp_cpus = NULL, *tmp;
	int *tmp_cpus = NULL, *tmp;
	int max_entries = 0;
	int max_entries = 0;
	int n, cpu, prev;
	int n, cpu, prev;
	char sep;
	char sep;


	onlnf = fopen("/sys/devices/system/cpu/online", "r");
	if (!onlnf)
		return cpu_map__default_new();

	sep = 0;
	sep = 0;
	prev = -1;
	prev = -1;
	for (;;) {
	for (;;) {
		n = fscanf(onlnf, "%u%c", &cpu, &sep);
		n = fscanf(file, "%u%c", &cpu, &sep);
		if (n <= 0)
		if (n <= 0)
			break;
			break;
		if (prev >= 0) {
		if (prev >= 0) {
@@ -95,6 +90,19 @@ static struct cpu_map *cpu_map__read_all_cpu_map(void)
		cpus = cpu_map__default_new();
		cpus = cpu_map__default_new();
out_free_tmp:
out_free_tmp:
	free(tmp_cpus);
	free(tmp_cpus);
	return cpus;
}

static struct cpu_map *cpu_map__read_all_cpu_map(void)
{
	struct cpu_map *cpus = NULL;
	FILE *onlnf;

	onlnf = fopen("/sys/devices/system/cpu/online", "r");
	if (!onlnf)
		return cpu_map__default_new();

	cpus = cpu_map__read(onlnf);
	fclose(onlnf);
	fclose(onlnf);
	return cpus;
	return cpus;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -11,7 +11,7 @@ struct cpu_map {
struct cpu_map *cpu_map__new(const char *cpu_list);
struct cpu_map *cpu_map__new(const char *cpu_list);
struct cpu_map *cpu_map__dummy_new(void);
struct cpu_map *cpu_map__dummy_new(void);
void cpu_map__delete(struct cpu_map *map);
void cpu_map__delete(struct cpu_map *map);

struct cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);


#endif /* __PERF_CPUMAP_H */
#endif /* __PERF_CPUMAP_H */
+1 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ struct perf_evsel {
		void		*func;
		void		*func;
		void		*data;
		void		*data;
	} handler;
	} handler;
	struct cpu_map		*cpus;
	unsigned int		sample_size;
	unsigned int		sample_size;
	bool 			supported;
	bool 			supported;
	/* parse modifier helper */
	/* parse modifier helper */
+14 −4
Original line number Original line Diff line number Diff line
@@ -239,8 +239,11 @@ const char *event_type(int type)
	return "unknown";
	return "unknown";
}
}


static int add_event(struct list_head **_list, int *idx,

		     struct perf_event_attr *attr, char *name)

static int __add_event(struct list_head **_list, int *idx,
		       struct perf_event_attr *attr,
		       char *name, struct cpu_map *cpus)
{
{
	struct perf_evsel *evsel;
	struct perf_evsel *evsel;
	struct list_head *list = *_list;
	struct list_head *list = *_list;
@@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	evsel->cpus = cpus;
	if (name)
	if (name)
		evsel->name = strdup(name);
		evsel->name = strdup(name);
	list_add_tail(&evsel->node, list);
	list_add_tail(&evsel->node, list);
@@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx,
	return 0;
	return 0;
}
}


static int add_event(struct list_head **_list, int *idx,
		     struct perf_event_attr *attr, char *name)
{
	return __add_event(_list, idx, attr, name, NULL);
}

static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
{
{
	int i, j;
	int i, j;
@@ -607,8 +617,8 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
	if (perf_pmu__config(pmu, &attr, head_config))
	if (perf_pmu__config(pmu, &attr, head_config))
		return -EINVAL;
		return -EINVAL;


	return add_event(list, idx, &attr,
	return __add_event(list, idx, &attr, pmu_event_name(head_config),
			 pmu_event_name(head_config));
			   pmu->cpus);
}
}


int parse_events__modifier_group(struct list_head *list,
int parse_events__modifier_group(struct list_head *list,
Loading