perf evsel: Add read_counter()
authorJiri Olsa <jolsa@kernel.org>
Wed, 26 Jul 2017 12:02:05 +0000 (14:02 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 26 Jul 2017 17:21:59 +0000 (14:21 -0300)
Add perf_evsel__read_counter() to read single or group counter. After
calling this function the counter's evsel::counts struct is filled with
values for the counter and member of its group if there are any.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.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/20170726120206.9099-3-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/stat.c
tools/perf/util/stat.h

index 4dd0fcc06db96b41b52c4c84fad8c7a4c926fff6..89aecf3a35c7be720f6eb4f4d61bb4521600dc35 100644 (file)
@@ -1302,6 +1302,106 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
        return 0;
 }
 
+static int
+perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread)
+{
+       struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
+
+       return perf_evsel__read(evsel, cpu, thread, count);
+}
+
+static void
+perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
+                     u64 val, u64 ena, u64 run)
+{
+       struct perf_counts_values *count;
+
+       count = perf_counts(counter->counts, cpu, thread);
+
+       count->val    = val;
+       count->ena    = ena;
+       count->run    = run;
+}
+
+static int
+perf_evsel__process_group_data(struct perf_evsel *leader,
+                              int cpu, int thread, u64 *data)
+{
+       u64 read_format = leader->attr.read_format;
+       struct sample_read_value *v;
+       u64 nr, ena = 0, run = 0, i;
+
+       nr = *data++;
+
+       if (nr != (u64) leader->nr_members)
+               return -EINVAL;
+
+       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+               ena = *data++;
+
+       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+               run = *data++;
+
+       v = (struct sample_read_value *) data;
+
+       perf_evsel__set_count(leader, cpu, thread,
+                             v[0].value, ena, run);
+
+       for (i = 1; i < nr; i++) {
+               struct perf_evsel *counter;
+
+               counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
+               if (!counter)
+                       return -EINVAL;
+
+               perf_evsel__set_count(counter, cpu, thread,
+                                     v[i].value, ena, run);
+       }
+
+       return 0;
+}
+
+static int
+perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
+{
+       struct perf_stat_evsel *ps = leader->priv;
+       u64 read_format = leader->attr.read_format;
+       int size = perf_evsel__read_size(leader);
+       u64 *data = ps->group_data;
+
+       if (!(read_format & PERF_FORMAT_ID))
+               return -EINVAL;
+
+       if (!perf_evsel__is_group_leader(leader))
+               return -EINVAL;
+
+       if (!data) {
+               data = zalloc(size);
+               if (!data)
+                       return -ENOMEM;
+
+               ps->group_data = data;
+       }
+
+       if (FD(leader, cpu, thread) < 0)
+               return -EINVAL;
+
+       if (readn(FD(leader, cpu, thread), data, size) <= 0)
+               return -errno;
+
+       return perf_evsel__process_group_data(leader, cpu, thread, data);
+}
+
+int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
+{
+       u64 read_format = evsel->attr.read_format;
+
+       if (read_format & PERF_FORMAT_GROUP)
+               return perf_evsel__read_group(evsel, cpu, thread);
+       else
+               return perf_evsel__read_one(evsel, cpu, thread);
+}
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
                              int cpu, int thread, bool scale)
 {
index fb40ca3c6519f6bcbf9883780b0abcff918d560e..de03c18daaf07786ba86ded13615f30a05bb36e5 100644 (file)
@@ -299,6 +299,8 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
                     struct perf_counts_values *count);
 
+int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread);
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
                              int cpu, int thread, bool scale);
 
index 53b9a994a3dc9e50aca6da360d4781d93f52dfc9..35e9848734d6108e00104de58d35e6773a2ccb95 100644 (file)
@@ -128,6 +128,10 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 
 static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 {
+       struct perf_stat_evsel *ps = evsel->priv;
+
+       if (ps)
+               free(ps->group_data);
        zfree(&evsel->priv);
 }
 
index 7522bf10b03e2fcbf26b9c67bebd41e56bff310b..eacaf958e19d2a2750af0ddc5de9f2fa993a3d86 100644 (file)
@@ -28,8 +28,9 @@ enum perf_stat_evsel_id {
 };
 
 struct perf_stat_evsel {
-       struct stats            res_stats[3];
-       enum perf_stat_evsel_id id;
+       struct stats             res_stats[3];
+       enum perf_stat_evsel_id  id;
+       u64                     *group_data;
 };
 
 enum aggr_mode {