diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index b24a7a08bd1d..860e8ad06616 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -388,10 +388,56 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count) | |||
388 | update_stats(&runtime_itlb_cache_stats[0], count[0]); | 388 | update_stats(&runtime_itlb_cache_stats[0], count[0]); |
389 | } | 389 | } |
390 | 390 | ||
391 | static void zero_per_pkg(struct perf_evsel *counter) | ||
392 | { | ||
393 | if (counter->per_pkg_mask) | ||
394 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); | ||
395 | } | ||
396 | |||
397 | static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | ||
398 | { | ||
399 | unsigned long *mask = counter->per_pkg_mask; | ||
400 | struct cpu_map *cpus = perf_evsel__cpus(counter); | ||
401 | int s; | ||
402 | |||
403 | *skip = false; | ||
404 | |||
405 | if (!counter->per_pkg) | ||
406 | return 0; | ||
407 | |||
408 | if (cpu_map__empty(cpus)) | ||
409 | return 0; | ||
410 | |||
411 | if (!mask) { | ||
412 | mask = zalloc(MAX_NR_CPUS); | ||
413 | if (!mask) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | counter->per_pkg_mask = mask; | ||
417 | } | ||
418 | |||
419 | s = cpu_map__get_socket(cpus, cpu); | ||
420 | if (s < 0) | ||
421 | return -1; | ||
422 | |||
423 | *skip = test_and_set_bit(s, mask) == 1; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
391 | static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, | 427 | static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, |
392 | struct perf_counts_values *count) | 428 | struct perf_counts_values *count) |
393 | { | 429 | { |
394 | struct perf_counts_values *aggr = &evsel->counts->aggr; | 430 | struct perf_counts_values *aggr = &evsel->counts->aggr; |
431 | static struct perf_counts_values zero; | ||
432 | bool skip = false; | ||
433 | |||
434 | if (check_per_pkg(evsel, cpu, &skip)) { | ||
435 | pr_err("failed to read per-pkg counter\n"); | ||
436 | return -1; | ||
437 | } | ||
438 | |||
439 | if (skip) | ||
440 | count = &zero; | ||
395 | 441 | ||
396 | switch (aggr_mode) { | 442 | switch (aggr_mode) { |
397 | case AGGR_CORE: | 443 | case AGGR_CORE: |
@@ -465,6 +511,9 @@ static int read_counter(struct perf_evsel *counter) | |||
465 | if (counter->system_wide) | 511 | if (counter->system_wide) |
466 | nthreads = 1; | 512 | nthreads = 1; |
467 | 513 | ||
514 | if (counter->per_pkg) | ||
515 | zero_per_pkg(counter); | ||
516 | |||
468 | for (thread = 0; thread < nthreads; thread++) { | 517 | for (thread = 0; thread < nthreads; thread++) { |
469 | for (cpu = 0; cpu < ncpus; cpu++) { | 518 | for (cpu = 0; cpu < ncpus; cpu++) { |
470 | if (perf_evsel__read_cb(counter, cpu, thread, read_cb)) | 519 | if (perf_evsel__read_cb(counter, cpu, thread, read_cb)) |