aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2012-09-10 03:53:50 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-09-17 12:12:02 -0400
commit7ae92e744e3fb389afb1e24920ecda331d360c61 (patch)
tree46c5d4616a003011a1237ed8d31592a662cf9720
parent314d9f63f385096580e9e2a06eaa0745d92fe4ac (diff)
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: "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: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-stat.c30
-rw-r--r--tools/perf/util/cpumap.c22
-rw-r--r--tools/perf/util/cpumap.h2
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/parse-events.c18
-rw-r--r--tools/perf/util/pmu.c30
-rw-r--r--tools/perf/util/pmu.h1
7 files changed, 82 insertions, 22 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3c43a3578f3..e0f65fe6594 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -215,6 +215,16 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
215 evsel->priv = NULL; 215 evsel->priv = NULL;
216} 216}
217 217
218static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
219{
220 return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
221}
222
223static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
224{
225 return perf_evsel__cpus(evsel)->nr;
226}
227
218static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 228static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
219static struct stats runtime_cycles_stats[MAX_NR_CPUS]; 229static struct stats runtime_cycles_stats[MAX_NR_CPUS];
220static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS]; 230static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
@@ -246,7 +256,7 @@ retry:
246 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; 256 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
247 257
248 if (perf_target__has_cpu(&target)) { 258 if (perf_target__has_cpu(&target)) {
249 ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus); 259 ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
250 if (ret) 260 if (ret)
251 goto check_ret; 261 goto check_ret;
252 return 0; 262 return 0;
@@ -327,7 +337,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
327 u64 *count = counter->counts->aggr.values; 337 u64 *count = counter->counts->aggr.values;
328 int i; 338 int i;
329 339
330 if (__perf_evsel__read(counter, evsel_list->cpus->nr, 340 if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
331 evsel_list->threads->nr, scale) < 0) 341 evsel_list->threads->nr, scale) < 0)
332 return -1; 342 return -1;
333 343
@@ -356,7 +366,7 @@ static int read_counter(struct perf_evsel *counter)
356 u64 *count; 366 u64 *count;
357 int cpu; 367 int cpu;
358 368
359 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 369 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
360 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 370 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
361 return -1; 371 return -1;
362 372
@@ -495,12 +505,12 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
495 if (no_aggr) { 505 if (no_aggr) {
496 list_for_each_entry(counter, &evsel_list->entries, node) { 506 list_for_each_entry(counter, &evsel_list->entries, node) {
497 read_counter(counter); 507 read_counter(counter);
498 perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 508 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
499 } 509 }
500 } else { 510 } else {
501 list_for_each_entry(counter, &evsel_list->entries, node) { 511 list_for_each_entry(counter, &evsel_list->entries, node) {
502 read_counter_aggr(counter); 512 read_counter_aggr(counter);
503 perf_evsel__close_fd(counter, evsel_list->cpus->nr, 513 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
504 evsel_list->threads->nr); 514 evsel_list->threads->nr);
505 } 515 }
506 } 516 }
@@ -538,7 +548,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
538 if (no_aggr) 548 if (no_aggr)
539 sprintf(cpustr, "CPU%*d%s", 549 sprintf(cpustr, "CPU%*d%s",
540 csv_output ? 0 : -4, 550 csv_output ? 0 : -4,
541 evsel_list->cpus->map[cpu], csv_sep); 551 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
542 552
543 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel)); 553 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
544 554
@@ -750,7 +760,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
750 if (no_aggr) 760 if (no_aggr)
751 sprintf(cpustr, "CPU%*d%s", 761 sprintf(cpustr, "CPU%*d%s",
752 csv_output ? 0 : -4, 762 csv_output ? 0 : -4,
753 evsel_list->cpus->map[cpu], csv_sep); 763 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
754 else 764 else
755 cpu = 0; 765 cpu = 0;
756 766
@@ -911,14 +921,14 @@ static void print_counter(struct perf_evsel *counter)
911 u64 ena, run, val; 921 u64 ena, run, val;
912 int cpu; 922 int cpu;
913 923
914 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 924 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
915 val = counter->counts->cpu[cpu].val; 925 val = counter->counts->cpu[cpu].val;
916 ena = counter->counts->cpu[cpu].ena; 926 ena = counter->counts->cpu[cpu].ena;
917 run = counter->counts->cpu[cpu].run; 927 run = counter->counts->cpu[cpu].run;
918 if (run == 0 || ena == 0) { 928 if (run == 0 || ena == 0) {
919 fprintf(output, "CPU%*d%s%*s%s%*s", 929 fprintf(output, "CPU%*d%s%*s%s%*s",
920 csv_output ? 0 : -4, 930 csv_output ? 0 : -4,
921 evsel_list->cpus->map[cpu], csv_sep, 931 perf_evsel__cpus(counter)->map[cpu], csv_sep,
922 csv_output ? 0 : 18, 932 csv_output ? 0 : 18,
923 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 933 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
924 csv_sep, 934 csv_sep,
@@ -1217,7 +1227,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1217 1227
1218 list_for_each_entry(pos, &evsel_list->entries, node) { 1228 list_for_each_entry(pos, &evsel_list->entries, node) {
1219 if (perf_evsel__alloc_stat_priv(pos) < 0 || 1229 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
1220 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) 1230 perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
1221 goto out_free_fd; 1231 goto out_free_fd;
1222 } 1232 }
1223 1233
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index adc72f09914..2b32ffa9ebd 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -38,24 +38,19 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
38 return cpus; 38 return cpus;
39} 39}
40 40
41static struct cpu_map *cpu_map__read_all_cpu_map(void) 41struct cpu_map *cpu_map__read(FILE *file)
42{ 42{
43 struct cpu_map *cpus = NULL; 43 struct cpu_map *cpus = NULL;
44 FILE *onlnf;
45 int nr_cpus = 0; 44 int nr_cpus = 0;
46 int *tmp_cpus = NULL, *tmp; 45 int *tmp_cpus = NULL, *tmp;
47 int max_entries = 0; 46 int max_entries = 0;
48 int n, cpu, prev; 47 int n, cpu, prev;
49 char sep; 48 char sep;
50 49
51 onlnf = fopen("/sys/devices/system/cpu/online", "r");
52 if (!onlnf)
53 return cpu_map__default_new();
54
55 sep = 0; 50 sep = 0;
56 prev = -1; 51 prev = -1;
57 for (;;) { 52 for (;;) {
58 n = fscanf(onlnf, "%u%c", &cpu, &sep); 53 n = fscanf(file, "%u%c", &cpu, &sep);
59 if (n <= 0) 54 if (n <= 0)
60 break; 55 break;
61 if (prev >= 0) { 56 if (prev >= 0) {
@@ -95,6 +90,19 @@ static struct cpu_map *cpu_map__read_all_cpu_map(void)
95 cpus = cpu_map__default_new(); 90 cpus = cpu_map__default_new();
96out_free_tmp: 91out_free_tmp:
97 free(tmp_cpus); 92 free(tmp_cpus);
93 return cpus;
94}
95
96static struct cpu_map *cpu_map__read_all_cpu_map(void)
97{
98 struct cpu_map *cpus = NULL;
99 FILE *onlnf;
100
101 onlnf = fopen("/sys/devices/system/cpu/online", "r");
102 if (!onlnf)
103 return cpu_map__default_new();
104
105 cpus = cpu_map__read(onlnf);
98 fclose(onlnf); 106 fclose(onlnf);
99 return cpus; 107 return cpus;
100} 108}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index c41518573c6..17b5264f643 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -11,7 +11,7 @@ struct cpu_map {
11struct cpu_map *cpu_map__new(const char *cpu_list); 11struct cpu_map *cpu_map__new(const char *cpu_list);
12struct cpu_map *cpu_map__dummy_new(void); 12struct cpu_map *cpu_map__dummy_new(void);
13void cpu_map__delete(struct cpu_map *map); 13void cpu_map__delete(struct cpu_map *map);
14 14struct cpu_map *cpu_map__read(FILE *file);
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16 16
17#endif /* __PERF_CPUMAP_H */ 17#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index dc40fe32210..93876bad2e5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -66,6 +66,7 @@ struct perf_evsel {
66 void *func; 66 void *func;
67 void *data; 67 void *data;
68 } handler; 68 } handler;
69 struct cpu_map *cpus;
69 unsigned int sample_size; 70 unsigned int sample_size;
70 bool supported; 71 bool supported;
71 /* parse modifier helper */ 72 /* parse modifier helper */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 44afcf40f79..bf5d033ee1b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -239,8 +239,11 @@ const char *event_type(int type)
239 return "unknown"; 239 return "unknown";
240} 240}
241 241
242static int add_event(struct list_head **_list, int *idx, 242
243 struct perf_event_attr *attr, char *name) 243
244static int __add_event(struct list_head **_list, int *idx,
245 struct perf_event_attr *attr,
246 char *name, struct cpu_map *cpus)
244{ 247{
245 struct perf_evsel *evsel; 248 struct perf_evsel *evsel;
246 struct list_head *list = *_list; 249 struct list_head *list = *_list;
@@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx,
260 return -ENOMEM; 263 return -ENOMEM;
261 } 264 }
262 265
266 evsel->cpus = cpus;
263 if (name) 267 if (name)
264 evsel->name = strdup(name); 268 evsel->name = strdup(name);
265 list_add_tail(&evsel->node, list); 269 list_add_tail(&evsel->node, list);
@@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx,
267 return 0; 271 return 0;
268} 272}
269 273
274static int add_event(struct list_head **_list, int *idx,
275 struct perf_event_attr *attr, char *name)
276{
277 return __add_event(_list, idx, attr, name, NULL);
278}
279
270static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 280static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
271{ 281{
272 int i, j; 282 int i, j;
@@ -607,8 +617,8 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
607 if (perf_pmu__config(pmu, &attr, head_config)) 617 if (perf_pmu__config(pmu, &attr, head_config))
608 return -EINVAL; 618 return -EINVAL;
609 619
610 return add_event(list, idx, &attr, 620 return __add_event(list, idx, &attr, pmu_event_name(head_config),
611 pmu_event_name(head_config)); 621 pmu->cpus);
612} 622}
613 623
614int parse_events__modifier_group(struct list_head *list, 624int parse_events__modifier_group(struct list_head *list,
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 6631d828db3..8a2229da594 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -9,6 +9,7 @@
9#include "util.h" 9#include "util.h"
10#include "pmu.h" 10#include "pmu.h"
11#include "parse-events.h" 11#include "parse-events.h"
12#include "cpumap.h"
12 13
13#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" 14#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
14 15
@@ -253,6 +254,33 @@ static void pmu_read_sysfs(void)
253 closedir(dir); 254 closedir(dir);
254} 255}
255 256
257static struct cpu_map *pmu_cpumask(char *name)
258{
259 struct stat st;
260 char path[PATH_MAX];
261 const char *sysfs;
262 FILE *file;
263 struct cpu_map *cpus;
264
265 sysfs = sysfs_find_mountpoint();
266 if (!sysfs)
267 return NULL;
268
269 snprintf(path, PATH_MAX,
270 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
271
272 if (stat(path, &st) < 0)
273 return NULL;
274
275 file = fopen(path, "r");
276 if (!file)
277 return NULL;
278
279 cpus = cpu_map__read(file);
280 fclose(file);
281 return cpus;
282}
283
256static struct perf_pmu *pmu_lookup(char *name) 284static struct perf_pmu *pmu_lookup(char *name)
257{ 285{
258 struct perf_pmu *pmu; 286 struct perf_pmu *pmu;
@@ -275,6 +303,8 @@ static struct perf_pmu *pmu_lookup(char *name)
275 if (!pmu) 303 if (!pmu)
276 return NULL; 304 return NULL;
277 305
306 pmu->cpus = pmu_cpumask(name);
307
278 pmu_aliases(name, &aliases); 308 pmu_aliases(name, &aliases);
279 309
280 INIT_LIST_HEAD(&pmu->format); 310 INIT_LIST_HEAD(&pmu->format);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 47f68d3cc5d..53c7794fc4b 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -28,6 +28,7 @@ struct perf_pmu__alias {
28struct perf_pmu { 28struct perf_pmu {
29 char *name; 29 char *name;
30 __u32 type; 30 __u32 type;
31 struct cpu_map *cpus;
31 struct list_head format; 32 struct list_head format;
32 struct list_head aliases; 33 struct list_head aliases;
33 struct list_head list; 34 struct list_head list;