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

perf dsos: Move the dsos struct and its methods to separate source files

So that we can reduce the header dependency tree further, in the process
noticed that lots of places were getting even things like build-id
routines and 'struct perf_tool' definition indirectly, so fix all those
too.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/n/tip-ti0btma9ow5ndrytyoqdk62j@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+331 -257
+1
tools/perf/builtin-annotate.c
··· 27 27 #include "util/thread.h" 28 28 #include "util/sort.h" 29 29 #include "util/hist.h" 30 + #include "util/dso.h" 30 31 #include "util/map.h" 31 32 #include "util/session.h" 32 33 #include "util/tool.h"
+1
tools/perf/builtin-buildid-cache.c
··· 22 22 #include "util/strlist.h" 23 23 #include "util/build-id.h" 24 24 #include "util/session.h" 25 + #include "util/dso.h" 25 26 #include "util/symbol.h" 26 27 #include "util/time-utils.h" 27 28 #include "util/util.h"
+1
tools/perf/builtin-buildid-list.c
··· 12 12 #include "util/build-id.h" 13 13 #include "util/cache.h" 14 14 #include "util/debug.h" 15 + #include "util/dso.h" 15 16 #include <subcmd/parse-options.h> 16 17 #include "util/session.h" 17 18 #include "util/symbol.h"
+1
tools/perf/builtin-inject.c
··· 9 9 #include "builtin.h" 10 10 11 11 #include "util/color.h" 12 + #include "util/dso.h" 12 13 #include "util/evlist.h" 13 14 #include "util/evsel.h" 14 15 #include "util/map.h"
+1
tools/perf/builtin-kallsyms.c
··· 11 11 #include <linux/compiler.h> 12 12 #include <subcmd/parse-options.h> 13 13 #include "debug.h" 14 + #include "dso.h" 14 15 #include "machine.h" 15 16 #include "map.h" 16 17 #include "symbol.h"
+1
tools/perf/builtin-kmem.c
··· 2 2 #include "builtin.h" 3 3 #include "perf.h" 4 4 5 + #include "util/dso.h" 5 6 #include "util/evlist.h" 6 7 #include "util/evsel.h" 7 8 #include "util/config.h"
+1
tools/perf/builtin-kvm.c
··· 2 2 #include "builtin.h" 3 3 #include "perf.h" 4 4 5 + #include "util/build-id.h" 5 6 #include "util/evsel.h" 6 7 #include "util/evlist.h" 7 8 #include "util/term.h"
+1
tools/perf/builtin-mem.c
··· 13 13 #include "util/data.h" 14 14 #include "util/mem-events.h" 15 15 #include "util/debug.h" 16 + #include "util/dso.h" 16 17 #include "util/map.h" 17 18 #include "util/symbol.h" 18 19
+1
tools/perf/builtin-report.c
··· 12 12 13 13 #include "util/annotate.h" 14 14 #include "util/color.h" 15 + #include "util/dso.h" 15 16 #include <linux/list.h> 16 17 #include <linux/rbtree.h> 17 18 #include <linux/err.h>
+1
tools/perf/builtin-script.c
··· 4 4 #include "util/cache.h" 5 5 #include "util/counts.h" 6 6 #include "util/debug.h" 7 + #include "util/dso.h" 7 8 #include <subcmd/exec-cmd.h> 8 9 #include "util/header.h" 9 10 #include <subcmd/parse-options.h>
+1
tools/perf/builtin-top.c
··· 24 24 #include "util/bpf-event.h" 25 25 #include "util/config.h" 26 26 #include "util/color.h" 27 + #include "util/dso.h" 27 28 #include "util/evlist.h" 28 29 #include "util/evsel.h" 29 30 #include "util/event.h"
+2
tools/perf/builtin-trace.c
··· 25 25 #include "util/color.h" 26 26 #include "util/config.h" 27 27 #include "util/debug.h" 28 + #include "util/dso.h" 28 29 #include "util/env.h" 29 30 #include "util/event.h" 30 31 #include "util/evlist.h" ··· 43 42 #include "util/intlist.h" 44 43 #include "util/thread_map.h" 45 44 #include "util/stat.h" 45 + #include "util/tool.h" 46 46 #include "util/util.h" 47 47 #include "trace/beauty/beauty.h" 48 48 #include "trace-event.h"
+1
tools/perf/tests/code-reading.c
··· 12 12 #include <perf/evlist.h> 13 13 14 14 #include "debug.h" 15 + #include "dso.h" 15 16 #include "parse-events.h" 16 17 #include "evlist.h" 17 18 #include "evsel.h"
+1
tools/perf/tests/dso-data.c
··· 9 9 #include <sys/time.h> 10 10 #include <sys/resource.h> 11 11 #include <api/fs/fs.h> 12 + #include "dso.h" 12 13 #include "util.h" 13 14 #include "machine.h" 14 15 #include "symbol.h"
+1
tools/perf/tests/dwarf-unwind.c
··· 3 3 #include <linux/types.h> 4 4 #include <linux/zalloc.h> 5 5 #include <inttypes.h> 6 + #include <limits.h> 6 7 #include <unistd.h> 7 8 #include "tests.h" 8 9 #include "debug.h"
+1
tools/perf/tests/event_update.c
··· 4 4 #include "evlist.h" 5 5 #include "evsel.h" 6 6 #include "machine.h" 7 + #include "tool.h" 7 8 #include "tests.h" 8 9 #include "debug.h" 9 10
+1
tools/perf/tests/hists_common.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <inttypes.h> 3 3 #include "util/debug.h" 4 + #include "util/dso.h" 4 5 #include "util/map.h" 5 6 #include "util/symbol.h" 6 7 #include "util/sort.h"
+1
tools/perf/tests/hists_cumulate.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "util/debug.h" 3 + #include "util/dso.h" 3 4 #include "util/event.h" 4 5 #include "util/map.h" 5 6 #include "util/symbol.h"
+1
tools/perf/tests/hists_output.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "util/debug.h" 3 + #include "util/dso.h" 3 4 #include "util/event.h" 4 5 #include "util/map.h" 5 6 #include "util/symbol.h"
+1
tools/perf/tests/vmlinux-kallsyms.c
··· 4 4 #include <inttypes.h> 5 5 #include <string.h> 6 6 #include <stdlib.h> 7 + #include "dso.h" 7 8 #include "map.h" 8 9 #include "symbol.h" 9 10 #include "util.h"
+1
tools/perf/ui/browsers/annotate.c
··· 5 5 #include "../util.h" 6 6 #include "../../util/annotate.h" 7 7 #include "../../util/debug.h" 8 + #include "../../util/dso.h" 8 9 #include "../../util/hist.h" 9 10 #include "../../util/sort.h" 10 11 #include "../../util/map.h"
+1
tools/perf/ui/browsers/hists.c
··· 12 12 #include <linux/zalloc.h> 13 13 14 14 #include "../../util/debug.h" 15 + #include "../../util/dso.h" 15 16 #include "../../util/callchain.h" 16 17 #include "../../util/evsel.h" 17 18 #include "../../util/evlist.h"
+1
tools/perf/util/Build
··· 36 36 perf-y += top.o 37 37 perf-y += usage.o 38 38 perf-y += dso.o 39 + perf-y += dsos.o 39 40 perf-y += symbol.o 40 41 perf-y += symbol_fprintf.o 41 42 perf-y += color.o
+1
tools/perf/util/bpf-event.c
··· 8 8 #include <linux/err.h> 9 9 #include "bpf-event.h" 10 10 #include "debug.h" 11 + #include "dso.h" 11 12 #include "symbol.h" 12 13 #include "machine.h" 13 14 #include "env.h"
+1
tools/perf/util/callchain.c
··· 22 22 #include "asm/bug.h" 23 23 24 24 #include "debug.h" 25 + #include "dso.h" 25 26 #include "hist.h" 26 27 #include "sort.h" 27 28 #include "machine.h"
+2
tools/perf/util/cs-etm.c
··· 21 21 #include "cs-etm.h" 22 22 #include "cs-etm-decoder/cs-etm-decoder.h" 23 23 #include "debug.h" 24 + #include "dso.h" 24 25 #include "evlist.h" 25 26 #include "intlist.h" 26 27 #include "machine.h" 27 28 #include "map.h" 28 29 #include "perf.h" 29 30 #include "symbol.h" 31 + #include "tool.h" 30 32 #include "thread.h" 31 33 #include "thread_map.h" 32 34 #include "thread-stack.h"
+1
tools/perf/util/db-export.c
··· 7 7 #include <errno.h> 8 8 #include <stdlib.h> 9 9 10 + #include "dso.h" 10 11 #include "evsel.h" 11 12 #include "machine.h" 12 13 #include "thread.h"
+3 -232
tools/perf/util/dso.c
··· 10 10 #include <unistd.h> 11 11 #include <errno.h> 12 12 #include <fcntl.h> 13 - #include <libgen.h> 14 13 #include <bpf/libbpf.h> 15 14 #include "bpf-event.h" 16 15 #include "compress.h" ··· 19 20 #include "symbol.h" 20 21 #include "srcline.h" 21 22 #include "dso.h" 23 + #include "dsos.h" 22 24 #include "machine.h" 23 25 #include "auxtrace.h" 24 26 #include "util.h" /* O_CLOEXEC for older systems */ ··· 1094 1094 return dso; 1095 1095 } 1096 1096 1097 - /* 1098 - * Find a matching entry and/or link current entry to RB tree. 1099 - * Either one of the dso or name parameter must be non-NULL or the 1100 - * function will not work. 1101 - */ 1102 - static struct dso *__dso__findlink_by_longname(struct rb_root *root, 1103 - struct dso *dso, const char *name) 1104 - { 1105 - struct rb_node **p = &root->rb_node; 1106 - struct rb_node *parent = NULL; 1107 - 1108 - if (!name) 1109 - name = dso->long_name; 1110 - /* 1111 - * Find node with the matching name 1112 - */ 1113 - while (*p) { 1114 - struct dso *this = rb_entry(*p, struct dso, rb_node); 1115 - int rc = strcmp(name, this->long_name); 1116 - 1117 - parent = *p; 1118 - if (rc == 0) { 1119 - /* 1120 - * In case the new DSO is a duplicate of an existing 1121 - * one, print a one-time warning & put the new entry 1122 - * at the end of the list of duplicates. 1123 - */ 1124 - if (!dso || (dso == this)) 1125 - return this; /* Find matching dso */ 1126 - /* 1127 - * The core kernel DSOs may have duplicated long name. 1128 - * In this case, the short name should be different. 1129 - * Comparing the short names to differentiate the DSOs. 1130 - */ 1131 - rc = strcmp(dso->short_name, this->short_name); 1132 - if (rc == 0) { 1133 - pr_err("Duplicated dso name: %s\n", name); 1134 - return NULL; 1135 - } 1136 - } 1137 - if (rc < 0) 1138 - p = &parent->rb_left; 1139 - else 1140 - p = &parent->rb_right; 1141 - } 1142 - if (dso) { 1143 - /* Add new node and rebalance tree */ 1144 - rb_link_node(&dso->rb_node, parent, p); 1145 - rb_insert_color(&dso->rb_node, root); 1146 - dso->root = root; 1147 - } 1148 - return NULL; 1149 - } 1150 - 1151 - static inline struct dso *__dso__find_by_longname(struct rb_root *root, 1152 - const char *name) 1153 - { 1154 - return __dso__findlink_by_longname(root, NULL, name); 1155 - } 1156 - 1157 1097 void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 1158 1098 { 1159 1099 struct rb_root *root = dso->root; ··· 1107 1167 if (root) { 1108 1168 rb_erase(&dso->rb_node, root); 1109 1169 /* 1110 - * __dso__findlink_by_longname() isn't guaranteed to add it 1170 + * __dsos__findnew_link_by_longname() isn't guaranteed to add it 1111 1171 * back, so a clean removal is required here. 1112 1172 */ 1113 1173 RB_CLEAR_NODE(&dso->rb_node); ··· 1119 1179 dso->long_name_allocated = name_allocated; 1120 1180 1121 1181 if (root) 1122 - __dso__findlink_by_longname(root, dso, NULL); 1182 + __dsos__findnew_link_by_longname(root, dso, NULL); 1123 1183 } 1124 1184 1125 1185 void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) ··· 1133 1193 dso->short_name = name; 1134 1194 dso->short_name_len = strlen(name); 1135 1195 dso->short_name_allocated = name_allocated; 1136 - } 1137 - 1138 - static void dso__set_basename(struct dso *dso) 1139 - { 1140 - char *base, *lname; 1141 - int tid; 1142 - 1143 - if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) { 1144 - if (asprintf(&base, "[JIT] tid %d", tid) < 0) 1145 - return; 1146 - } else { 1147 - /* 1148 - * basename() may modify path buffer, so we must pass 1149 - * a copy. 1150 - */ 1151 - lname = strdup(dso->long_name); 1152 - if (!lname) 1153 - return; 1154 - 1155 - /* 1156 - * basename() may return a pointer to internal 1157 - * storage which is reused in subsequent calls 1158 - * so copy the result. 1159 - */ 1160 - base = strdup(basename(lname)); 1161 - 1162 - free(lname); 1163 - 1164 - if (!base) 1165 - return; 1166 - } 1167 - dso__set_short_name(dso, base, true); 1168 1196 } 1169 1197 1170 1198 int dso__name_len(const struct dso *dso) ··· 1283 1375 dso->has_build_id = true; 1284 1376 1285 1377 return 0; 1286 - } 1287 - 1288 - bool __dsos__read_build_ids(struct list_head *head, bool with_hits) 1289 - { 1290 - bool have_build_id = false; 1291 - struct dso *pos; 1292 - struct nscookie nsc; 1293 - 1294 - list_for_each_entry(pos, head, node) { 1295 - if (with_hits && !pos->hit && !dso__is_vdso(pos)) 1296 - continue; 1297 - if (pos->has_build_id) { 1298 - have_build_id = true; 1299 - continue; 1300 - } 1301 - nsinfo__mountns_enter(pos->nsinfo, &nsc); 1302 - if (filename__read_build_id(pos->long_name, pos->build_id, 1303 - sizeof(pos->build_id)) > 0) { 1304 - have_build_id = true; 1305 - pos->has_build_id = true; 1306 - } 1307 - nsinfo__mountns_exit(&nsc); 1308 - } 1309 - 1310 - return have_build_id; 1311 - } 1312 - 1313 - void __dsos__add(struct dsos *dsos, struct dso *dso) 1314 - { 1315 - list_add_tail(&dso->node, &dsos->head); 1316 - __dso__findlink_by_longname(&dsos->root, dso, NULL); 1317 - /* 1318 - * It is now in the linked list, grab a reference, then garbage collect 1319 - * this when needing memory, by looking at LRU dso instances in the 1320 - * list with atomic_read(&dso->refcnt) == 1, i.e. no references 1321 - * anywhere besides the one for the list, do, under a lock for the 1322 - * list: remove it from the list, then a dso__put(), that probably will 1323 - * be the last and will then call dso__delete(), end of life. 1324 - * 1325 - * That, or at the end of the 'struct machine' lifetime, when all 1326 - * 'struct dso' instances will be removed from the list, in 1327 - * dsos__exit(), if they have no other reference from some other data 1328 - * structure. 1329 - * 1330 - * E.g.: after processing a 'perf.data' file and storing references 1331 - * to objects instantiated while processing events, we will have 1332 - * references to the 'thread', 'map', 'dso' structs all from 'struct 1333 - * hist_entry' instances, but we may not need anything not referenced, 1334 - * so we might as well call machines__exit()/machines__delete() and 1335 - * garbage collect it. 1336 - */ 1337 - dso__get(dso); 1338 - } 1339 - 1340 - void dsos__add(struct dsos *dsos, struct dso *dso) 1341 - { 1342 - down_write(&dsos->lock); 1343 - __dsos__add(dsos, dso); 1344 - up_write(&dsos->lock); 1345 - } 1346 - 1347 - struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 1348 - { 1349 - struct dso *pos; 1350 - 1351 - if (cmp_short) { 1352 - list_for_each_entry(pos, &dsos->head, node) 1353 - if (strcmp(pos->short_name, name) == 0) 1354 - return pos; 1355 - return NULL; 1356 - } 1357 - return __dso__find_by_longname(&dsos->root, name); 1358 - } 1359 - 1360 - struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 1361 - { 1362 - struct dso *dso; 1363 - down_read(&dsos->lock); 1364 - dso = __dsos__find(dsos, name, cmp_short); 1365 - up_read(&dsos->lock); 1366 - return dso; 1367 - } 1368 - 1369 - struct dso *__dsos__addnew(struct dsos *dsos, const char *name) 1370 - { 1371 - struct dso *dso = dso__new(name); 1372 - 1373 - if (dso != NULL) { 1374 - __dsos__add(dsos, dso); 1375 - dso__set_basename(dso); 1376 - /* Put dso here because __dsos_add already got it */ 1377 - dso__put(dso); 1378 - } 1379 - return dso; 1380 - } 1381 - 1382 - struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 1383 - { 1384 - struct dso *dso = __dsos__find(dsos, name, false); 1385 - 1386 - return dso ? dso : __dsos__addnew(dsos, name); 1387 - } 1388 - 1389 - struct dso *dsos__findnew(struct dsos *dsos, const char *name) 1390 - { 1391 - struct dso *dso; 1392 - down_write(&dsos->lock); 1393 - dso = dso__get(__dsos__findnew(dsos, name)); 1394 - up_write(&dsos->lock); 1395 - return dso; 1396 - } 1397 - 1398 - size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1399 - bool (skip)(struct dso *dso, int parm), int parm) 1400 - { 1401 - struct dso *pos; 1402 - size_t ret = 0; 1403 - 1404 - list_for_each_entry(pos, head, node) { 1405 - if (skip && skip(pos, parm)) 1406 - continue; 1407 - ret += dso__fprintf_buildid(pos, fp); 1408 - ret += fprintf(fp, " %s\n", pos->long_name); 1409 - } 1410 - return ret; 1411 - } 1412 - 1413 - size_t __dsos__fprintf(struct list_head *head, FILE *fp) 1414 - { 1415 - struct dso *pos; 1416 - size_t ret = 0; 1417 - 1418 - list_for_each_entry(pos, head, node) { 1419 - ret += dso__fprintf(pos, fp); 1420 - } 1421 - 1422 - return ret; 1423 1378 } 1424 1379 1425 1380 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
+1 -24
tools/perf/util/dso.h
··· 2 2 #ifndef __PERF_DSO 3 3 #define __PERF_DSO 4 4 5 + #include <pthread.h> 5 6 #include <linux/refcount.h> 6 7 #include <linux/types.h> 7 8 #include <linux/rbtree.h> 8 9 #include <sys/types.h> 9 10 #include <stdbool.h> 10 11 #include <stdio.h> 11 - #include "rwsem.h" 12 12 #include <linux/bitops.h> 13 13 #include "build-id.h" 14 14 ··· 127 127 u64 offset; 128 128 u64 size; 129 129 char data[0]; 130 - }; 131 - 132 - /* 133 - * DSOs are put into both a list for fast iteration and rbtree for fast 134 - * long name lookup. 135 - */ 136 - struct dsos { 137 - struct list_head head; 138 - struct rb_root root; /* rbtree root sorted by long name */ 139 - struct rw_semaphore lock; 140 130 }; 141 131 142 132 struct auxtrace_cache; ··· 337 347 struct dso *machine__findnew_kernel(struct machine *machine, const char *name, 338 348 const char *short_name, int dso_type); 339 349 340 - void __dsos__add(struct dsos *dsos, struct dso *dso); 341 - void dsos__add(struct dsos *dsos, struct dso *dso); 342 - struct dso *__dsos__addnew(struct dsos *dsos, const char *name); 343 - struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short); 344 - struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short); 345 - struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 346 - struct dso *dsos__findnew(struct dsos *dsos, const char *name); 347 - bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 348 - 349 350 void dso__reset_find_symbol_cache(struct dso *dso); 350 - 351 - size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 352 - bool (skip)(struct dso *dso, int parm), int parm); 353 - size_t __dsos__fprintf(struct list_head *head, FILE *fp); 354 351 355 352 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 356 353 size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp);
+232
tools/perf/util/dsos.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include "debug.h" 3 + #include "dsos.h" 4 + #include "dso.h" 5 + #include "vdso.h" 6 + #include "namespaces.h" 7 + #include <libgen.h> 8 + #include <stdlib.h> 9 + #include <string.h> 10 + #include <symbol.h> // filename__read_build_id 11 + 12 + bool __dsos__read_build_ids(struct list_head *head, bool with_hits) 13 + { 14 + bool have_build_id = false; 15 + struct dso *pos; 16 + struct nscookie nsc; 17 + 18 + list_for_each_entry(pos, head, node) { 19 + if (with_hits && !pos->hit && !dso__is_vdso(pos)) 20 + continue; 21 + if (pos->has_build_id) { 22 + have_build_id = true; 23 + continue; 24 + } 25 + nsinfo__mountns_enter(pos->nsinfo, &nsc); 26 + if (filename__read_build_id(pos->long_name, pos->build_id, 27 + sizeof(pos->build_id)) > 0) { 28 + have_build_id = true; 29 + pos->has_build_id = true; 30 + } 31 + nsinfo__mountns_exit(&nsc); 32 + } 33 + 34 + return have_build_id; 35 + } 36 + 37 + /* 38 + * Find a matching entry and/or link current entry to RB tree. 39 + * Either one of the dso or name parameter must be non-NULL or the 40 + * function will not work. 41 + */ 42 + struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name) 43 + { 44 + struct rb_node **p = &root->rb_node; 45 + struct rb_node *parent = NULL; 46 + 47 + if (!name) 48 + name = dso->long_name; 49 + /* 50 + * Find node with the matching name 51 + */ 52 + while (*p) { 53 + struct dso *this = rb_entry(*p, struct dso, rb_node); 54 + int rc = strcmp(name, this->long_name); 55 + 56 + parent = *p; 57 + if (rc == 0) { 58 + /* 59 + * In case the new DSO is a duplicate of an existing 60 + * one, print a one-time warning & put the new entry 61 + * at the end of the list of duplicates. 62 + */ 63 + if (!dso || (dso == this)) 64 + return this; /* Find matching dso */ 65 + /* 66 + * The core kernel DSOs may have duplicated long name. 67 + * In this case, the short name should be different. 68 + * Comparing the short names to differentiate the DSOs. 69 + */ 70 + rc = strcmp(dso->short_name, this->short_name); 71 + if (rc == 0) { 72 + pr_err("Duplicated dso name: %s\n", name); 73 + return NULL; 74 + } 75 + } 76 + if (rc < 0) 77 + p = &parent->rb_left; 78 + else 79 + p = &parent->rb_right; 80 + } 81 + if (dso) { 82 + /* Add new node and rebalance tree */ 83 + rb_link_node(&dso->rb_node, parent, p); 84 + rb_insert_color(&dso->rb_node, root); 85 + dso->root = root; 86 + } 87 + return NULL; 88 + } 89 + 90 + void __dsos__add(struct dsos *dsos, struct dso *dso) 91 + { 92 + list_add_tail(&dso->node, &dsos->head); 93 + __dsos__findnew_link_by_longname(&dsos->root, dso, NULL); 94 + /* 95 + * It is now in the linked list, grab a reference, then garbage collect 96 + * this when needing memory, by looking at LRU dso instances in the 97 + * list with atomic_read(&dso->refcnt) == 1, i.e. no references 98 + * anywhere besides the one for the list, do, under a lock for the 99 + * list: remove it from the list, then a dso__put(), that probably will 100 + * be the last and will then call dso__delete(), end of life. 101 + * 102 + * That, or at the end of the 'struct machine' lifetime, when all 103 + * 'struct dso' instances will be removed from the list, in 104 + * dsos__exit(), if they have no other reference from some other data 105 + * structure. 106 + * 107 + * E.g.: after processing a 'perf.data' file and storing references 108 + * to objects instantiated while processing events, we will have 109 + * references to the 'thread', 'map', 'dso' structs all from 'struct 110 + * hist_entry' instances, but we may not need anything not referenced, 111 + * so we might as well call machines__exit()/machines__delete() and 112 + * garbage collect it. 113 + */ 114 + dso__get(dso); 115 + } 116 + 117 + void dsos__add(struct dsos *dsos, struct dso *dso) 118 + { 119 + down_write(&dsos->lock); 120 + __dsos__add(dsos, dso); 121 + up_write(&dsos->lock); 122 + } 123 + 124 + struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 125 + { 126 + struct dso *pos; 127 + 128 + if (cmp_short) { 129 + list_for_each_entry(pos, &dsos->head, node) 130 + if (strcmp(pos->short_name, name) == 0) 131 + return pos; 132 + return NULL; 133 + } 134 + return __dsos__findnew_by_longname(&dsos->root, name); 135 + } 136 + 137 + struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short) 138 + { 139 + struct dso *dso; 140 + down_read(&dsos->lock); 141 + dso = __dsos__find(dsos, name, cmp_short); 142 + up_read(&dsos->lock); 143 + return dso; 144 + } 145 + 146 + static void dso__set_basename(struct dso *dso) 147 + { 148 + char *base, *lname; 149 + int tid; 150 + 151 + if (sscanf(dso->long_name, "/tmp/perf-%d.map", &tid) == 1) { 152 + if (asprintf(&base, "[JIT] tid %d", tid) < 0) 153 + return; 154 + } else { 155 + /* 156 + * basename() may modify path buffer, so we must pass 157 + * a copy. 158 + */ 159 + lname = strdup(dso->long_name); 160 + if (!lname) 161 + return; 162 + 163 + /* 164 + * basename() may return a pointer to internal 165 + * storage which is reused in subsequent calls 166 + * so copy the result. 167 + */ 168 + base = strdup(basename(lname)); 169 + 170 + free(lname); 171 + 172 + if (!base) 173 + return; 174 + } 175 + dso__set_short_name(dso, base, true); 176 + } 177 + 178 + struct dso *__dsos__addnew(struct dsos *dsos, const char *name) 179 + { 180 + struct dso *dso = dso__new(name); 181 + 182 + if (dso != NULL) { 183 + __dsos__add(dsos, dso); 184 + dso__set_basename(dso); 185 + /* Put dso here because __dsos_add already got it */ 186 + dso__put(dso); 187 + } 188 + return dso; 189 + } 190 + 191 + struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 192 + { 193 + struct dso *dso = __dsos__find(dsos, name, false); 194 + 195 + return dso ? dso : __dsos__addnew(dsos, name); 196 + } 197 + 198 + struct dso *dsos__findnew(struct dsos *dsos, const char *name) 199 + { 200 + struct dso *dso; 201 + down_write(&dsos->lock); 202 + dso = dso__get(__dsos__findnew(dsos, name)); 203 + up_write(&dsos->lock); 204 + return dso; 205 + } 206 + 207 + size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 208 + bool (skip)(struct dso *dso, int parm), int parm) 209 + { 210 + struct dso *pos; 211 + size_t ret = 0; 212 + 213 + list_for_each_entry(pos, head, node) { 214 + if (skip && skip(pos, parm)) 215 + continue; 216 + ret += dso__fprintf_buildid(pos, fp); 217 + ret += fprintf(fp, " %s\n", pos->long_name); 218 + } 219 + return ret; 220 + } 221 + 222 + size_t __dsos__fprintf(struct list_head *head, FILE *fp) 223 + { 224 + struct dso *pos; 225 + size_t ret = 0; 226 + 227 + list_for_each_entry(pos, head, node) { 228 + ret += dso__fprintf(pos, fp); 229 + } 230 + 231 + return ret; 232 + }
+44
tools/perf/util/dsos.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __PERF_DSOS 3 + #define __PERF_DSOS 4 + 5 + #include <stdbool.h> 6 + #include <stdio.h> 7 + #include <linux/list.h> 8 + #include <linux/rbtree.h> 9 + #include "rwsem.h" 10 + 11 + struct dso; 12 + 13 + /* 14 + * DSOs are put into both a list for fast iteration and rbtree for fast 15 + * long name lookup. 16 + */ 17 + struct dsos { 18 + struct list_head head; 19 + struct rb_root root; /* rbtree root sorted by long name */ 20 + struct rw_semaphore lock; 21 + }; 22 + 23 + void __dsos__add(struct dsos *dsos, struct dso *dso); 24 + void dsos__add(struct dsos *dsos, struct dso *dso); 25 + struct dso *__dsos__addnew(struct dsos *dsos, const char *name); 26 + struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short); 27 + struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short); 28 + struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 29 + struct dso *dsos__findnew(struct dsos *dsos, const char *name); 30 + 31 + struct dso *__dsos__findnew_link_by_longname(struct rb_root *root, struct dso *dso, const char *name); 32 + 33 + static inline struct dso *__dsos__findnew_by_longname(struct rb_root *root, const char *name) 34 + { 35 + return __dsos__findnew_link_by_longname(root, NULL, name); 36 + } 37 + 38 + bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 39 + 40 + size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 41 + bool (skip)(struct dso *dso, int parm), int parm); 42 + size_t __dsos__fprintf(struct list_head *head, FILE *fp); 43 + 44 + #endif /* __PERF_DSOS */
+2
tools/perf/util/event.c
··· 11 11 #include <api/fs/fs.h> 12 12 #include <linux/perf_event.h> 13 13 #include <linux/zalloc.h> 14 + #include "dso.h" 14 15 #include "event.h" 15 16 #include "debug.h" 16 17 #include "hist.h" ··· 30 29 #include "stat.h" 31 30 #include "session.h" 32 31 #include "bpf-event.h" 32 + #include "tool.h" 33 33 #include "../perf.h" 34 34 35 35 #define DEFAULT_PROC_MAP_PARSE_TIMEOUT 500
+1
tools/perf/util/header.c
··· 22 22 #include <bpf/libbpf.h> 23 23 #include <perf/cpumap.h> 24 24 25 + #include "dso.h" 25 26 #include "evlist.h" 26 27 #include "evsel.h" 27 28 #include "header.h"
+1
tools/perf/util/hist.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "callchain.h" 3 3 #include "debug.h" 4 + #include "dso.h" 4 5 #include "build-id.h" 5 6 #include "hist.h" 6 7 #include "map.h"
+1
tools/perf/util/intel-bts.c
··· 22 22 #include "map.h" 23 23 #include "symbol.h" 24 24 #include "session.h" 25 + #include "tool.h" 25 26 #include "thread.h" 26 27 #include "thread-stack.h" 27 28 #include "debug.h"
+1
tools/perf/util/jitdump.c
··· 14 14 #include <sys/mman.h> 15 15 #include <linux/stringify.h> 16 16 17 + #include "build-id.h" 17 18 #include "util.h" 18 19 #include "event.h" 19 20 #include "debug.h"
+1
tools/perf/util/machine.c
··· 5 5 #include <regex.h> 6 6 #include "callchain.h" 7 7 #include "debug.h" 8 + #include "dso.h" 8 9 #include "event.h" 9 10 #include "evsel.h" 10 11 #include "hist.h"
+2 -1
tools/perf/util/machine.h
··· 5 5 #include <sys/types.h> 6 6 #include <linux/rbtree.h> 7 7 #include "map_groups.h" 8 - #include "dso.h" 8 + #include "dsos.h" 9 9 #include "event.h" 10 10 #include "rwsem.h" 11 11 12 12 struct addr_location; 13 13 struct branch_stack; 14 + struct dso; 14 15 struct evsel; 15 16 struct perf_sample; 16 17 struct symbol;
+1
tools/perf/util/map.c
··· 8 8 #include <stdio.h> 9 9 #include <unistd.h> 10 10 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 11 + #include "dso.h" 11 12 #include "map.h" 12 13 #include "thread.h" 13 14 #include "vdso.h"
+1
tools/perf/util/parse-events.c
··· 10 10 #include <fcntl.h> 11 11 #include <sys/param.h> 12 12 #include "term.h" 13 + #include "build-id.h" 13 14 #include "evlist.h" 14 15 #include "evsel.h" 15 16 #include <subcmd/parse-options.h>
+2
tools/perf/util/probe-event.c
··· 19 19 #include <limits.h> 20 20 #include <elf.h> 21 21 22 + #include "build-id.h" 22 23 #include "event.h" 23 24 #include "namespaces.h" 24 25 #include "strlist.h" 25 26 #include "strfilter.h" 26 27 #include "debug.h" 28 + #include "dso.h" 27 29 #include "cache.h" 28 30 #include "color.h" 29 31 #include "map.h"
+1
tools/perf/util/s390-cpumsf.c
··· 157 157 #include "evlist.h" 158 158 #include "machine.h" 159 159 #include "session.h" 160 + #include "tool.h" 160 161 #include "thread.h" 161 162 #include "debug.h" 162 163 #include "auxtrace.h"
+1
tools/perf/util/scripting-engines/trace-event-perl.c
··· 35 35 #include <perl.h> 36 36 37 37 #include "../callchain.h" 38 + #include "../dso.h" 38 39 #include "../machine.h" 39 40 #include "../map.h" 40 41 #include "../symbol.h"
+2
tools/perf/util/scripting-engines/trace-event-python.c
··· 31 31 #include <linux/compiler.h> 32 32 #include <linux/time64.h> 33 33 34 + #include "../build-id.h" 34 35 #include "../counts.h" 35 36 #include "../debug.h" 37 + #include "../dso.h" 36 38 #include "../callchain.h" 37 39 #include "../evsel.h" 38 40 #include "../util.h"
+1
tools/perf/util/sort.c
··· 5 5 #include <linux/mman.h> 6 6 #include <linux/time64.h> 7 7 #include "debug.h" 8 + #include "dso.h" 8 9 #include "sort.h" 9 10 #include "hist.h" 10 11 #include "cacheline.h"
+1
tools/perf/util/thread.c
··· 5 5 #include <string.h> 6 6 #include <linux/kernel.h> 7 7 #include <linux/zalloc.h> 8 + #include "dso.h" 8 9 #include "session.h" 9 10 #include "thread.h" 10 11 #include "thread-stack.h"
+1
tools/perf/util/unwind-libdw.c
··· 5 5 #include <inttypes.h> 6 6 #include <errno.h> 7 7 #include "debug.h" 8 + #include "dso.h" 8 9 #include "unwind.h" 9 10 #include "unwind-libdw.h" 10 11 #include "machine.h"
+1
tools/perf/util/unwind-libunwind.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "unwind.h" 3 + #include "dso.h" 3 4 #include "map.h" 4 5 #include "thread.h" 5 6 #include "session.h"
+1
tools/perf/util/vdso.c
··· 10 10 #include <linux/kernel.h> 11 11 12 12 #include "vdso.h" 13 + #include "dso.h" 13 14 #include "util.h" 14 15 #include "map.h" 15 16 #include "symbol.h"