diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2012-09-10 03:53:50 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-17 12:12:02 -0400 |
commit | 7ae92e744e3fb389afb1e24920ecda331d360c61 (patch) | |
tree | 46c5d4616a003011a1237ed8d31592a662cf9720 /tools/perf/util | |
parent | 314d9f63f385096580e9e2a06eaa0745d92fe4ac (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>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/cpumap.c | 22 | ||||
-rw-r--r-- | tools/perf/util/cpumap.h | 2 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 1 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 18 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 30 | ||||
-rw-r--r-- | tools/perf/util/pmu.h | 1 |
6 files changed, 62 insertions, 12 deletions
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 | ||
41 | static struct cpu_map *cpu_map__read_all_cpu_map(void) | 41 | struct 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(); |
96 | out_free_tmp: | 91 | out_free_tmp: |
97 | free(tmp_cpus); | 92 | free(tmp_cpus); |
93 | return cpus; | ||
94 | } | ||
95 | |||
96 | static 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 { | |||
11 | struct cpu_map *cpu_map__new(const char *cpu_list); | 11 | struct cpu_map *cpu_map__new(const char *cpu_list); |
12 | struct cpu_map *cpu_map__dummy_new(void); | 12 | struct cpu_map *cpu_map__dummy_new(void); |
13 | void cpu_map__delete(struct cpu_map *map); | 13 | void cpu_map__delete(struct cpu_map *map); |
14 | 14 | struct cpu_map *cpu_map__read(FILE *file); | |
15 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 15 | size_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 | ||
242 | static int add_event(struct list_head **_list, int *idx, | 242 | |
243 | struct perf_event_attr *attr, char *name) | 243 | |
244 | static 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 | ||
274 | static 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 | |||
270 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) | 280 | static 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 | ||
614 | int parse_events__modifier_group(struct list_head *list, | 624 | int 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 | ||
257 | static 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 | |||
256 | static struct perf_pmu *pmu_lookup(char *name) | 284 | static 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 { | |||
28 | struct perf_pmu { | 28 | struct 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; |