perf dsos: Introduce dsos__for_each_dso()
authorIan Rogers <irogers@google.com>
Wed, 10 Apr 2024 06:42:05 +0000 (23:42 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 12 Apr 2024 15:04:13 +0000 (12:04 -0300)
To better abstract the dsos internals, introduce dsos__for_each_dso that
does a callback on each dso.

This also means the read lock can be correctly held.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Anne Macedo <retpolanne@posteo.net>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Ben Gainey <ben.gainey@arm.com>
Cc: Changbin Du <changbin.du@huawei.com>
Cc: Chengen Du <chengen.du@canonical.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Li Dong <lidong@vivo.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Markus Elfring <Markus.Elfring@web.de>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paran Lee <p4ranlee@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Song Liu <song@kernel.org>
Cc: Sun Haiyong <sunhaiyong@loongson.cn>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Yanteng Si <siyanteng@loongson.cn>
Cc: Yicong Yang <yangyicong@hisilicon.com>
Cc: zhaimingbing <zhaimingbing@cmss.chinamobile.com>
Link: https://lore.kernel.org/r/20240410064214.2755936-4-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-inject.c
tools/perf/util/build-id.c
tools/perf/util/dsos.c
tools/perf/util/dsos.h
tools/perf/util/machine.c

index ef73317e6ae7e797766b59e3d08fd81f0f96b9f5..ce5e28eaad90413d8878996250cb72a9454ad5f0 100644 (file)
@@ -1187,23 +1187,28 @@ static int synthesize_build_id(struct perf_inject *inject, struct dso *dso, pid_
                                               process_build_id, machine);
 }
 
+static int guest_session__add_build_ids_cb(struct dso *dso, void *data)
+{
+       struct guest_session *gs = data;
+       struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session);
+
+       if (!dso->has_build_id)
+               return 0;
+
+       return synthesize_build_id(inject, dso, gs->machine_pid);
+
+}
+
 static int guest_session__add_build_ids(struct guest_session *gs)
 {
        struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session);
-       struct machine *machine = &gs->session->machines.host;
-       struct dso *dso;
-       int ret;
 
        /* Build IDs will be put in the Build ID feature section */
        perf_header__set_feat(&inject->session->header, HEADER_BUILD_ID);
 
-       dsos__for_each_with_build_id(dso, &machine->dsos.head) {
-               ret = synthesize_build_id(inject, dso, gs->machine_pid);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
+       return dsos__for_each_dso(&gs->session->machines.host.dsos,
+                                 guest_session__add_build_ids_cb,
+                                 gs);
 }
 
 static int guest_session__ksymbol_event(struct perf_tool *tool,
index a617b1917e6bd6af8de8e187f55ed083569316df..a6d3c253f19fa14c9f2e92c15807aa68fd0ac034 100644 (file)
@@ -327,48 +327,56 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
        return write_padded(fd, name, name_len + 1, len);
 }
 
