diff options
author | Jiri Olsa <jolsa@kernel.org> | 2015-07-21 08:31:27 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-06 15:08:16 -0400 |
commit | f80010eb230b94e8d9cf5bf83373a097fb5b2dcc (patch) | |
tree | a122a4edc3bd68d173c274ad168651b8fa2856e8 /tools | |
parent | 5e5fe748bec771a810b1f44ec9c19e4b92685246 (diff) |
perf stat: Move counter processing code into stat object
Moving counter processing code into stat object as
perf_stat__process_counter.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-8-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-stat.c | 141 | ||||
-rw-r--r-- | tools/perf/util/stat.c | 139 | ||||
-rw-r--r-- | tools/perf/util/stat.h | 3 |
3 files changed, 143 insertions, 140 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 5a781718c09f..a054ddc0b2a0 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -179,145 +179,6 @@ static inline int nsec_counter(struct perf_evsel *evsel) | |||
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | static void zero_per_pkg(struct perf_evsel *counter) | ||
183 | { | ||
184 | if (counter->per_pkg_mask) | ||
185 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); | ||
186 | } | ||
187 | |||
188 | static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | ||
189 | { | ||
190 | unsigned long *mask = counter->per_pkg_mask; | ||
191 | struct cpu_map *cpus = perf_evsel__cpus(counter); | ||
192 | int s; | ||
193 | |||
194 | *skip = false; | ||
195 | |||
196 | if (!counter->per_pkg) | ||
197 | return 0; | ||
198 | |||
199 | if (cpu_map__empty(cpus)) | ||
200 | return 0; | ||
201 | |||
202 | if (!mask) { | ||
203 | mask = zalloc(MAX_NR_CPUS); | ||
204 | if (!mask) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | counter->per_pkg_mask = mask; | ||
208 | } | ||
209 | |||
210 | s = cpu_map__get_socket(cpus, cpu); | ||
211 | if (s < 0) | ||
212 | return -1; | ||
213 | |||
214 | *skip = test_and_set_bit(s, mask) == 1; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int | ||
219 | process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel, | ||
220 | int cpu, int thread, | ||
221 | struct perf_counts_values *count) | ||
222 | { | ||
223 | struct perf_counts_values *aggr = &evsel->counts->aggr; | ||
224 | static struct perf_counts_values zero; | ||
225 | bool skip = false; | ||
226 | |||
227 | if (check_per_pkg(evsel, cpu, &skip)) { | ||
228 | pr_err("failed to read per-pkg counter\n"); | ||
229 | return -1; | ||
230 | } | ||
231 | |||
232 | if (skip) | ||
233 | count = &zero; | ||
234 | |||
235 | switch (config->aggr_mode) { | ||
236 | case AGGR_THREAD: | ||
237 | case AGGR_CORE: | ||
238 | case AGGR_SOCKET: | ||
239 | case AGGR_NONE: | ||
240 | if (!evsel->snapshot) | ||
241 | perf_evsel__compute_deltas(evsel, cpu, thread, count); | ||
242 | perf_counts_values__scale(count, config->scale, NULL); | ||
243 | if (config->aggr_mode == AGGR_NONE) | ||
244 | perf_stat__update_shadow_stats(evsel, count->values, cpu); | ||
245 | break; | ||
246 | case AGGR_GLOBAL: | ||
247 | aggr->val += count->val; | ||
248 | if (config->scale) { | ||
249 | aggr->ena += count->ena; | ||
250 | aggr->run += count->run; | ||
251 | } | ||
252 | default: | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int process_counter_maps(struct perf_stat_config *config, | ||
260 | struct perf_evsel *counter) | ||
261 | { | ||
262 | int nthreads = thread_map__nr(counter->threads); | ||
263 | int ncpus = perf_evsel__nr_cpus(counter); | ||
264 | int cpu, thread; | ||
265 | |||
266 | if (counter->system_wide) | ||
267 | nthreads = 1; | ||
268 | |||
269 | for (thread = 0; thread < nthreads; thread++) { | ||
270 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
271 | if (process_counter_values(config, counter, cpu, thread, | ||
272 | perf_counts(counter->counts, cpu, thread))) | ||
273 | return -1; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int process_counter(struct perf_stat_config *config, | ||
281 | struct perf_evsel *counter) | ||
282 | { | ||
283 | struct perf_counts_values *aggr = &counter->counts->aggr; | ||
284 | struct perf_stat *ps = counter->priv; | ||
285 | u64 *count = counter->counts->aggr.values; | ||
286 | int i, ret; | ||
287 | |||
288 | aggr->val = aggr->ena = aggr->run = 0; | ||
289 | init_stats(ps->res_stats); | ||
290 | |||
291 | if (counter->per_pkg) | ||
292 | zero_per_pkg(counter); | ||
293 | |||
294 | ret = process_counter_maps(&stat_config, counter); | ||
295 | if (ret) | ||
296 | return ret; | ||
297 | |||
298 | if (config->aggr_mode != AGGR_GLOBAL) | ||
299 | return 0; | ||
300 | |||
301 | if (!counter->snapshot) | ||
302 | perf_evsel__compute_deltas(counter, -1, -1, aggr); | ||
303 | perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled); | ||
304 | |||
305 | for (i = 0; i < 3; i++) | ||
306 | update_stats(&ps->res_stats[i], count[i]); | ||
307 | |||
308 | if (verbose) { | ||
309 | fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", | ||
310 | perf_evsel__name(counter), count[0], count[1], count[2]); | ||
311 | } | ||
312 | |||
313 | /* | ||
314 | * Save the full runtime - to allow normalization during printout: | ||
315 | */ | ||
316 | perf_stat__update_shadow_stats(counter, count, 0); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | /* | 182 | /* |
322 | * Read out the results of a single counter: | 183 | * Read out the results of a single counter: |
323 | * do not aggregate counts across CPUs in system-wide mode | 184 | * do not aggregate counts across CPUs in system-wide mode |
@@ -355,7 +216,7 @@ static void read_counters(bool close_counters) | |||
355 | if (read_counter(counter)) | 216 | if (read_counter(counter)) |
356 | pr_warning("failed to read counter %s\n", counter->name); | 217 | pr_warning("failed to read counter %s\n", counter->name); |
357 | 218 | ||
358 | if (process_counter(&stat_config, counter)) | 219 | if (perf_stat_process_counter(&stat_config, counter)) |
359 | pr_warning("failed to process counter %s\n", counter->name); | 220 | pr_warning("failed to process counter %s\n", counter->name); |
360 | 221 | ||
361 | if (close_counters) { | 222 | if (close_counters) { |
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index f2a0d1521e26..c5c709cdc3ce 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
@@ -238,3 +238,142 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist) | |||
238 | perf_evsel__reset_counts(evsel); | 238 | perf_evsel__reset_counts(evsel); |
239 | } | 239 | } |
240 | } | 240 | } |
241 | |||
242 | static void zero_per_pkg(struct perf_evsel *counter) | ||
243 | { | ||
244 | if (counter->per_pkg_mask) | ||
245 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); | ||
246 | } | ||
247 | |||
248 | static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | ||
249 | { | ||
250 | unsigned long *mask = counter->per_pkg_mask; | ||
251 | struct cpu_map *cpus = perf_evsel__cpus(counter); | ||
252 | int s; | ||
253 | |||
254 | *skip = false; | ||
255 | |||
256 | if (!counter->per_pkg) | ||
257 | return 0; | ||
258 | |||
259 | if (cpu_map__empty(cpus)) | ||
260 | return 0; | ||
261 | |||
262 | if (!mask) { | ||
263 | mask = zalloc(MAX_NR_CPUS); | ||
264 | if (!mask) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | counter->per_pkg_mask = mask; | ||
268 | } | ||
269 | |||
270 | s = cpu_map__get_socket(cpus, cpu); | ||
271 | if (s < 0) | ||
272 | return -1; | ||
273 | |||
274 | *skip = test_and_set_bit(s, mask) == 1; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int | ||
279 | process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel, | ||
280 | int cpu, int thread, | ||
281 | struct perf_counts_values *count) | ||
282 | { | ||
283 | struct perf_counts_values *aggr = &evsel->counts->aggr; | ||
284 | static struct perf_counts_values zero; | ||
285 | bool skip = false; | ||
286 | |||
287 | if (check_per_pkg(evsel, cpu, &skip)) { | ||
288 | pr_err("failed to read per-pkg counter\n"); | ||
289 | return -1; | ||
290 | } | ||
291 | |||
292 | if (skip) | ||
293 | count = &zero; | ||
294 | |||
295 | switch (config->aggr_mode) { | ||
296 | case AGGR_THREAD: | ||
297 | case AGGR_CORE: | ||
298 | case AGGR_SOCKET: | ||
299 | case AGGR_NONE: | ||
300 | if (!evsel->snapshot) | ||
301 | perf_evsel__compute_deltas(evsel, cpu, thread, count); | ||
302 | perf_counts_values__scale(count, config->scale, NULL); | ||
303 | if (config->aggr_mode == AGGR_NONE) | ||
304 | perf_stat__update_shadow_stats(evsel, count->values, cpu); | ||
305 | break; | ||
306 | case AGGR_GLOBAL: | ||
307 | aggr->val += count->val; | ||
308 | if (config->scale) { | ||
309 | aggr->ena += count->ena; | ||
310 | aggr->run += count->run; | ||
311 | } | ||
312 | default: | ||
313 | break; | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int process_counter_maps(struct perf_stat_config *config, | ||
320 | struct perf_evsel *counter) | ||
321 | { | ||
322 | int nthreads = thread_map__nr(counter->threads); | ||
323 | int ncpus = perf_evsel__nr_cpus(counter); | ||
324 | int cpu, thread; | ||
325 | |||
326 | if (counter->system_wide) | ||
327 | nthreads = 1; | ||
328 | |||
329 | for (thread = 0; thread < nthreads; thread++) { | ||
330 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
331 | if (process_counter_values(config, counter, cpu, thread, | ||
332 | perf_counts(counter->counts, cpu, thread))) | ||
333 | return -1; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | int perf_stat_process_counter(struct perf_stat_config *config, | ||
341 | struct perf_evsel *counter) | ||
342 | { | ||
343 | struct perf_counts_values *aggr = &counter->counts->aggr; | ||
344 | struct perf_stat *ps = counter->priv; | ||
345 | u64 *count = counter->counts->aggr.values; | ||
346 | int i, ret; | ||
347 | |||
348 | aggr->val = aggr->ena = aggr->run = 0; | ||
349 | init_stats(ps->res_stats); | ||
350 | |||
351 | if (counter->per_pkg) | ||
352 | zero_per_pkg(counter); | ||
353 | |||
354 | ret = process_counter_maps(config, counter); | ||
355 | if (ret) | ||
356 | return ret; | ||
357 | |||
358 | if (config->aggr_mode != AGGR_GLOBAL) | ||
359 | return 0; | ||
360 | |||
361 | if (!counter->snapshot) | ||
362 | perf_evsel__compute_deltas(counter, -1, -1, aggr); | ||
363 | perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled); | ||
364 | |||
365 | for (i = 0; i < 3; i++) | ||
366 | update_stats(&ps->res_stats[i], count[i]); | ||
367 | |||
368 | if (verbose) { | ||
369 | fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", | ||
370 | perf_evsel__name(counter), count[0], count[1], count[2]); | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * Save the full runtime - to allow normalization during printout: | ||
375 | */ | ||
376 | perf_stat__update_shadow_stats(counter, count, 0); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 1da706d848fb..0b897b083682 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h | |||
@@ -116,4 +116,7 @@ int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw); | |||
116 | int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); | 116 | int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); |
117 | void perf_evlist__free_stats(struct perf_evlist *evlist); | 117 | void perf_evlist__free_stats(struct perf_evlist *evlist); |
118 | void perf_evlist__reset_stats(struct perf_evlist *evlist); | 118 | void perf_evlist__reset_stats(struct perf_evlist *evlist); |
119 | |||
120 | int perf_stat_process_counter(struct perf_stat_config *config, | ||
121 | struct perf_evsel *counter); | ||
119 | #endif | 122 | #endif |