perf cpumap: Refactor cpu_map__build_map()
authorIan Rogers <irogers@google.com>
Wed, 5 Jan 2022 06:13:21 +0000 (22:13 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 12 Jan 2022 17:28:22 +0000 (14:28 -0300)
Turn it into a cpu_aggr_map__new(). Pass helper functions. Refactor
builtin-stat calls to manually pass function pointers. Try to reduce
some copy-paste code.

Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Riccardo Mancini <rickyman7@gmail.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Vineet Singh <vineet.singh@intel.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: zhengjun.xing@intel.com
Link: https://lore.kernel.org/r/20220105061351.120843-19-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-stat.c
tools/perf/util/cpumap.c
tools/perf/util/cpumap.h

index d06921c..c55a7fe 100644 (file)
@@ -1322,6 +1322,17 @@ static struct option stat_options[] = {
        OPT_END()
 };
 
+static const char *const aggr_mode__string[] = {
+       [AGGR_CORE] = "core",
+       [AGGR_DIE] = "die",
+       [AGGR_GLOBAL] = "global",
+       [AGGR_NODE] = "node",
+       [AGGR_NONE] = "none",
+       [AGGR_SOCKET] = "socket",
+       [AGGR_THREAD] = "thread",
+       [AGGR_UNSET] = "unset",
+};
+
 static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
                                                int cpu)
 {
@@ -1394,54 +1405,67 @@ static bool term_percore_set(void)
        return false;
 }
 
-static int perf_stat_init_aggr_mode(void)
+static aggr_cpu_id_get_t aggr_mode__get_aggr(enum aggr_mode aggr_mode)
 {
-       int nr;
+       switch (aggr_mode) {
+       case AGGR_SOCKET:
+               return cpu_map__get_socket_aggr_by_cpu;
+       case AGGR_DIE:
+               return cpu_map__get_die_aggr_by_cpu;
+       case AGGR_CORE:
+               return cpu_map__get_core_aggr_by_cpu;
+       case AGGR_NODE:
+               return cpu_map__get_node_aggr_by_cpu;
+       case AGGR_NONE:
+               if (term_percore_set())
+                       return cpu_map__get_core_aggr_by_cpu;
+
+               return NULL;
+       case AGGR_GLOBAL:
+       case AGGR_THREAD:
+       case AGGR_UNSET:
+       default:
+               return NULL;
+       }
+}
 