-static int machine__write_buildid_table(struct machine *machine,
-                                       struct feat_fd *fd)
+struct machine__write_buildid_table_cb_args {
+       struct machine *machine;
+       struct feat_fd *fd;
+       u16 kmisc, umisc;
+};
+
+static int machine__write_buildid_table_cb(struct dso *dso, void *data)
 {
-       int err = 0;
-       struct dso *pos;
-       u16 kmisc = PERF_RECORD_MISC_KERNEL,
-           umisc = PERF_RECORD_MISC_USER;
+       struct machine__write_buildid_table_cb_args *args = data;
+       const char *name;
+       size_t name_len;
+       bool in_kernel = false;
 
-       if (!machine__is_host(machine)) {
-               kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
-               umisc = PERF_RECORD_MISC_GUEST_USER;
-       }
+       if (!dso->has_build_id)
+               return 0;
 
-       dsos__for_each_with_build_id(pos, &machine->dsos.head) {
-               const char *name;
-               size_t name_len;
-               bool in_kernel = false;
+       if (!dso->hit && !dso__is_vdso(dso))
+               return 0;
 
-               if (!pos->hit && !dso__is_vdso(pos))
-                       continue;
+       if (dso__is_vdso(dso)) {
+               name = dso->short_name;
+               name_len = dso->short_name_len;
+       } else if (dso__is_kcore(dso)) {
+               name = args->machine->mmap_name;
+               name_len = strlen(name);
+       } else {
+               name = dso->long_name;
+               name_len = dso->long_name_len;
+       }
 
-               if (dso__is_vdso(pos)) {
-                       name = pos->short_name;
-                       name_len = pos->short_name_len;
-               } else if (dso__is_kcore(pos)) {
-                       name = machine->mmap_name;
-                       name_len = strlen(name);
-               } else {
-                       name = pos->long_name;
-                       name_len = pos->long_name_len;
-               }
+       in_kernel = dso->kernel || is_kernel_module(name, PERF_RECORD_MISC_CPUMODE_UNKNOWN);
+       return write_buildid(name, name_len, &dso->bid, args->machine->pid,
+                            in_kernel ? args->kmisc : args->umisc, args->fd);
+}
 
-               in_kernel = pos->kernel ||
-                               is_kernel_module(name,
-                                       PERF_RECORD_MISC_CPUMODE_UNKNOWN);
-               err = write_buildid(name, name_len, &pos->bid, machine->pid,
-                                   in_kernel ? kmisc : umisc, fd);
-               if (err)
-                       break;
+static int machine__write_buildid_table(struct machine *machine, struct feat_fd *fd)
+{
+       struct machine__write_buildid_table_cb_args args = {
+               .machine = machine,
+               .fd = fd,
+               .kmisc = PERF_RECORD_MISC_KERNEL,
+               .umisc = PERF_RECORD_MISC_USER,
+       };
+
+       if (!machine__is_host(machine)) {
+               args.kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
+               args.umisc = PERF_RECORD_MISC_GUEST_USER;
        }
 
-       return err;
+       return dsos__for_each_dso(&machine->dsos, machine__write_buildid_table_cb, &args);
 }
 
 int perf_session__write_buildid_table(struct perf_session *session,
index d269e09005a726b6134252cacdf69ec6a3066ae1..d43f64939b121b4bc9826bb566daf891375178a6 100644 (file)
@@ -433,3 +433,19 @@ struct dso *dsos__find_kernel_dso(struct dsos *dsos)
        up_read(&dsos->lock);
        return res;
 }
+
+int dsos__for_each_dso(struct dsos *dsos, int (*cb)(struct dso *dso, void *data), void *data)
+{
+       struct dso *dso;
+
+       down_read(&dsos->lock);
+       list_for_each_entry(dso, &dsos->head, node) {
+               int err;
+
+               err = cb(dso, data);
+               if (err)
+                       return err;
+       }
+       up_read(&dsos->lock);
+       return 0;
+}
index a7c7f723c5fff0115e54522c05eebf79c9547000..317a263f0e37f8136e1c98095e09d96881ee11fc 100644 (file)
@@ -23,12 +23,6 @@ struct dsos {
        struct rw_semaphore lock;
 };
 
-#define dsos__for_each_with_build_id(pos, head)        \
-       list_for_each_entry(pos, head, node)    \
-               if (!pos->has_build_id)         \
-                       continue;               \
-               else
-
 void dsos__init(struct dsos *dsos);
 void dsos__exit(struct dsos *dsos);
 
@@ -55,4 +49,6 @@ struct dso *dsos__findnew_module_dso(struct dsos *dsos, struct machine *machine,
 
 struct dso *dsos__find_kernel_dso(struct dsos *dsos);
 
+int dsos__for_each_dso(struct dsos *dsos, int (*cb)(struct dso *dso, void *data), void *data);
+
 #endif /* __PERF_DSOS */
index e2c800a1449b0a95a3387269d2d479b679de9bc9..e3deef38405c373a746f02cd4dd70835b1788fd6 100644 (file)
@@ -1562,16 +1562,14 @@ out_put:
        return ret;
 }
 
-static bool machine__uses_kcore(struct machine *machine)
+static int machine__uses_kcore_cb(struct dso *dso, void *data __maybe_unused)
 {
-       struct dso *dso;
-
-       list_for_each_entry(dso, &machine->dsos.head, node) {
-               if (dso__is_kcore(dso))
-                       return true;
-       }
+       return dso__is_kcore(dso) ? 1 : 0;
+}
 
-       return false;
+static bool machine__uses_kcore(struct machine *machine)
+{
+       return dsos__for_each_dso(&machine->dsos, machine__uses_kcore_cb, NULL) != 0 ? true : false;
 }
 
 static bool perf_event__is_extra_kernel_mmap(struct machine *machine,
@@ -3137,16 +3135,28 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch
        return sym->name;
 }
 
+struct machine__for_each_dso_cb_args {
+       struct machine *machine;
+       machine__dso_t fn;
+       void *priv;
+};
+
+static int machine__for_each_dso_cb(struct dso *dso, void *data)
+{
+       struct machine__for_each_dso_cb_args *args = data;
+
+       return args->fn(dso, args->machine, args->priv);
+}
+
 int machine__for_each_dso(struct machine *machine, machine__dso_t fn, void *priv)
 {
-       struct dso *pos;
-       int err = 0;
+       struct machine__for_each_dso_cb_args args = {
+               .machine = machine,
+               .fn = fn,
+               .priv = priv,
+       };
 
-       list_for_each_entry(pos, &machine->dsos.head, node) {
-               if (fn(pos, machine, priv))
-                       err = -1;
-       }
-       return err;
+       return dsos__for_each_dso(&machine->dsos, machine__for_each_dso_cb, &args);
 }
 
 int machine__for_each_kernel_map(struct machine *machine, machine__map_t fn, void *priv)