aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/evsel.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-06-20 07:41:42 -0400
committerIngo Molnar <mingo@kernel.org>2012-06-20 07:41:53 -0400
commit32c46e579b68c7ac0cd19d0803898a841d99833d (patch)
tree64a15c3b6eca5b302ef5aff0e045f52035c33eb7 /tools/perf/util/evsel.c
parent2992c542fcd40777ed253f57362c65711fb8acaf (diff)
parentc0a58fb2bdf033df433cad9009c7dac4c6b872b0 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf improvements from Arnaldo Carvalho de Melo: * Replace event_name with perf_evsel__name, that handles the event modifiers and doesn't use static variables. * GTK browser improvements, from Namhyung Kim * Fix possible NULL pointer deref in the TUI annotate browser, from Samuel Liao * Add sort by source file:line number, using addr2line. * Allow printing histogram text snapshots at any point in top/report. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/evsel.c')
-rw-r--r--tools/perf/util/evsel.c196
1 files changed, 169 insertions, 27 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f6cebd798ee..876f639d69ed 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
78 "ref-cycles", 78 "ref-cycles",
79}; 79};
80 80
81const char *__perf_evsel__hw_name(u64 config) 81static const char *__perf_evsel__hw_name(u64 config)
82{ 82{
83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
84 return perf_evsel__hw_names[config]; 84 return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
86 return "unknown-hardware"; 86 return "unknown-hardware";
87} 87}
88 88
89static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 89static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
90{ 90{
91 int colon = 0; 91 int colon = 0, r = 0;
92 struct perf_event_attr *attr = &evsel->attr; 92 struct perf_event_attr *attr = &evsel->attr;
93 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
94 bool exclude_guest_default = false; 93 bool exclude_guest_default = false;
95 94
96#define MOD_PRINT(context, mod) do { \ 95#define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 96 if (!attr->exclude_##context) { \
98 if (!colon) colon = r++; \ 97 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 98 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 99 } } while(0)
101 100
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
108 107
109 if (attr->precise_ip) { 108 if (attr->precise_ip) {
110 if (!colon) 109 if (!colon)
111 colon = r++; 110 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 111 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 112 exclude_guest_default = true;
114 } 113 }
@@ -119,39 +118,182 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
119 } 118 }
120#undef MOD_PRINT 119#undef MOD_PRINT
121 if (colon) 120 if (colon)
122 bf[colon] = ':'; 121 bf[colon - 1] = ':';
123 return r; 122 return r;
124} 123}
125 124
126int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 125static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
126{
127 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
129}
130
131static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
132 "cpu-clock",
133 "task-clock",
134 "page-faults",
135 "context-switches",
136 "CPU-migrations",
137 "minor-faults",
138 "major-faults",
139 "alignment-faults",
140 "emulation-faults",
141};
142
143static const char *__perf_evsel__sw_name(u64 config)
144{
145 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
146 return perf_evsel__sw_names[config];
147 return "unknown-software";
148}
149
150static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
151{
152 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
153 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
154}
155
156const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
157 [PERF_EVSEL__MAX_ALIASES] = {
158 { "L1-dcache", "l1-d", "l1d", "L1-data", },
159 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
160 { "LLC", "L2", },
161 { "dTLB", "d-tlb", "Data-TLB", },
162 { "iTLB", "i-tlb", "Instruction-TLB", },
163 { "branch", "branches", "bpu", "btb", "bpc", },
164 { "node", },
165};
166
167const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
168 [PERF_EVSEL__MAX_ALIASES] = {
169 { "load", "loads", "read", },
170 { "store", "stores", "write", },
171 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
172};
173
174const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
175 [PERF_EVSEL__MAX_ALIASES] = {
176 { "refs", "Reference", "ops", "access", },
177 { "misses", "miss", },
178};
179
180#define C(x) PERF_COUNT_HW_CACHE_##x
181#define CACHE_READ (1 << C(OP_READ))
182#define CACHE_WRITE (1 << C(OP_WRITE))
183#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
184#define COP(x) (1 << x)
185
186/*
187 * cache operartion stat
188 * L1I : Read and prefetch only
189 * ITLB and BPU : Read-only
190 */
191static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
192 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
193 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
194 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
195 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
196 [C(ITLB)] = (CACHE_READ),
197 [C(BPU)] = (CACHE_READ),
198 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
199};
200
201bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
202{
203 if (perf_evsel__hw_cache_stat[type] & COP(op))
204 return true; /* valid */
205 else
206 return false; /* invalid */
207}
208
209int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
210 char *bf, size_t size)
211{
212 if (result) {
213 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
214 perf_evsel__hw_cache_op[op][0],
215 perf_evsel__hw_cache_result[result][0]);
216 }
217
218 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
219 perf_evsel__hw_cache_op[op][1]);
220}
221
222static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
127{ 223{
128 int ret; 224 u8 op, result, type = (config >> 0) & 0xff;
225 const char *err = "unknown-ext-hardware-cache-type";
226
227 if (type > PERF_COUNT_HW_CACHE_MAX)
228 goto out_err;
229
230 op = (config >> 8) & 0xff;
231 err = "unknown-ext-hardware-cache-op";
232 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
233 goto out_err;
234
235 result = (config >> 16) & 0xff;
236 err = "unknown-ext-hardware-cache-result";
237 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
238 goto out_err;
239
240 err = "invalid-cache";
241 if (!perf_evsel__is_cache_op_valid(type, op))
242 goto out_err;
243
244 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
245out_err:
246 return scnprintf(bf, size, "%s", err);
247}
248
249static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
250{
251 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
252 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
253}
254
255static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
256{
257 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
258 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
259}
260
261const char *perf_evsel__name(struct perf_evsel *evsel)
262{
263 char bf[128];
264
265 if (evsel->name)
266 return evsel->name;
129 267
130 switch (evsel->attr.type) { 268 switch (evsel->attr.type) {
131 case PERF_TYPE_RAW: 269 case PERF_TYPE_RAW:
132 ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 270 perf_evsel__raw_name(evsel, bf, sizeof(bf));
133 break; 271 break;
134 272
135 case PERF_TYPE_HARDWARE: 273 case PERF_TYPE_HARDWARE:
136 ret = perf_evsel__hw_name(evsel, bf, size); 274 perf_evsel__hw_name(evsel, bf, sizeof(bf));
275 break;
276
277 case PERF_TYPE_HW_CACHE:
278 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
279 break;
280
281 case PERF_TYPE_SOFTWARE:
282 perf_evsel__sw_name(evsel, bf, sizeof(bf));
137 break; 283 break;
284
285 case PERF_TYPE_TRACEPOINT:
286 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
287 break;
288
138 default: 289 default:
139 /* 290 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
140 * FIXME 291 break;
141 * 292 }
142 * This is the minimal perf_evsel__name so that we can 293
143 * reconstruct event names taking into account event modifiers. 294 evsel->name = strdup(bf);
144 * 295
145 * The old event_name uses it now for raw anr hw events, so that 296 return evsel->name ?: "unknown";
146 * we don't drag all the parsing stuff into the python binding.
147 *
148 * On the next devel cycle the rest of the event naming will be
149 * brought here.
150 */
151 return 0;
152 }
153
154 return ret;
155} 297}
156 298
157void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 299void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,