Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf values: Use evsel rather than evsel->idx

An evsel idx may not be stable due to sorting, evlist removal,
etc. Avoid use of the idx where the evsel itself can be used to avoid
these problems. This removed 1 values array and duplicated evsel name
strings.

Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Chen Ni <nichen@iscas.ac.cn>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241114230713.330701-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
2f4847b5 2f0539fa

+51 -68
+1 -3
tools/perf/builtin-report.c
··· 348 348 struct report *rep = container_of(tool, struct report, tool); 349 349 350 350 if (rep->show_threads) { 351 - const char *name = evsel__name(evsel); 352 351 int err = perf_read_values_add_value(&rep->show_threads_values, 353 352 event->read.pid, event->read.tid, 354 - evsel->core.idx, 355 - name, 353 + evsel, 356 354 event->read.value); 357 355 358 356 if (err)
+45 -61
tools/perf/util/values.c
··· 8 8 9 9 #include "values.h" 10 10 #include "debug.h" 11 + #include "evsel.h" 11 12 12 13 int perf_read_values_init(struct perf_read_values *values) 13 14 { ··· 23 22 values->threads = 0; 24 23 25 24 values->counters_max = 16; 26 - values->counterrawid = malloc(values->counters_max 27 - * sizeof(*values->counterrawid)); 28 - values->countername = malloc(values->counters_max 29 - * sizeof(*values->countername)); 30 - if (!values->counterrawid || !values->countername) { 31 - pr_debug("failed to allocate read_values counters arrays"); 25 + values->counters = malloc(values->counters_max * sizeof(*values->counters)); 26 + if (!values->counters) { 27 + pr_debug("failed to allocate read_values counters array"); 32 28 goto out_free_counter; 33 29 } 34 - values->counters = 0; 30 + values->num_counters = 0; 35 31 36 32 return 0; 37 33 38 34 out_free_counter: 39 - zfree(&values->counterrawid); 40 - zfree(&values->countername); 35 + zfree(&values->counters); 41 36 out_free_pid: 42 37 zfree(&values->pid); 43 38 zfree(&values->tid); ··· 53 56 zfree(&values->value); 54 57 zfree(&values->pid); 55 58 zfree(&values->tid); 56 - zfree(&values->counterrawid); 57 - for (i = 0; i < values->counters; i++) 58 - zfree(&values->countername[i]); 59 - zfree(&values->countername); 59 + zfree(&values->counters); 60 60 } 61 61 62 62 static int perf_read_values__enlarge_threads(struct perf_read_values *values) ··· 110 116 111 117 static int perf_read_values__enlarge_counters(struct perf_read_values *values) 112 118 { 113 - char **countername; 114 - int i, counters_max = values->counters_max * 2; 115 - u64 *counterrawid = realloc(values->counterrawid, counters_max * sizeof(*values->counterrawid)); 119 + int counters_max = values->counters_max * 2; 120 + struct evsel **new_counters = realloc(values->counters, 121 + counters_max * sizeof(*values->counters)); 116 122 117 - if (!counterrawid) { 118 - pr_debug("failed to enlarge read_values rawid array"); 123 + if (!new_counters) { 124 + pr_debug("failed to enlarge read_values counters array"); 119 125 goto out_enomem; 120 126 } 121 127 122 - countername = realloc(values->countername, counters_max * sizeof(*values->countername)); 123 - if (!countername) { 124 - pr_debug("failed to enlarge read_values rawid array"); 125 - goto out_free_rawid; 126 - } 127 - 128 - for (i = 0; i < values->threads; i++) { 128 + for (int i = 0; i < values->threads; i++) { 129 129 u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value)); 130 - int j; 131 130 132 131 if (!value) { 133 132 pr_debug("failed to enlarge read_values ->values array"); 134 - goto out_free_name; 133 + goto out_free_counters; 135 134 } 136 135 137 - for (j = values->counters_max; j < counters_max; j++) 136 + for (int j = values->counters_max; j < counters_max; j++) 138 137 value[j] = 0; 139 138 140 139 values->value[i] = value; 141 140 } 142 141 143 142 values->counters_max = counters_max; 144 - values->counterrawid = counterrawid; 145 - values->countername = countername; 143 + values->counters = new_counters; 146 144 147 145 return 0; 148 - out_free_name: 149 - free(countername); 150 - out_free_rawid: 151 - free(counterrawid); 146 + out_free_counters: 147 + free(new_counters); 152 148 out_enomem: 153 149 return -ENOMEM; 154 150 } 155 151 156 152 static int perf_read_values__findnew_counter(struct perf_read_values *values, 157 - u64 rawid, const char *name) 153 + struct evsel *evsel) 158 154 { 159 155 int i; 160 156 161 - for (i = 0; i < values->counters; i++) 162 - if (values->counterrawid[i] == rawid) 157 + for (i = 0; i < values->num_counters; i++) 158 + if (values->counters[i] == evsel) 163 159 return i; 164 160 165 - if (values->counters == values->counters_max) { 166 - i = perf_read_values__enlarge_counters(values); 167 - if (i) 168 - return i; 161 + if (values->num_counters == values->counters_max) { 162 + int err = perf_read_values__enlarge_counters(values); 163 + 164 + if (err) 165 + return err; 169 166 } 170 167 171 - i = values->counters++; 172 - values->counterrawid[i] = rawid; 173 - values->countername[i] = strdup(name); 168 + i = values->num_counters++; 169 + values->counters[i] = evsel; 174 170 175 171 return i; 176 172 } 177 173 178 174 int perf_read_values_add_value(struct perf_read_values *values, 179 175 u32 pid, u32 tid, 180 - u64 rawid, const char *name, u64 value) 176 + struct evsel *evsel, u64 value) 181 177 { 182 178 int tindex, cindex; 183 179 184 180 tindex = perf_read_values__findnew_thread(values, pid, tid); 185 181 if (tindex < 0) 186 182 return tindex; 187 - cindex = perf_read_values__findnew_counter(values, rawid, name); 183 + cindex = perf_read_values__findnew_counter(values, evsel); 188 184 if (cindex < 0) 189 185 return cindex; 190 186 ··· 189 205 int pidwidth, tidwidth; 190 206 int *counterwidth; 191 207 192 - counterwidth = malloc(values->counters * sizeof(*counterwidth)); 208 + counterwidth = malloc(values->num_counters * sizeof(*counterwidth)); 193 209 if (!counterwidth) { 194 210 fprintf(fp, "INTERNAL ERROR: Failed to allocate counterwidth array\n"); 195 211 return; 196 212 } 197 213 tidwidth = 3; 198 214 pidwidth = 3; 199 - for (j = 0; j < values->counters; j++) 200 - counterwidth[j] = strlen(values->countername[j]); 215 + for (j = 0; j < values->num_counters; j++) 216 + counterwidth[j] = strlen(evsel__name(values->counters[j])); 201 217 for (i = 0; i < values->threads; i++) { 202 218 int width; 203 219 ··· 207 223 width = snprintf(NULL, 0, "%d", values->tid[i]); 208 224 if (width > tidwidth) 209 225 tidwidth = width; 210 - for (j = 0; j < values->counters; j++) { 226 + for (j = 0; j < values->num_counters; j++) { 211 227 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]); 212 228 if (width > counterwidth[j]) 213 229 counterwidth[j] = width; ··· 215 231 } 216 232 217 233 fprintf(fp, "# %*s %*s", pidwidth, "PID", tidwidth, "TID"); 218 - for (j = 0; j < values->counters; j++) 219 - fprintf(fp, " %*s", counterwidth[j], values->countername[j]); 234 + for (j = 0; j < values->num_counters; j++) 235 + fprintf(fp, " %*s", counterwidth[j], evsel__name(values->counters[j])); 220 236 fprintf(fp, "\n"); 221 237 222 238 for (i = 0; i < values->threads; i++) { 223 239 fprintf(fp, " %*d %*d", pidwidth, values->pid[i], 224 240 tidwidth, values->tid[i]); 225 - for (j = 0; j < values->counters; j++) 241 + for (j = 0; j < values->num_counters; j++) 226 242 fprintf(fp, " %*" PRIu64, 227 243 counterwidth[j], values->value[i][j]); 228 244 fprintf(fp, "\n"); ··· 250 266 if (width > tidwidth) 251 267 tidwidth = width; 252 268 } 253 - for (j = 0; j < values->counters; j++) { 254 - width = strlen(values->countername[j]); 269 + for (j = 0; j < values->num_counters; j++) { 270 + width = strlen(evsel__name(values->counters[j])); 255 271 if (width > namewidth) 256 272 namewidth = width; 257 - width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]); 273 + width = snprintf(NULL, 0, "%x", values->counters[j]->core.idx); 258 274 if (width > rawwidth) 259 275 rawwidth = width; 260 276 } 261 277 for (i = 0; i < values->threads; i++) { 262 - for (j = 0; j < values->counters; j++) { 278 + for (j = 0; j < values->num_counters; j++) { 263 279 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]); 264 280 if (width > countwidth) 265 281 countwidth = width; ··· 271 287 namewidth, "Name", rawwidth, "Raw", 272 288 countwidth, "Count"); 273 289 for (i = 0; i < values->threads; i++) 274 - for (j = 0; j < values->counters; j++) 275 - fprintf(fp, " %*d %*d %*s %*" PRIx64 " %*" PRIu64, 290 + for (j = 0; j < values->num_counters; j++) 291 + fprintf(fp, " %*d %*d %*s %*x %*" PRIu64, 276 292 pidwidth, values->pid[i], 277 293 tidwidth, values->tid[i], 278 - namewidth, values->countername[j], 279 - rawwidth, values->counterrawid[j], 294 + namewidth, evsel__name(values->counters[j]), 295 + rawwidth, values->counters[j]->core.idx, 280 296 countwidth, values->value[i][j]); 281 297 } 282 298
+5 -4
tools/perf/util/values.h
··· 5 5 #include <stdio.h> 6 6 #include <linux/types.h> 7 7 8 + struct evsel; 9 + 8 10 struct perf_read_values { 9 11 int threads; 10 12 int threads_max; 11 13 u32 *pid, *tid; 12 - int counters; 14 + int num_counters; 13 15 int counters_max; 14 - u64 *counterrawid; 15 - char **countername; 16 + struct evsel **counters; 16 17 u64 **value; 17 18 }; 18 19 ··· 22 21 23 22 int perf_read_values_add_value(struct perf_read_values *values, 24 23 u32 pid, u32 tid, 25 - u64 rawid, const char *name, u64 value); 24 + struct evsel *evsel, u64 value); 26 25 27 26 void perf_read_values_display(FILE *fp, struct perf_read_values *values, 28 27 int raw);