Skip to content

Commit

Permalink
perf stat: Fix per-pkg event reporting bug
Browse files Browse the repository at this point in the history
Per-pkg events need to be captured once per processor socket. The code
in check_per_pkg() ensures only one value per processor package is used.
However there is a problem with this function in case the first CPU of
the package does not measure anything for the per-pkg event, but other
CPUs do.

Consider the following:

  $ create cgroup FOO; echo $$ >FOO/tasks; taskset -c 1 noploop &
  $ perf stat -a -I 1000 -e intel_cqm/llc_occupancy/ -G FOO sleep 100
    1.00000 <not counted> Bytes intel_cqm/llc_occupancy/  FOO

The reason for this is that CPU0 in the cgroup has nothing running on it.
Yet check_per_plg() will mark socket0 as processed and no other event
value will be considered for the socket.

This patch fixes the problem by having check_per_pkg() only consider
events which actually ran.

Signed-off-by: Stephane Eranian <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
Stephane Eranian authored and acmel committed Sep 16, 2015
1 parent f6cf87f commit 02d8dab
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions tools/perf/util/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ static void zero_per_pkg(struct perf_evsel *counter)
memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
}

static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
static int check_per_pkg(struct perf_evsel *counter,
struct perf_counts_values *vals, int cpu, bool *skip)
{
unsigned long *mask = counter->per_pkg_mask;
struct cpu_map *cpus = perf_evsel__cpus(counter);
Expand All @@ -218,6 +219,17 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
counter->per_pkg_mask = mask;
}

/*
* we do not consider an event that has not run as a good
* instance to mark a package as used (skip=1). Otherwise
* we may run into a situation where the first CPU in a package
* is not running anything, yet the second is, and this function
* would mark the package as used after the first CPU and would
* not read the values from the second CPU.
*/
if (!(vals->run && vals->ena))
return 0;

s = cpu_map__get_socket(cpus, cpu);
if (s < 0)
return -1;
Expand All @@ -235,7 +247,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
static struct perf_counts_values zero;
bool skip = false;

if (check_per_pkg(evsel, cpu, &skip)) {
if (check_per_pkg(evsel, count, cpu, &skip)) {
pr_err("failed to read per-pkg counter\n");
return -1;
}
Expand Down

0 comments on commit 02d8dab

Please sign in to comment.