diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
| -rw-r--r-- | tools/perf/util/parse-events.c | 139 |
1 files changed, 88 insertions, 51 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 044178408783..52219d5a507b 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,13 +637,20 @@ 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, " %-40s [%s]\n", evt_path, |
