diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-06-06 03:58:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-06 05:37:22 -0400 |
commit | a21ca2cac582886a3e95c8bb84ff7c52d4d15e54 (patch) | |
tree | d110005d81e46b1afb3204fbaacc132d0ec946ee /Documentation/perf_counter/util/parse-events.c | |
parent | 2f335a02b3c816e77e7df1d15b12e3bbb8f4c8f0 (diff) |
perf_counter: Separate out attr->type from attr->config
Counter type is a frequently used value and we do a lot of
bit juggling by encoding and decoding it from attr->config.
Clean this up by creating a separate attr->type field.
Also clean up the various similarly complex user-space bits
all around counter attribute management.
The net improvement is significant, and it will be easier
to add a new major type (which is what triggered this cleanup).
(This changes the ABI, all tools are adapted.)
(PowerPC build-tested.)
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/util/parse-events.c')
-rw-r--r-- | Documentation/perf_counter/util/parse-events.c | 120 |
1 files changed, 66 insertions, 54 deletions
diff --git a/Documentation/perf_counter/util/parse-events.c b/Documentation/perf_counter/util/parse-events.c index 2fdfd1d923f2..eb56bd996573 100644 --- a/Documentation/perf_counter/util/parse-events.c +++ b/Documentation/perf_counter/util/parse-events.c | |||
@@ -6,37 +6,39 @@ | |||
6 | #include "exec_cmd.h" | 6 | #include "exec_cmd.h" |
7 | #include "string.h" | 7 | #include "string.h" |
8 | 8 | ||
9 | int nr_counters; | 9 | int nr_counters; |
10 | 10 | ||
11 | __u64 event_id[MAX_COUNTERS] = { }; | 11 | struct perf_counter_attr attrs[MAX_COUNTERS]; |
12 | int event_mask[MAX_COUNTERS]; | ||
13 | 12 | ||
14 | struct event_symbol { | 13 | struct event_symbol { |
15 | __u64 event; | 14 | __u8 type; |
16 | char *symbol; | 15 | __u64 config; |
16 | char *symbol; | ||
17 | }; | 17 | }; |
18 | 18 | ||
19 | #define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y | ||
20 | |||
19 | static struct event_symbol event_symbols[] = { | 21 | static struct event_symbol event_symbols[] = { |
20 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cpu-cycles", }, | 22 | { C(HARDWARE, CPU_CYCLES), "cpu-cycles", }, |
21 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cycles", }, | 23 | { C(HARDWARE, CPU_CYCLES), "cycles", }, |
22 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), "instructions", }, | 24 | { C(HARDWARE, INSTRUCTIONS), "instructions", }, |
23 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), "cache-references", }, | 25 | { C(HARDWARE, CACHE_REFERENCES), "cache-references", }, |
24 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), "cache-misses", }, | 26 | { C(HARDWARE, CACHE_MISSES), "cache-misses", }, |
25 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branch-instructions", }, | 27 | { C(HARDWARE, BRANCH_INSTRUCTIONS), "branch-instructions", }, |
26 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branches", }, | 28 | { C(HARDWARE, BRANCH_INSTRUCTIONS), "branches", }, |
27 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES), "branch-misses", }, | 29 | { C(HARDWARE, BRANCH_MISSES), "branch-misses", }, |
28 | {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES), "bus-cycles", }, | 30 | { C(HARDWARE, BUS_CYCLES), "bus-cycles", }, |
29 | 31 | ||
30 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK), "cpu-clock", }, | 32 | { C(SOFTWARE, CPU_CLOCK), "cpu-clock", }, |
31 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), "task-clock", }, | 33 | { C(SOFTWARE, TASK_CLOCK), "task-clock", }, |
32 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "page-faults", }, | 34 | { C(SOFTWARE, PAGE_FAULTS), "page-faults", }, |
33 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "faults", }, | 35 | { C(SOFTWARE, PAGE_FAULTS), "faults", }, |
34 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN), "minor-faults", }, | 36 | { C(SOFTWARE, PAGE_FAULTS_MIN), "minor-faults", }, |
35 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ), "major-faults", }, | 37 | { C(SOFTWARE, PAGE_FAULTS_MAJ), "major-faults", }, |
36 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "context-switches", }, | 38 | { C(SOFTWARE, CONTEXT_SWITCHES), "context-switches", }, |
37 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "cs", }, | 39 | { C(SOFTWARE, CONTEXT_SWITCHES), "cs", }, |
38 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "cpu-migrations", }, | 40 | { C(SOFTWARE, CPU_MIGRATIONS), "cpu-migrations", }, |
39 | {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", }, | 41 | { C(SOFTWARE, CPU_MIGRATIONS), "migrations", }, |
40 | }; | 42 | }; |
41 | 43 | ||
42 | #define __PERF_COUNTER_FIELD(config, name) \ | 44 | #define __PERF_COUNTER_FIELD(config, name) \ |
@@ -67,27 +69,26 @@ static char *sw_event_names[] = { | |||
67 | "major faults", | 69 | "major faults", |
68 | }; | 70 | }; |
69 | 71 | ||
70 | char *event_name(int ctr) | 72 | char *event_name(int counter) |
71 | { | 73 | { |
72 | __u64 config = event_id[ctr]; | 74 | __u64 config = attrs[counter].config; |
73 | int type = PERF_COUNTER_TYPE(config); | 75 | int type = attrs[counter].type; |
74 | int id = PERF_COUNTER_ID(config); | ||
75 | static char buf[32]; | 76 | static char buf[32]; |
76 | 77 | ||
77 | if (PERF_COUNTER_RAW(config)) { | 78 | if (attrs[counter].type == PERF_TYPE_RAW) { |
78 | sprintf(buf, "raw 0x%llx", PERF_COUNTER_CONFIG(config)); | 79 | sprintf(buf, "raw 0x%llx", config); |
79 | return buf; | 80 | return buf; |
80 | } | 81 | } |
81 | 82 | ||
82 | switch (type) { | 83 | switch (type) { |
83 | case PERF_TYPE_HARDWARE: | 84 | case PERF_TYPE_HARDWARE: |
84 | if (id < PERF_HW_EVENTS_MAX) | 85 | if (config < PERF_HW_EVENTS_MAX) |
85 | return hw_event_names[id]; | 86 | return hw_event_names[config]; |
86 | return "unknown-hardware"; | 87 | return "unknown-hardware"; |
87 | 88 | ||
88 | case PERF_TYPE_SOFTWARE: | 89 | case PERF_TYPE_SOFTWARE: |
89 | if (id < PERF_SW_EVENTS_MAX) | 90 | if (config < PERF_SW_EVENTS_MAX) |
90 | return sw_event_names[id]; | 91 | return sw_event_names[config]; |
91 | return "unknown-software"; | 92 | return "unknown-software"; |
92 | 93 | ||
93 | default: | 94 | default: |
@@ -101,15 +102,19 @@ char *event_name(int ctr) | |||
101 | * Each event can have multiple symbolic names. | 102 | * Each event can have multiple symbolic names. |
102 | * Symbolic names are (almost) exactly matched. | 103 | * Symbolic names are (almost) exactly matched. |
103 | */ | 104 | */ |
104 | static __u64 match_event_symbols(const char *str) | 105 | static int match_event_symbols(const char *str, struct perf_counter_attr *attr) |
105 | { | 106 | { |
106 | __u64 config, id; | 107 | __u64 config, id; |
107 | int type; | 108 | int type; |
108 | unsigned int i; | 109 | unsigned int i; |
109 | const char *sep, *pstr; | 110 | const char *sep, *pstr; |
110 | 111 | ||
111 | if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) | 112 | if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { |
112 | return config | PERF_COUNTER_RAW_MASK; | 113 | attr->type = PERF_TYPE_RAW; |
114 | attr->config = config; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
113 | 118 | ||
114 | pstr = str; | 119 | pstr = str; |
115 | sep = strchr(pstr, ':'); | 120 | sep = strchr(pstr, ':'); |
@@ -121,35 +126,45 @@ static __u64 match_event_symbols(const char *str) | |||
121 | if (sep) { | 126 | if (sep) { |
122 | pstr = sep + 1; | 127 | pstr = sep + 1; |
123 | if (strchr(pstr, 'k')) | 128 | if (strchr(pstr, 'k')) |
124 | event_mask[nr_counters] |= EVENT_MASK_USER; | 129 | attr->exclude_user = 1; |
125 | if (strchr(pstr, 'u')) | 130 | if (strchr(pstr, 'u')) |
126 | event_mask[nr_counters] |= EVENT_MASK_KERNEL; | 131 | attr->exclude_kernel = 1; |
127 | } | 132 | } |
128 | return EID(type, id); | 133 | attr->type = type; |
134 | attr->config = id; | ||
135 | |||
136 | return 0; | ||
129 | } | 137 | } |
130 | 138 | ||
131 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | 139 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { |
132 | if (!strncmp(str, event_symbols[i].symbol, | 140 | if (!strncmp(str, event_symbols[i].symbol, |
133 | strlen(event_symbols[i].symbol))) | 141 | strlen(event_symbols[i].symbol))) { |
134 | return event_symbols[i].event; | 142 | |
143 | attr->type = event_symbols[i].type; | ||
144 | attr->config = event_symbols[i].config; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
135 | } | 148 | } |
136 | 149 | ||
137 | return ~0ULL; | 150 | return -EINVAL; |
138 | } | 151 | } |
139 | 152 | ||
140 | int parse_events(const struct option *opt, const char *str, int unset) | 153 | int parse_events(const struct option *opt, const char *str, int unset) |
141 | { | 154 | { |
142 | __u64 config; | 155 | struct perf_counter_attr attr; |
156 | int ret; | ||
143 | 157 | ||
158 | memset(&attr, 0, sizeof(attr)); | ||
144 | again: | 159 | again: |
145 | if (nr_counters == MAX_COUNTERS) | 160 | if (nr_counters == MAX_COUNTERS) |
146 | return -1; | 161 | return -1; |
147 | 162 | ||
148 | config = match_event_symbols(str); | 163 | ret = match_event_symbols(str, &attr); |
149 | if (config == ~0ULL) | 164 | if (ret < 0) |
150 | return -1; | 165 | return ret; |
151 | 166 | ||
152 | event_id[nr_counters] = config; | 167 | attrs[nr_counters] = attr; |
153 | nr_counters++; | 168 | nr_counters++; |
154 | 169 | ||
155 | str = strstr(str, ","); | 170 | str = strstr(str, ","); |
@@ -168,7 +183,6 @@ void create_events_help(char *events_help_msg) | |||
168 | { | 183 | { |
169 | unsigned int i; | 184 | unsigned int i; |
170 | char *str; | 185 | char *str; |
171 | __u64 e; | ||
172 | 186 | ||
173 | str = events_help_msg; | 187 | str = events_help_msg; |
174 | 188 | ||
@@ -178,9 +192,8 @@ void create_events_help(char *events_help_msg) | |||
178 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { | 192 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { |
179 | int type, id; | 193 | int type, id; |
180 | 194 | ||
181 | e = event_symbols[i].event; | 195 | type = event_symbols[i].type; |
182 | type = PERF_COUNTER_TYPE(e); | 196 | id = event_symbols[i].config; |
183 | id = PERF_COUNTER_ID(e); | ||
184 | 197 | ||
185 | if (i) | 198 | if (i) |
186 | str += sprintf(str, "|"); | 199 | str += sprintf(str, "|"); |
@@ -191,4 +204,3 @@ void create_events_help(char *events_help_msg) | |||
191 | 204 | ||
192 | str += sprintf(str, "|rNNN]"); | 205 | str += sprintf(str, "|rNNN]"); |
193 | } | 206 | } |
194 | |||