aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/perf_counter/Makefile2
-rw-r--r--Documentation/perf_counter/builtin-record.c154
-rw-r--r--Documentation/perf_counter/util/parse-events.c127
-rw-r--r--Documentation/perf_counter/util/parse-events.h10
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
290LIB_H += perf.h 290LIB_H += perf.h
291LIB_H += util/levenshtein.h 291LIB_H += util/levenshtein.h
292LIB_H += util/parse-options.h 292LIB_H += util/parse-options.h
293LIB_H += util/parse-events.h
293LIB_H += util/quote.h 294LIB_H += util/quote.h
294LIB_H += util/util.h 295LIB_H += util/util.h
295LIB_H += util/help.h 296LIB_H += util/help.h
@@ -304,6 +305,7 @@ LIB_OBJS += util/exec_cmd.o
304LIB_OBJS += util/help.o 305LIB_OBJS += util/help.o
305LIB_OBJS += util/levenshtein.o 306LIB_OBJS += util/levenshtein.o
306LIB_OBJS += util/parse-options.o 307LIB_OBJS += util/parse-options.o
308LIB_OBJS += util/parse-events.o
307LIB_OBJS += util/path.o 309LIB_OBJS += util/path.o
308LIB_OBJS += util/run-command.o 310LIB_OBJS += util/run-command.o
309LIB_OBJS += util/quote.o 311LIB_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
40static int nr_counters = 0;
41static __u64 event_id[MAX_COUNTERS] = { };
42static int default_interval = 100000; 14static int default_interval = 100000;
43static int event_count[MAX_COUNTERS]; 15static int event_count[MAX_COUNTERS];
16
44static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 17static int fd[MAX_NR_CPUS][MAX_COUNTERS];
45static int nr_cpus = 0; 18static int nr_cpus = 0;
46static unsigned int page_size; 19static 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
423struct event_symbol {
424 __u64 event;
425 char *symbol;
426};
427
428static 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 */
455static __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
476static int parse_events(const struct option *opt, const char *str, int unset)
477{
478 __u64 config;
479
480again:
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
500static 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
512static 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
540static const char * const record_usage[] = { 396static const char * const record_usage[] = {
541 "perf record [<options>] <command>", 397 "perf record [<options>] <command>",
542 NULL 398 NULL
543}; 399};
544 400
401static char events_help_msg[EVENTS_HELP_MAX];
402
545const struct option options[] = { 403const 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
8int nr_counters;
9
10__u64 event_id[MAX_COUNTERS] = { };
11
12struct event_symbol {
13 __u64 event;
14 char *symbol;
15};
16
17static 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 */
44static __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
65int parse_events(const struct option *opt, const char *str, int unset)
66{
67 __u64 config;
68
69again:
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 */
100void 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
2extern int nr_counters;
3extern __u64 event_id[MAX_COUNTERS];
4
5extern int parse_events(const struct option *opt, const char *str, int unset);
6
7#define EVENTS_HELP_MAX (128*1024)
8
9extern void create_events_help(char *help_msg);
10