After perf_evlist__create_maps() being executed, we can get all
threads from /proc. And via thread_map__nr(), we can also get
the number of threads.

With the number of threads, the patch allocates a buffer which
will record the shadow stats for these threads.

The buffer pointer is saved in stat_config.

Signed-off-by: Jin Yao <yao....@linux.intel.com>
---
 tools/perf/builtin-stat.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/stat.h    |  2 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1edc082..4b88803 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -214,8 +214,13 @@ static inline void diff_timespec(struct timespec *r, 
struct timespec *a,
 
 static void perf_stat__reset_stats(void)
 {
+       int i;
+
        perf_evlist__reset_stats(evsel_list);
        perf_stat__reset_shadow_stats();
+
+       for (i = 0; i < stat_config.stats_num; i++)
+               perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
 }
 
 static int create_perf_stat_counter(struct perf_evsel *evsel)
@@ -2496,6 +2501,35 @@ int process_cpu_map_event(struct perf_tool *tool,
        return set_maps(st);
 }
 
+static int runtime_stat_alloc(struct perf_stat_config *config, int nthreads)
+{
+       int i;
+
+       config->stats = calloc(nthreads, sizeof(struct runtime_stat));
+       if (!config->stats)
+               return -1;
+
+       config->stats_num = nthreads;
+
+       for (i = 0; i < nthreads; i++)
+               runtime_stat__init(&config->stats[i]);
+
+       return 0;
+}
+
+static void runtime_stat_free(struct perf_stat_config *config)
+{
+       int i;
+
+       if (!config->stats)
+               return;
+
+       for (i = 0; i < config->stats_num; i++)
+               runtime_stat__free(&config->stats[i]);
+
+       free(config->stats);
+}
+
 static const char * const stat_report_usage[] = {
        "perf stat report [<options>]",
        NULL,
@@ -2751,8 +2785,15 @@ int cmd_stat(int argc, const char **argv)
         * Initialize thread_map with comm names,
         * so we could print it out on output.
         */
-       if (stat_config.aggr_mode == AGGR_THREAD)
+       if (stat_config.aggr_mode == AGGR_THREAD) {
                thread_map__read_comms(evsel_list->threads);
+               if (target.system_wide) {
+                       if (runtime_stat_alloc(&stat_config,
+                               thread_map__nr(evsel_list->threads))) {
+                               goto out;
+                       }
+               }
+       }
 
        if (interval && interval < 100) {
                if (interval < 10) {
@@ -2842,5 +2883,8 @@ int cmd_stat(int argc, const char **argv)
                sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
 
        perf_evlist__delete(evsel_list);
+
+       runtime_stat_free(&stat_config);
+
        return status;
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1a99fcf..5f91103 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -91,6 +91,8 @@ struct perf_stat_config {
        bool            scale;
        FILE            *output;
        unsigned int    interval;
+       struct runtime_stat *stats;
+       int             stats_num;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.7.4

Reply via email to