-       switch (stat_config.aggr_mode) {
+static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)
+{
+       switch (aggr_mode) {
        case AGGR_SOCKET:
-               if (cpu_map__build_socket_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build socket map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_socket_cached;
-               break;
+               return perf_stat__get_socket_cached;
        case AGGR_DIE:
-               if (cpu_map__build_die_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build die map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_die_cached;
-               break;
+               return perf_stat__get_die_cached;
        case AGGR_CORE:
-               if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build core map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_core_cached;
-               break;
+               return perf_stat__get_core_cached;
        case AGGR_NODE:
-               if (cpu_map__build_node_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build core map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_node_cached;
-               break;
+               return perf_stat__get_node_cached;
        case AGGR_NONE:
                if (term_percore_set()) {
-                       if (cpu_map__build_core_map(evsel_list->core.cpus,
-                                                   &stat_config.aggr_map)) {
-                               perror("cannot build core map");
-                               return -1;
-                       }
-                       stat_config.aggr_get_id = perf_stat__get_core_cached;
+                       return perf_stat__get_core_cached;
                }
-               break;
+               return NULL;
        case AGGR_GLOBAL:
        case AGGR_THREAD:
        case AGGR_UNSET:
        default:
-               break;
+               return NULL;
+       }
+}
+
+static int perf_stat_init_aggr_mode(void)
+{
+       int nr;
+       aggr_cpu_id_get_t get_id = aggr_mode__get_aggr(stat_config.aggr_mode);
+
+       if (get_id) {
+               stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.cpus,
+                                                        get_id, /*data=*/NULL);
+               if (!stat_config.aggr_map) {
+                       pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
+                       return -1;
+               }
+               stat_config.aggr_get_id = aggr_mode__get_id(stat_config.aggr_mode);
        }
 
        /*
@@ -1533,30 +1557,6 @@ static struct aggr_cpu_id perf_env__get_node_aggr_by_cpu(int cpu, void *data)
        return id;
 }
 
-static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                     struct cpu_aggr_map **sockp)
-{
-       return cpu_map__build_map(cpus, sockp, perf_env__get_socket_aggr_by_cpu, env);
-}
-
-static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                  struct cpu_aggr_map **diep)
-{
-       return cpu_map__build_map(cpus, diep, perf_env__get_die_aggr_by_cpu, env);
-}
-
-static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                   struct cpu_aggr_map **corep)
-{
-       return cpu_map__build_map(cpus, corep, perf_env__get_core_aggr_by_cpu, env);
-}
-
-static int perf_env__build_node_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                   struct cpu_aggr_map **nodep)
-{
-       return cpu_map__build_map(cpus, nodep, perf_env__get_node_aggr_by_cpu, env);
-}
-
 static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
                                                     int cpu)
 {
@@ -1580,47 +1580,60 @@ static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *conf
        return perf_env__get_node_aggr_by_cpu(cpu, &perf_stat.session->header.env);
 }
 
-static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
+static aggr_cpu_id_get_t aggr_mode__get_aggr_file(enum aggr_mode aggr_mode)
 {
-       struct perf_env *env = &st->session->header.env;
+       switch (aggr_mode) {
+       case AGGR_SOCKET:
+               return perf_env__get_socket_aggr_by_cpu;
+       case AGGR_DIE:
+               return perf_env__get_die_aggr_by_cpu;
+       case AGGR_CORE:
+               return perf_env__get_core_aggr_by_cpu;
+       case AGGR_NODE:
+               return perf_env__get_node_aggr_by_cpu;
+       case AGGR_NONE:
+       case AGGR_GLOBAL:
+       case AGGR_THREAD:
+       case AGGR_UNSET:
+       default:
+               return NULL;
+       }
+}
 
-       switch (stat_config.aggr_mode) {
+static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)
+{
+       switch (aggr_mode) {
        case AGGR_SOCKET:
-               if (perf_env__build_socket_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build socket map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_socket_file;
-               break;
+               return perf_stat__get_socket_file;
        case AGGR_DIE:
-               if (perf_env__build_die_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build die map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_die_file;
-               break;
+               return perf_stat__get_die_file;
        case AGGR_CORE:
-               if (perf_env__build_core_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build core map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_core_file;
-               break;
+               return perf_stat__get_core_file;
        case AGGR_NODE:
-               if (perf_env__build_node_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
-                       perror("cannot build core map");
-                       return -1;
-               }
-               stat_config.aggr_get_id = perf_stat__get_node_file;
-               break;
+               return perf_stat__get_node_file;
        case AGGR_NONE:
        case AGGR_GLOBAL:
        case AGGR_THREAD:
        case AGGR_UNSET:
        default:
-               break;
+               return NULL;
        }
+}
+
+static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
+{
+       struct perf_env *env = &st->session->header.env;
+       aggr_cpu_id_get_t get_id = aggr_mode__get_aggr_file(stat_config.aggr_mode);
 
+       if (!get_id)
+               return 0;
+
+       stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.cpus, get_id, env);
+       if (!stat_config.aggr_map) {
+               pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
+               return -1;
+       }
+       stat_config.aggr_get_id = aggr_mode__get_id_file(stat_config.aggr_mode);
        return 0;
 }
 
index 32f9fc2..c8f9b3f 100644 (file)
@@ -140,7 +140,7 @@ struct aggr_cpu_id cpu_map__get_socket_aggr_by_cpu(int cpu, void *data __maybe_u
        return id;
 }
 
-static int cmp_aggr_cpu_id(const void *a_pointer, const void *b_pointer)
+static int aggr_cpu_id__cmp(const void *a_pointer, const void *b_pointer)
 {
        struct aggr_cpu_id *a = (struct aggr_cpu_id *)a_pointer;
        struct aggr_cpu_id *b = (struct aggr_cpu_id *)b_pointer;
@@ -157,37 +157,40 @@ static int cmp_aggr_cpu_id(const void *a_pointer, const void *b_pointer)
                return a->thread - b->thread;
 }
 
-int cpu_map__build_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **res,
-                      struct aggr_cpu_id (*f)(int cpu, void *data),
-                      void *data)
+struct cpu_aggr_map *cpu_aggr_map__new(const struct perf_cpu_map *cpus,
+                                      aggr_cpu_id_get_t get_id,
+                                      void *data)
 {
-       int nr = cpus->nr;
-       struct cpu_aggr_map *c = cpu_aggr_map__empty_new(nr);
-       int cpu, s2;
-       struct aggr_cpu_id s1;
+       int cpu, idx;
+       struct cpu_aggr_map *c = cpu_aggr_map__empty_new(cpus->nr);
 
        if (!c)
-               return -1;
+               return NULL;
 
        /* Reset size as it may only be partially filled */
        c->nr = 0;
 
-       for (cpu = 0; cpu < nr; cpu++) {
-               s1 = f(cpu, data);
-               for (s2 = 0; s2 < c->nr; s2++) {
-                       if (aggr_cpu_id__equal(&s1, &c->map[s2]))
+       perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
+               bool duplicate = false;
+               struct aggr_cpu_id cpu_id = get_id(cpu, data);
+
+               for (int j = 0; j < c->nr; j++) {
+                       if (aggr_cpu_id__equal(&cpu_id, &c->map[j])) {
+                               duplicate = true;
                                break;
+                       }
                }
-               if (s2 == c->nr) {
-                       c->map[c->nr] = s1;
+               if (!duplicate) {
+                       c->map[c->nr] = cpu_id;
                        c->nr++;
                }
        }
+
        /* ensure we process id in increasing order */
-       qsort(c->map, c->nr, sizeof(struct aggr_cpu_id), cmp_aggr_cpu_id);
+       qsort(c->map, c->nr, sizeof(struct aggr_cpu_id), aggr_cpu_id__cmp);
+
+       return c;
 
-       *res = c;
-       return 0;
 }
 
 int cpu__get_die_id(int cpu)
@@ -253,26 +256,6 @@ struct aggr_cpu_id cpu_map__get_node_aggr_by_cpu(int cpu, void *data __maybe_unu
        return id;
 }
 
-int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **sockp)
-{
-       return cpu_map__build_map(cpus, sockp, cpu_map__get_socket_aggr_by_cpu, NULL);
-}
-
-int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **diep)
-{
-       return cpu_map__build_map(cpus, diep, cpu_map__get_die_aggr_by_cpu, NULL);
-}
-
-int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **corep)
-{
-       return cpu_map__build_map(cpus, corep, cpu_map__get_core_aggr_by_cpu, NULL);
-}
-
-int cpu_map__build_node_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **numap)
-{
-       return cpu_map__build_map(cpus, numap, cpu_map__get_node_aggr_by_cpu, NULL);
-}
-
 /* setup simple routines to easily access node numbers given a cpu number */
 static int get_max_num(char *path, int *max)
 {
index 87545bc..611048e 100644 (file)
@@ -43,10 +43,6 @@ struct aggr_cpu_id cpu_map__get_socket_aggr_by_cpu(int cpu, void *data);
 struct aggr_cpu_id cpu_map__get_die_aggr_by_cpu(int cpu, void *data);
 struct aggr_cpu_id cpu_map__get_core_aggr_by_cpu(int cpu, void *data);
 struct aggr_cpu_id cpu_map__get_node_aggr_by_cpu(int cpu, void *data);
-int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **sockp);
-int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **diep);
-int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **corep);
-int cpu_map__build_node_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **nodep);
 const struct perf_cpu_map *cpu_map__online(void); /* thread unsafe */
 
 int cpu__setup_cpunode_map(void);
@@ -75,10 +71,16 @@ int cpu__get_die_id(int cpu);
  */
 int cpu__get_core_id(int cpu);
 
+typedef struct aggr_cpu_id (*aggr_cpu_id_get_t)(int cpu, void *data);
 
-int cpu_map__build_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **res,
-                      struct aggr_cpu_id (*f)(int cpu, void *data),
-                      void *data);
+/**
+ * cpu_aggr_map__new - Create a cpu_aggr_map with an aggr_cpu_id for each cpu in
+ * cpus. The aggr_cpu_id is created with 'get_id' that may have a data value
+ * passed to it. The cpu_aggr_map is sorted with duplicate values removed.
+ */
+struct cpu_aggr_map *cpu_aggr_map__new(const struct perf_cpu_map *cpus,
+                                      aggr_cpu_id_get_t get_id,
+                                      void *data);
 
 bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);