diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 147 |
1 files changed, 92 insertions, 55 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 044178408783..a587d41ae3c9 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -1,23 +1,21 @@ | |||
1 | 1 | ||
2 | #include "../perf.h" | ||
3 | #include "util.h" | 2 | #include "util.h" |
3 | #include "../perf.h" | ||
4 | #include "parse-options.h" | 4 | #include "parse-options.h" |
5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
6 | #include "exec_cmd.h" | 6 | #include "exec_cmd.h" |
7 | #include "string.h" | 7 | #include "string.h" |
8 | #include "cache.h" | 8 | #include "cache.h" |
9 | 9 | ||
10 | extern char *strcasestr(const char *haystack, const char *needle); | ||
11 | |||
12 | int nr_counters; | 10 | int nr_counters; |
13 | 11 | ||
14 | struct perf_counter_attr attrs[MAX_COUNTERS]; | 12 | struct perf_counter_attr attrs[MAX_COUNTERS]; |
15 | 13 | ||
16 | struct event_symbol { | 14 | struct event_symbol { |
17 | u8 type; | 15 | u8 type; |
18 | u64 config; | 16 | u64 config; |
19 | char *symbol; | 17 | const char *symbol; |
20 | char *alias; | 18 | const char *alias; |
21 | }; | 19 | }; |
22 | 20 | ||
23 | char debugfs_path[MAXPATHLEN]; | 21 | char debugfs_path[MAXPATHLEN]; |
@@ -51,7 +49,7 @@ static struct event_symbol event_symbols[] = { | |||
51 | #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) | 49 | #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) |
52 | #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) | 50 | #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) |
53 | 51 | ||
54 | static char *hw_event_names[] = { | 52 | static const char *hw_event_names[] = { |
55 | "cycles", | 53 | "cycles", |
56 | "instructions", | 54 | "instructions", |
57 | "cache-references", | 55 | "cache-references", |
@@ -61,7 +59,7 @@ static char *hw_event_names[] = { | |||
61 | "bus-cycles", | 59 | "bus-cycles", |
62 | }; | 60 | }; |
63 | 61 | ||
64 | static char *sw_event_names[] = { | 62 | static const char *sw_event_names[] = { |
65 | "cpu-clock-msecs", | 63 | "cpu-clock-msecs", |
66 | "task-clock-msecs", | 64 | "task-clock-msecs", |
67 | "page-faults", | 65 | "page-faults", |
@@ -73,7 +71,7 @@ static char *sw_event_names[] = { | |||
73 | 71 | ||
74 | #define MAX_ALIASES 8 | 72 | #define MAX_ALIASES 8 |
75 | 73 | ||
76 | static char *hw_cache[][MAX_ALIASES] = { | 74 | static const char *hw_cache[][MAX_ALIASES] = { |
77 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, | 75 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, |
78 | { "L1-icache", "l1-i", "l1i", "L1-instruction", }, | 76 | { "L1-icache", "l1-i", "l1i", "L1-instruction", }, |
79 | { "LLC", "L2" }, | 77 | { "LLC", "L2" }, |
@@ -82,13 +80,13 @@ static char *hw_cache[][MAX_ALIASES] = { | |||
82 | { "branch", "branches", "bpu", "btb", "bpc", }, | 80 | { "branch", "branches", "bpu", "btb", "bpc", }, |
83 | }; | 81 | }; |
84 | 82 | ||
85 | static char *hw_cache_op[][MAX_ALIASES] = { | 83 | static const char *hw_cache_op[][MAX_ALIASES] = { |
86 | { "load", "loads", "read", }, | 84 | { "load", "loads", "read", }, |
87 | { "store", "stores", "write", }, | 85 | { "store", "stores", "write", }, |
88 | { "prefetch", "prefetches", "speculative-read", "speculative-load", }, | 86 | { "prefetch", "prefetches", "speculative-read", "speculative-load", }, |
89 | }; | 87 | }; |
90 | 88 | ||
91 | static char *hw_cache_result[][MAX_ALIASES] = { | 89 | static const char *hw_cache_result[][MAX_ALIASES] = { |
92 | { "refs", "Reference", "ops", "access", }, | 90 | { "refs", "Reference", "ops", "access", }, |
93 | { "misses", "miss", }, | 91 | { "misses", "miss", }, |
94 | }; | 92 | }; |
@@ -113,11 +111,9 @@ static unsigned long hw_cache_stat[C(MAX)] = { | |||
113 | [C(BPU)] = (CACHE_READ), | 111 | [C(BPU)] = (CACHE_READ), |
114 | }; | 112 | }; |
115 | 113 | ||
116 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \ | 114 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ |
117 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ | 115 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ |
118 | if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \ | 116 | if (sys_dirent.d_type == DT_DIR && \ |
119 | sys_dirent.d_name) && \ | ||
120 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
121 | (strcmp(sys_dirent.d_name, ".")) && \ | 117 | (strcmp(sys_dirent.d_name, ".")) && \ |
122 | (strcmp(sys_dirent.d_name, ".."))) | 118 | (strcmp(sys_dirent.d_name, ".."))) |
123 | 119 | ||
@@ -136,11 +132,9 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) | |||
136 | return 0; | 132 | return 0; |
137 | } | 133 | } |
138 | 134 | ||
139 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \ | 135 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ |
140 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ | 136 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ |
141 | if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \ | 137 | if (evt_dirent.d_type == DT_DIR && \ |
142 | sys_dirent.d_name, evt_dirent.d_name) && \ | ||
143 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
144 | (strcmp(evt_dirent.d_name, ".")) && \ | 138 | (strcmp(evt_dirent.d_name, ".")) && \ |
145 | (strcmp(evt_dirent.d_name, "..")) && \ | 139 | (strcmp(evt_dirent.d_name, "..")) && \ |
146 | (!tp_event_has_id(&sys_dirent, &evt_dirent))) | 140 | (!tp_event_has_id(&sys_dirent, &evt_dirent))) |
@@ -158,34 +152,39 @@ int valid_debugfs_mount(const char *debugfs) | |||
158 | return 0; | 152 | return 0; |
159 | } | 153 | } |
160 | 154 | ||
161 | static char *tracepoint_id_to_name(u64 config) | 155 | struct tracepoint_path *tracepoint_id_to_path(u64 config) |
162 | { | 156 | { |
163 | static char tracepoint_name[2 * MAX_EVENT_LENGTH]; | 157 | struct tracepoint_path *path = NULL; |
164 | DIR *sys_dir, *evt_dir; | 158 | DIR *sys_dir, *evt_dir; |
165 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 159 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
166 | struct stat st; | ||
167 | char id_buf[4]; | 160 | char id_buf[4]; |
168 | int fd; | 161 | int sys_dir_fd, fd; |
169 | u64 id; | 162 | u64 id; |
170 | char evt_path[MAXPATHLEN]; | 163 | char evt_path[MAXPATHLEN]; |
171 | 164 | ||
172 | if (valid_debugfs_mount(debugfs_path)) | 165 | if (valid_debugfs_mount(debugfs_path)) |
173 | return "unkown"; | 166 | return NULL; |
174 | 167 | ||
175 | sys_dir = opendir(debugfs_path); | 168 | sys_dir = opendir(debugfs_path); |
176 | if (!sys_dir) | 169 | if (!sys_dir) |
177 | goto cleanup; | 170 | goto cleanup; |
178 | 171 | sys_dir_fd = dirfd(sys_dir); | |
179 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | 172 | |
180 | evt_dir = opendir(evt_path); | 173 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { |
181 | if (!evt_dir) | 174 | int dfd = openat(sys_dir_fd, sys_dirent.d_name, |
182 | goto cleanup; | 175 | O_RDONLY|O_DIRECTORY), evt_dir_fd; |
183 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | 176 | if (dfd == -1) |
184 | evt_path, st) { | 177 | continue; |
185 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", | 178 | evt_dir = fdopendir(dfd); |
186 | debugfs_path, sys_dirent.d_name, | 179 | if (!evt_dir) { |
180 | close(dfd); | ||
181 | continue; | ||
182 | } | ||
183 | evt_dir_fd = dirfd(evt_dir); | ||
184 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | ||
185 | snprintf(evt_path, MAXPATHLEN, "%s/id", | ||
187 | evt_dirent.d_name); | 186 | evt_dirent.d_name); |
188 | fd = open(evt_path, O_RDONLY); | 187 | fd = openat(evt_dir_fd, evt_path, O_RDONLY); |
189 | if (fd < 0) | 188 | if (fd < 0) |
190 | continue; | 189 | continue; |
191 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { | 190 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { |
@@ -197,10 +196,23 @@ static char *tracepoint_id_to_name(u64 config) | |||
197 | if (id == config) { | 196 | if (id == config) { |
198 | closedir(evt_dir); | 197 | closedir(evt_dir); |
199 | closedir(sys_dir); | 198 | closedir(sys_dir); |
200 | snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH, | 199 | path = calloc(1, sizeof(path)); |
201 | "%s:%s", sys_dirent.d_name, | 200 | path->system = malloc(MAX_EVENT_LENGTH); |
202 | evt_dirent.d_name); | 201 | if (!path->system) { |
203 | return tracepoint_name; | 202 | free(path); |
203 | return NULL; | ||
204 | } | ||
205 | path->name = malloc(MAX_EVENT_LENGTH); | ||
206 | if (!path->name) { | ||
207 | free(path->system); | ||
208 | free(path); | ||
209 | return NULL; | ||
210 | } | ||
211 | strncpy(path->system, sys_dirent.d_name, | ||
212 | MAX_EVENT_LENGTH); | ||
213 | strncpy(path->name, evt_dirent.d_name, | ||
214 | MAX_EVENT_LENGTH); | ||
215 | return path; | ||
204 | } | 216 | } |
205 | } | 217 | } |
206 | closedir(evt_dir); | 218 | closedir(evt_dir); |
@@ -208,7 +220,25 @@ static char *tracepoint_id_to_name(u64 config) | |||
208 | 220 | ||
209 | cleanup: | 221 | cleanup: |
210 | closedir(sys_dir); | 222 | closedir(sys_dir); |
211 | return "unkown"; | 223 | return NULL; |
224 | } | ||
225 | |||
226 | #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) | ||
227 | static const char *tracepoint_id_to_name(u64 config) | ||
228 | { | ||
229 | static char buf[TP_PATH_LEN]; | ||
230 | struct tracepoint_path *path; | ||
231 | |||
232 | path = tracepoint_id_to_path(config); | ||
233 | if (path) { | ||
234 | snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); | ||
235 | free(path->name); | ||
236 | free(path->system); | ||
237 | free(path); | ||
238 | } else | ||
239 | snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); | ||
240 | |||
241 | return buf; | ||
212 | } | 242 | } |
213 | 243 | ||
214 | static int is_cache_op_valid(u8 cache_type, u8 cache_op) | 244 | static int is_cache_op_valid(u8 cache_type, u8 cache_op) |
@@ -235,7 +265,7 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) | |||
235 | return name; | 265 | return name; |
236 | } | 266 | } |
237 | 267 | ||
238 | char *event_name(int counter) | 268 | const char *event_name(int counter) |
239 | { | 269 | { |
240 | u64 config = attrs[counter].config; | 270 | u64 config = attrs[counter].config; |
241 | int type = attrs[counter].type; | 271 | int type = attrs[counter].type; |
@@ -243,7 +273,7 @@ char *event_name(int counter) | |||
243 | return __event_name(type, config); | 273 | return __event_name(type, config); |
244 | } | 274 | } |
245 | 275 | ||
246 | char *__event_name(int type, u64 config) | 276 | const char *__event_name(int type, u64 config) |
247 | { | 277 | { |
248 | static char buf[32]; | 278 | static char buf[32]; |
249 | 279 | ||
@@ -294,7 +324,7 @@ char *__event_name(int type, u64 config) | |||
294 | return "unknown"; | 324 | return "unknown"; |
295 | } | 325 | } |
296 | 326 | ||
297 | static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) | 327 | static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) |
298 | { | 328 | { |
299 | int i, j; | 329 | int i, j; |
300 | int n, longest = -1; | 330 | int n, longest = -1; |
@@ -598,7 +628,7 @@ static void print_tracepoint_events(void) | |||
598 | { | 628 | { |
599 | DIR *sys_dir, *evt_dir; | 629 | DIR *sys_dir, *evt_dir; |
600 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 630 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
601 | struct stat st; | 631 | int sys_dir_fd; |
602 | char evt_path[MAXPATHLEN]; | 632 | char evt_path[MAXPATHLEN]; |
603 | 633 | ||
604 | if (valid_debugfs_mount(debugfs_path)) | 634 | if (valid_debugfs_mount(debugfs_path)) |
@@ -607,16 +637,23 @@ static void print_tracepoint_events(void) | |||
607 | sys_dir = opendir(debugfs_path); | 637 | sys_dir = opendir(debugfs_path); |
608 | if (!sys_dir) | 638 | if (!sys_dir) |
609 | goto cleanup; | 639 | goto cleanup; |
610 | 640 | sys_dir_fd = dirfd(sys_dir); | |
611 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | 641 | |
612 | evt_dir = opendir(evt_path); | 642 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { |
613 | if (!evt_dir) | 643 | int dfd = openat(sys_dir_fd, sys_dirent.d_name, |
614 | goto cleanup; | 644 | O_RDONLY|O_DIRECTORY), evt_dir_fd; |
615 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | 645 | if (dfd == -1) |
616 | evt_path, st) { | 646 | continue; |
647 | evt_dir = fdopendir(dfd); | ||
648 | if (!evt_dir) { | ||
649 | close(dfd); | ||
650 | continue; | ||
651 | } | ||
652 | evt_dir_fd = dirfd(evt_dir); | ||
653 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | ||
617 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | 654 | snprintf(evt_path, MAXPATHLEN, "%s:%s", |
618 | sys_dirent.d_name, evt_dirent.d_name); | 655 | sys_dirent.d_name, evt_dirent.d_name); |
619 | fprintf(stderr, " %-40s [%s]\n", evt_path, | 656 | fprintf(stderr, " %-42s [%s]\n", evt_path, |
620 | event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); | 657 | event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); |
621 | } | 658 | } |
622 | closedir(evt_dir); | 659 | closedir(evt_dir); |
@@ -650,7 +687,7 @@ void print_events(void) | |||
650 | sprintf(name, "%s OR %s", syms->symbol, syms->alias); | 687 | sprintf(name, "%s OR %s", syms->symbol, syms->alias); |
651 | else | 688 | else |
652 | strcpy(name, syms->symbol); | 689 | strcpy(name, syms->symbol); |
653 | fprintf(stderr, " %-40s [%s]\n", name, | 690 | fprintf(stderr, " %-42s [%s]\n", name, |
654 | event_type_descriptors[type]); | 691 | event_type_descriptors[type]); |
655 | 692 | ||
656 | prev_type = type; | 693 | prev_type = type; |
@@ -664,7 +701,7 @@ void print_events(void) | |||
664 | continue; | 701 | continue; |
665 | 702 | ||
666 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { | 703 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { |
667 | fprintf(stderr, " %-40s [%s]\n", | 704 | fprintf(stderr, " %-42s [%s]\n", |
668 | event_cache_name(type, op, i), | 705 | event_cache_name(type, op, i), |
669 | event_type_descriptors[4]); | 706 | event_type_descriptors[4]); |
670 | } | 707 | } |
@@ -672,7 +709,7 @@ void print_events(void) | |||
672 | } | 709 | } |
673 | 710 | ||
674 | fprintf(stderr, "\n"); | 711 | fprintf(stderr, "\n"); |
675 | fprintf(stderr, " %-40s [raw hardware event descriptor]\n", | 712 | fprintf(stderr, " %-42s [raw hardware event descriptor]\n", |
676 | "rNNN"); | 713 | "rNNN"); |
677 | fprintf(stderr, "\n"); | 714 | fprintf(stderr, "\n"); |
678 | 715 | ||