Merge branch 'next' into for-linus
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / stat.c
index 4014b709f956b96b86dab3526f3b35fec6d8c166..f2a0d1521e266a32a0df10b60f22d88107fae276 100644 (file)
@@ -1,6 +1,8 @@
 #include <math.h>
 #include "stat.h"
+#include "evlist.h"
 #include "evsel.h"
+#include "thread_map.h"
 
 void update_stats(struct stats *stats, u64 val)
 {
@@ -95,33 +97,46 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
        }
 }
 
-struct perf_counts *perf_counts__new(int ncpus)
+struct perf_counts *perf_counts__new(int ncpus, int nthreads)
 {
-       int size = sizeof(struct perf_counts) +
-                  ncpus * sizeof(struct perf_counts_values);
+       struct perf_counts *counts = zalloc(sizeof(*counts));
 
-       return zalloc(size);
+       if (counts) {
+               struct xyarray *values;
+
+               values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
+               if (!values) {
+                       free(counts);
+                       return NULL;
+               }
+
+               counts->values = values;
+       }
+
+       return counts;
 }
 
 void perf_counts__delete(struct perf_counts *counts)
 {
-       free(counts);
+       if (counts) {
+               xyarray__delete(counts->values);
+               free(counts);
+       }
 }
 
-static void perf_counts__reset(struct perf_counts *counts, int ncpus)
+static void perf_counts__reset(struct perf_counts *counts)
 {
-       memset(counts, 0, (sizeof(*counts) +
-              (ncpus * sizeof(struct perf_counts_values))));
+       xyarray__reset(counts->values);
 }
 
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
+void perf_evsel__reset_counts(struct perf_evsel *evsel)
 {
-       perf_counts__reset(evsel->counts, ncpus);
+       perf_counts__reset(evsel->counts);
 }
 
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
 {
-       evsel->counts = perf_counts__new(ncpus);
+       evsel->counts = perf_counts__new(ncpus, nthreads);
        return evsel->counts != NULL ? 0 : -ENOMEM;
 }
 
@@ -130,3 +145,96 @@ void perf_evsel__free_counts(struct perf_evsel *evsel)
        perf_counts__delete(evsel->counts);
        evsel->counts = NULL;
 }
+
+void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
+{
+       int i;
+       struct perf_stat *ps = evsel->priv;
+
+       for (i = 0; i < 3; i++)
+               init_stats(&ps->res_stats[i]);
+
+       perf_stat_evsel_id_init(evsel);
+}
+
+int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
+{
+       evsel->priv = zalloc(sizeof(struct perf_stat));
+       if (evsel->priv == NULL)
+               return -ENOMEM;
+       perf_evsel__reset_stat_priv(evsel);
+       return 0;
+}
+
+void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
+{
+       zfree(&evsel->priv);
+}
+
+int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+                                     int ncpus, int nthreads)
+{
+       struct perf_counts *counts;
+
+       counts = perf_counts__new(ncpus, nthreads);
+       if (counts)
+               evsel->prev_raw_counts = counts;
+
+       return counts ? 0 : -ENOMEM;
+}
+
+void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
+{
+       perf_counts__delete(evsel->prev_raw_counts);
+       evsel->prev_raw_counts = NULL;
+}
+
+int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
+{
+       int ncpus = perf_evsel__nr_cpus(evsel);
+       int nthreads = thread_map__nr(evsel->threads);
+
+       if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
+           perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
+           (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
+               return -ENOMEM;
+
+       return 0;
+}
+
+int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel) {
+               if (perf_evsel__alloc_stats(evsel, alloc_raw))
+                       goto out_free;
+       }
+
+       return 0;
+
+out_free:
+       perf_evlist__free_stats(evlist);
+       return -1;
+}
+
+void perf_evlist__free_stats(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel) {
+               perf_evsel__free_stat_priv(evsel);
+               perf_evsel__free_counts(evsel);
+               perf_evsel__free_prev_raw_counts(evsel);
+       }
+}
+
+void perf_evlist__reset_stats(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel) {
+               perf_evsel__reset_stat_priv(evsel);
+               perf_evsel__reset_counts(evsel);
+       }
+}