diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-26 05:10:09 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-26 05:26:34 -0400 |
commit | 8ad8db3788fd9a449941fb2392ca85af4ee1cde1 (patch) | |
tree | 8c88edd7cdd4ecce57cda2c46b6dd544d00f97df /Documentation/perf_counter | |
parent | 0e9b20b8a1cab6c6ab4f98f917a2d98783103969 (diff) |
perf_counter tools: Librarize event string parsing
Extract the event string parser from builtin-record.c, and
librarize it - to be reused in other commands.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter')
-rw-r--r-- | Documentation/perf_counter/Makefile | 2 | ||||
-rw-r--r-- | Documentation/perf_counter/builtin-record.c | 154 | ||||
-rw-r--r-- | Documentation/perf_counter/util/parse-events.c | 127 | ||||
-rw-r--r-- | Documentation/perf_counter/util/parse-events.h | 10 |
4 files changed, 145 insertions, 148 deletions
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile index 481e4c26cd45..45daa72facdc 100644 --- a/Documentation/perf_counter/Makefile +++ b/Documentation/perf_counter/Makefile | |||
@@ -290,6 +290,7 @@ LIB_H += ../../include/linux/perf_counter.h | |||
290 | LIB_H += perf.h | 290 | LIB_H += perf.h |
291 | LIB_H += util/levenshtein.h | 291 | LIB_H += util/levenshtein.h |
292 | LIB_H += util/parse-options.h | 292 | LIB_H += util/parse-options.h |
293 | LIB_H += util/parse-events.h | ||
293 | LIB_H += util/quote.h | 294 | LIB_H += util/quote.h |
294 | LIB_H += util/util.h | 295 | LIB_H += util/util.h |
295 | LIB_H += util/help.h | 296 | LIB_H += util/help.h |
@@ -304,6 +305,7 @@ LIB_OBJS += util/exec_cmd.o | |||
304 | LIB_OBJS += util/help.o | 305 | LIB_OBJS += util/help.o |
305 | LIB_OBJS += util/levenshtein.o | 306 | LIB_OBJS += util/levenshtein.o |
306 | LIB_OBJS += util/parse-options.o | 307 | LIB_OBJS += util/parse-options.o |
308 | LIB_OBJS += util/parse-events.o | ||
307 | LIB_OBJS += util/path.o | 309 | LIB_OBJS += util/path.o |
308 | LIB_OBJS += util/run-command.o | 310 | LIB_OBJS += util/run-command.o |
309 | LIB_OBJS += util/quote.o | 311 | LIB_OBJS += util/quote.o |
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c index f12a7822fcf1..6fa6ed664950 100644 --- a/Documentation/perf_counter/builtin-record.c +++ b/Documentation/perf_counter/builtin-record.c | |||
@@ -3,44 +3,17 @@ | |||
3 | #include "perf.h" | 3 | #include "perf.h" |
4 | #include "util/util.h" | 4 | #include "util/util.h" |
5 | #include "util/parse-options.h" | 5 | #include "util/parse-options.h" |
6 | #include "util/parse-events.h" | ||
6 | #include "util/exec_cmd.h" | 7 | #include "util/exec_cmd.h" |
7 | 8 | ||
8 | #include <sys/types.h> | ||
9 | #include <sys/stat.h> | ||
10 | #include <sys/time.h> | ||
11 | #include <unistd.h> | ||
12 | #include <stdint.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <limits.h> | ||
16 | #include <assert.h> | ||
17 | #include <fcntl.h> | ||
18 | #include <stdio.h> | ||
19 | #include <errno.h> | ||
20 | #include <time.h> | ||
21 | #include <sched.h> | 9 | #include <sched.h> |
22 | #include <pthread.h> | ||
23 | |||
24 | #include <sys/syscall.h> | ||
25 | #include <sys/ioctl.h> | ||
26 | #include <sys/poll.h> | ||
27 | #include <sys/prctl.h> | ||
28 | #include <sys/wait.h> | ||
29 | #include <sys/uio.h> | ||
30 | #include <sys/mman.h> | ||
31 | |||
32 | #include <linux/unistd.h> | ||
33 | #include <linux/types.h> | ||
34 | |||
35 | |||
36 | 10 | ||
37 | #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) | 11 | #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) |
38 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) | 12 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) |
39 | 13 | ||
40 | static int nr_counters = 0; | ||
41 | static __u64 event_id[MAX_COUNTERS] = { }; | ||
42 | static int default_interval = 100000; | 14 | static int default_interval = 100000; |
43 | static int event_count[MAX_COUNTERS]; | 15 | static int event_count[MAX_COUNTERS]; |
16 | |||
44 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; | 17 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; |
45 | static int nr_cpus = 0; | 18 | static int nr_cpus = 0; |
46 | static unsigned int page_size; | 19 | static unsigned int page_size; |
@@ -420,131 +393,16 @@ static int __cmd_record(int argc, const char **argv) | |||
420 | return 0; | 393 | return 0; |
421 | } | 394 | } |
422 | 395 | ||
423 | struct event_symbol { | ||
424 | __u64 event; | ||
425 | char *symbol; | ||
426 | }; | ||
427 | |||
428 | static struct event_symbol event_symbols[] = { | ||
429 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cpu-cycles", }, | ||
430 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cycles", }, | ||
431 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), "instructions", }, | ||
432 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), "cache-references", }, | ||
433 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), "cache-misses", }, | ||
434 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branch-instructions", }, | ||
435 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branches", }, | ||
436 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES), "branch-misses", }, | ||
437 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES), "bus-cycles", }, | ||
438 | |||
439 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK), "cpu-clock", }, | ||
440 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), "task-clock", }, | ||
441 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "page-faults", }, | ||
442 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "faults", }, | ||
443 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN), "minor-faults", }, | ||
444 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ), "major-faults", }, | ||
445 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "context-switches", }, | ||
446 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "cs", }, | ||
447 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "cpu-migrations", }, | ||
448 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", }, | ||
449 | }; | ||
450 | |||
451 | /* | ||
452 | * Each event can have multiple symbolic names. | ||
453 | * Symbolic names are (almost) exactly matched. | ||
454 | */ | ||
455 | static __u64 match_event_symbols(const char *str) | ||
456 | { | ||
457 | __u64 config, id; | ||
458 | int type; | ||
459 | unsigned int i; | ||
460 | |||
461 | if (sscanf(str, "r%llx", &config) == 1) | ||
462 | return config | PERF_COUNTER_RAW_MASK; | ||
463 | |||
464 | if (sscanf(str, "%d:%llu", &type, &id) == 2) | ||
465 | return EID(type, id); | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | ||
468 | if (!strncmp(str, event_symbols[i].symbol, | ||
469 | strlen(event_symbols[i].symbol))) | ||
470 | return event_symbols[i].event; | ||
471 | } | ||
472 | |||
473 | return ~0ULL; | ||
474 | } | ||
475 | |||
476 | static int parse_events(const struct option *opt, const char *str, int unset) | ||
477 | { | ||
478 | __u64 config; | ||
479 | |||
480 | again: | ||
481 | if (nr_counters == MAX_COUNTERS) | ||
482 | return -1; | ||
483 | |||
484 | config = match_event_symbols(str); | ||
485 | if (config == ~0ULL) | ||
486 | return -1; | ||
487 | |||
488 | event_id[nr_counters] = config; | ||
489 | nr_counters++; | ||
490 | |||
491 | str = strstr(str, ","); | ||
492 | if (str) { | ||
493 | str++; | ||
494 | goto again; | ||
495 | } | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static char events_help[100000]; | ||
501 | |||
502 | #define __PERF_COUNTER_FIELD(config, name) \ | ||
503 | ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) | ||
504 | |||
505 | #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) | ||
506 | #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) | ||
507 | #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) | ||
508 | #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) | ||
509 | |||
510 | |||
511 | |||
512 | static void create_events_help(void) | ||
513 | { | ||
514 | unsigned int i; | ||
515 | char *str; | ||
516 | __u64 e; | ||
517 | |||
518 | str = events_help; | ||
519 | |||
520 | str += sprintf(str, | ||
521 | "event name: ["); | ||
522 | |||
523 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | ||
524 | int type, id; | ||
525 | |||
526 | e = event_symbols[i].event; | ||
527 | type = PERF_COUNTER_TYPE(e); | ||
528 | id = PERF_COUNTER_ID(e); | ||
529 | |||
530 | if (i) | ||
531 | str += sprintf(str, "|"); | ||
532 | |||
533 | str += sprintf(str, "%s", | ||
534 | event_symbols[i].symbol); | ||
535 | } | ||
536 | |||
537 | str += sprintf(str, "|rNNN]"); | ||
538 | } | ||
539 | |||
540 | static const char * const record_usage[] = { | 396 | static const char * const record_usage[] = { |
541 | "perf record [<options>] <command>", | 397 | "perf record [<options>] <command>", |
542 | NULL | 398 | NULL |
543 | }; | 399 | }; |
544 | 400 | ||
401 | static char events_help_msg[EVENTS_HELP_MAX]; | ||
402 | |||
545 | const struct option options[] = { | 403 | const struct option options[] = { |
546 | OPT_CALLBACK('e', "event", NULL, "event", | 404 | OPT_CALLBACK('e', "event", NULL, "event", |
547 | events_help, parse_events), | 405 | events_help_msg, parse_events), |
548 | OPT_INTEGER('c', "count", &default_interval, | 406 | OPT_INTEGER('c', "count", &default_interval, |
549 | "event period to sample"), | 407 | "event period to sample"), |
550 | OPT_INTEGER('m', "mmap-pages", &mmap_pages, | 408 | OPT_INTEGER('m', "mmap-pages", &mmap_pages, |
@@ -566,7 +424,7 @@ int cmd_record(int argc, const char **argv, const char *prefix) | |||
566 | { | 424 | { |
567 | int counter; | 425 | int counter; |
568 | 426 | ||
569 | create_events_help(); | 427 | create_events_help(events_help_msg); |
570 | 428 | ||
571 | argc = parse_options(argc, argv, options, record_usage, 0); | 429 | argc = parse_options(argc, argv, options, record_usage, 0); |
572 | if (!argc) | 430 | if (!argc) |
diff --git a/Documentation/perf_counter/util/parse-events.c b/Documentation/perf_counter/util/parse-events.c new file mode 100644 index 000000000000..77d0917d55d3 --- /dev/null +++ b/Documentation/perf_counter/util/parse-events.c | |||
@@ -0,0 +1,127 @@ | |||
1 | |||
2 | #include "../perf.h" | ||
3 | #include "util.h" | ||
4 | #include "parse-options.h" | ||
5 | #include "parse-events.h" | ||
6 | #include "exec_cmd.h" | ||
7 | |||
8 | int nr_counters; | ||
9 | |||
10 | __u64 event_id[MAX_COUNTERS] = { }; | ||
11 | |||
12 | struct event_symbol { | ||
13 | __u64 event; | ||
14 | char *symbol; | ||
15 | }; | ||
16 | |||
17 | static struct event_symbol event_symbols[] = { | ||
18 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cpu-cycles", }, | ||
19 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cycles", }, | ||
20 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), "instructions", }, | ||
21 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), "cache-references", }, | ||
22 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), "cache-misses", }, | ||
23 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branch-instructions", }, | ||
24 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branches", }, | ||
25 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES), "branch-misses", }, | ||
26 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES), "bus-cycles", }, | ||
27 | |||
28 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK), "cpu-clock", }, | ||
29 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), "task-clock", }, | ||
30 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "page-faults", }, | ||
31 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "faults", }, | ||
32 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN), "minor-faults", }, | ||
33 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ), "major-faults", }, | ||
34 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "context-switches", }, | ||
35 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "cs", }, | ||
36 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "cpu-migrations", }, | ||
37 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", }, | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Each event can have multiple symbolic names. | ||
42 | * Symbolic names are (almost) exactly matched. | ||
43 | */ | ||
44 | static __u64 match_event_symbols(const char *str) | ||
45 | { | ||
46 | __u64 config, id; | ||
47 | int type; | ||
48 | unsigned int i; | ||
49 | |||
50 | if (sscanf(str, "r%llx", &config) == 1) | ||
51 | return config | PERF_COUNTER_RAW_MASK; | ||
52 | |||
53 | if (sscanf(str, "%d:%llu", &type, &id) == 2) | ||
54 | return EID(type, id); | ||
55 | |||
56 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | ||
57 | if (!strncmp(str, event_symbols[i].symbol, | ||
58 | strlen(event_symbols[i].symbol))) | ||
59 | return event_symbols[i].event; | ||
60 | } | ||
61 | |||
62 | return ~0ULL; | ||
63 | } | ||
64 | |||
65 | int parse_events(const struct option *opt, const char *str, int unset) | ||
66 | { | ||
67 | __u64 config; | ||
68 | |||
69 | again: | ||
70 | if (nr_counters == MAX_COUNTERS) | ||
71 | return -1; | ||
72 | |||
73 | config = match_event_symbols(str); | ||
74 | if (config == ~0ULL) | ||
75 | return -1; | ||
76 | |||
77 | event_id[nr_counters] = config; | ||
78 | nr_counters++; | ||
79 | |||
80 | str = strstr(str, ","); | ||
81 | if (str) { | ||
82 | str++; | ||
83 | goto again; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | #define __PERF_COUNTER_FIELD(config, name) \ | ||
90 | ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) | ||
91 | |||
92 | #define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) | ||
93 | #define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) | ||
94 | #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) | ||
95 | #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) | ||
96 | |||
97 | /* | ||
98 | * Create the help text for the event symbols: | ||
99 | */ | ||
100 | void create_events_help(char *events_help_msg) | ||
101 | { | ||
102 | unsigned int i; | ||
103 | char *str; | ||
104 | __u64 e; | ||
105 | |||
106 | str = events_help_msg; | ||
107 | |||
108 | str += sprintf(str, | ||
109 | "event name: ["); | ||
110 | |||
111 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | ||
112 | int type, id; | ||
113 | |||
114 | e = event_symbols[i].event; | ||
115 | type = PERF_COUNTER_TYPE(e); | ||
116 | id = PERF_COUNTER_ID(e); | ||
117 | |||
118 | if (i) | ||
119 | str += sprintf(str, "|"); | ||
120 | |||
121 | str += sprintf(str, "%s", | ||
122 | event_symbols[i].symbol); | ||
123 | } | ||
124 | |||
125 | str += sprintf(str, "|rNNN]"); | ||
126 | } | ||
127 | |||
diff --git a/Documentation/perf_counter/util/parse-events.h b/Documentation/perf_counter/util/parse-events.h new file mode 100644 index 000000000000..6e2ebe5ff7d7 --- /dev/null +++ b/Documentation/perf_counter/util/parse-events.h | |||
@@ -0,0 +1,10 @@ | |||
1 | |||
2 | extern int nr_counters; | ||
3 | extern __u64 event_id[MAX_COUNTERS]; | ||
4 | |||
5 | extern int parse_events(const struct option *opt, const char *str, int unset); | ||
6 | |||
7 | #define EVENTS_HELP_MAX (128*1024) | ||
8 | |||
9 | extern void create_events_help(char *help_msg); | ||
10 | |||