perf header: Store PMU caps in an array of strings
authorRavi Bangoria <ravi.bangoria@amd.com>
Sat, 4 Jun 2022 04:45:15 +0000 (10:15 +0530)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 24 Jun 2022 16:18:55 +0000 (13:18 -0300)
Currently all capabilities are stored in a single string separated by
NULL character. Instead, store them in an array which makes searching of
capability easier.

Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Ananth Narayan <ananth.narayan@amd.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kim Phillips <kim.phillips@amd.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robert Richter <rrichter@amd.com>
Cc: Sandipan Das <sandipan.das@amd.com>
Cc: Santosh Shukla <santosh.shukla@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: like.xu.linux@gmail.com
Cc: x86@kernel.org
Link: https://lore.kernel.org/r/20220604044519.594-5-ravi.bangoria@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/env.c
tools/perf/util/env.h
tools/perf/util/header.c

index 579e44c..7d3aeb2 100644 (file)
@@ -179,7 +179,7 @@ static void perf_env__purge_bpf(struct perf_env *env __maybe_unused)
 
 void perf_env__exit(struct perf_env *env)
 {
-       int i;
+       int i, j;
 
        perf_env__purge_bpf(env);
        perf_env__purge_cgroups(env);
@@ -196,6 +196,8 @@ void perf_env__exit(struct perf_env *env)
        zfree(&env->sibling_threads);
        zfree(&env->pmu_mappings);
        zfree(&env->cpu);
+       for (i = 0; i < env->nr_cpu_pmu_caps; i++)
+               zfree(&env->cpu_pmu_caps[i]);
        zfree(&env->cpu_pmu_caps);
        zfree(&env->numa_map);
 
@@ -218,6 +220,8 @@ void perf_env__exit(struct perf_env *env)
        zfree(&env->hybrid_nodes);
 
        for (i = 0; i < env->nr_hybrid_cpc_nodes; i++) {
+               for (j = 0; j < env->hybrid_cpc_nodes[i].nr_cpu_pmu_caps; j++)
+                       zfree(&env->hybrid_cpc_nodes[i].cpu_pmu_caps[j]);
                zfree(&env->hybrid_cpc_nodes[i].cpu_pmu_caps);
                zfree(&env->hybrid_cpc_nodes[i].pmu_name);
        }
index a3541f9..43aab59 100644 (file)
@@ -46,7 +46,7 @@ struct hybrid_node {
 struct hybrid_cpc_node {
        int             nr_cpu_pmu_caps;
        unsigned int    max_branches;
-       char            *cpu_pmu_caps;
+       char            **cpu_pmu_caps;
        char            *pmu_name;
 };
 
@@ -81,7 +81,7 @@ struct perf_env {
        char                    *sibling_dies;
        char                    *sibling_threads;
        char                    *pmu_mappings;
-       char                    *cpu_pmu_caps;
+       char                    **cpu_pmu_caps;
        struct cpu_topology_map *cpu;
        struct cpu_cache_level  *caches;
        int                      caches_cnt;
index 8c0b85e..c9d1f76 100644 (file)
@@ -2051,26 +2051,21 @@ static void print_compressed(struct feat_fd *ff, FILE *fp)
                ff->ph->env.comp_level, ff->ph->env.comp_ratio);
 }
 
-static void print_per_cpu_pmu_caps(FILE *fp, int nr_caps, char *cpu_pmu_caps,
+static void print_per_cpu_pmu_caps(FILE *fp, int nr_caps, char **cpu_pmu_caps,
                                   char *pmu_name)
 {
-       const char *delimiter;
-       char *str, buf[128];
+       const char *delimiter = "";
+       int i;
 
        if (!nr_caps) {
                fprintf(fp, "# %s pmu capabilities: not available\n", pmu_name);
                return;
        }
 
-       scnprintf(buf, sizeof(buf), "# %s pmu capabilities: ", pmu_name);
-
-       delimiter = buf;
-
-       str = cpu_pmu_caps;
-       while (nr_caps--) {
-               fprintf(fp, "%s%s", delimiter, str);
+       fprintf(fp, "# %s pmu capabilities: ", pmu_name);
+       for (i = 0; i < nr_caps; i++) {
+               fprintf(fp, "%s%s", delimiter, cpu_pmu_caps[i]);
                delimiter = ", ";
-               str += strlen(str) + 1;
        }
 
        fprintf(fp, "\n");
@@ -3202,27 +3197,26 @@ static int process_compressed(struct feat_fd *ff,
 }
 
 static int process_per_cpu_pmu_caps(struct feat_fd *ff, int *nr_cpu_pmu_caps,
-                                   char **cpu_pmu_caps,
+                                   char ***cpu_pmu_caps,
                                    unsigned int *max_branches)
 {
-       char *name, *value;
-       struct strbuf sb;
-       u32 nr_caps;
+       char *name, *value, *ptr;
+       u32 nr_caps, i;
+
+       *nr_cpu_pmu_caps = 0;
+       *cpu_pmu_caps = NULL;
 
        if (do_read_u32(ff, &nr_caps))
                return -1;
 
-       if (!nr_caps) {
-               pr_debug("cpu pmu capabilities not available\n");
+       if (!nr_caps)
                return 0;
-       }
-
-       *nr_cpu_pmu_caps = nr_caps;
 
-       if (strbuf_init(&sb, 128) < 0)
+       *cpu_pmu_caps = zalloc(sizeof(char *) * nr_caps);
+       if (!*cpu_pmu_caps)
                return -1;
 
-       while (nr_caps--) {
+       for (i = 0; i < nr_caps; i++) {
                name = do_read_string(ff);
                if (!name)
                        goto error;
@@ -3231,12 +3225,10 @@ static int process_per_cpu_pmu_caps(struct feat_fd *ff, int *nr_cpu_pmu_caps,
                if (!value)
                        goto free_name;
 
-               if (strbuf_addf(&sb, "%s=%s", name, value) < 0)
+               if (asprintf(&ptr, "%s=%s", name, value) < 0)
                        goto free_value;
 
-               /* include a NULL character at the end */
-               if (strbuf_add(&sb, "", 1) < 0)
-                       goto free_value;
+               (*cpu_pmu_caps)[i] = ptr;
 
                if (!strcmp(name, "branches"))
                        *max_branches = atoi(value);
@@ -3244,7 +3236,7 @@ static int process_per_cpu_pmu_caps(struct feat_fd *ff, int *nr_cpu_pmu_caps,
                free(value);
                free(name);
        }
-       *cpu_pmu_caps = strbuf_detach(&sb, NULL);
+       *nr_cpu_pmu_caps = nr_caps;
        return 0;
 
 free_value:
@@ -3252,16 +3244,24 @@ free_value:
 free_name:
        free(name);
 error:
-       strbuf_release(&sb);
+       for (; i > 0; i--)
+               free((*cpu_pmu_caps)[i - 1]);
+       free(*cpu_pmu_caps);
+       *cpu_pmu_caps = NULL;
+       *nr_cpu_pmu_caps = 0;
        return -1;
 }
 
 static int process_cpu_pmu_caps(struct feat_fd *ff,
                                void *data __maybe_unused)
 {
-       return process_per_cpu_pmu_caps(ff, &ff->ph->env.nr_cpu_pmu_caps,
+       int ret = process_per_cpu_pmu_caps(ff, &ff->ph->env.nr_cpu_pmu_caps,
                                        &ff->ph->env.cpu_pmu_caps,
                                        &ff->ph->env.max_branches);
+
+       if (!ret && !ff->ph->env.cpu_pmu_caps)
+               pr_debug("cpu pmu capabilities not available\n");
+       return ret;
 }
 
 static int process_hybrid_cpu_pmu_caps(struct feat_fd *ff,
@@ -3270,6 +3270,7 @@ static int process_hybrid_cpu_pmu_caps(struct feat_fd *ff,
        struct hybrid_cpc_node *nodes;
        u32 nr_pmu, i;
        int ret;
+       int j;
 
        if (do_read_u32(ff, &nr_pmu))
                return -1;
@@ -3297,6 +3298,8 @@ static int process_hybrid_cpu_pmu_caps(struct feat_fd *ff,
                        ret = -1;
                        goto err;
                }
+               if (!n->nr_cpu_pmu_caps)
+                       pr_debug("%s pmu capabilities not available\n", n->pmu_name);
        }
 
        ff->ph->env.nr_hybrid_cpc_nodes = nr_pmu;
@@ -3305,6 +3308,8 @@ static int process_hybrid_cpu_pmu_caps(struct feat_fd *ff,
 
 err:
        for (i = 0; i < nr_pmu; i++) {
+               for (j = 0; j < nodes[i].nr_cpu_pmu_caps; j++)
+                       free(nodes[i].cpu_pmu_caps[j]);
                free(nodes[i].cpu_pmu_caps);
                free(nodes[i].pmu_name);
        }