mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
perf dsos: Tidy reference counting and locking
Move more functionality into dsos.c generally from machine.c, renaming functions to match their new usage. The find function is made to always "get" before returning a dso. Reduce the scope of locks in vdso to match the locking paradigm. 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-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
83acca9f90
commit
f649ed80f3
5 changed files with 97 additions and 99 deletions
|
@ -181,7 +181,7 @@ struct dso *__dsos__findnew_link_by_longname_id(struct rb_root *root, struct dso
|
|||
* at the end of the list of duplicates.
|
||||
*/
|
||||
if (!dso || (dso == this))
|
||||
return this; /* Find matching dso */
|
||||
return dso__get(this); /* Find matching dso */
|
||||
/*
|
||||
* The core kernel DSOs may have duplicated long name.
|
||||
* In this case, the short name should be different.
|
||||
|
@ -253,15 +253,20 @@ static struct dso *__dsos__find_id(struct dsos *dsos, const char *name, struct d
|
|||
if (cmp_short) {
|
||||
list_for_each_entry(pos, &dsos->head, node)
|
||||
if (__dso__cmp_short_name(name, id, pos) == 0)
|
||||
return pos;
|
||||
return dso__get(pos);
|
||||
return NULL;
|
||||
}
|
||||
return __dsos__findnew_by_longname_id(&dsos->root, name, id);
|
||||
}
|
||||
|
||||
struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
|
||||
struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
|
||||
{
|
||||
return __dsos__find_id(dsos, name, NULL, cmp_short);
|
||||
struct dso *res;
|
||||
|
||||
down_read(&dsos->lock);
|
||||
res = __dsos__find_id(dsos, name, NULL, cmp_short);
|
||||
up_read(&dsos->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void dso__set_basename(struct dso *dso)
|
||||
|
@ -303,8 +308,6 @@ static struct dso *__dsos__addnew_id(struct dsos *dsos, const char *name, struct
|
|||
if (dso != NULL) {
|
||||
__dsos__add(dsos, dso);
|
||||
dso__set_basename(dso);
|
||||
/* Put dso here because __dsos_add already got it */
|
||||
dso__put(dso);
|
||||
}
|
||||
return dso;
|
||||
}
|
||||
|
@ -328,7 +331,7 @@ struct dso *dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id
|
|||
{
|
||||
struct dso *dso;
|
||||
down_write(&dsos->lock);
|
||||
dso = dso__get(__dsos__findnew_id(dsos, name, id));
|
||||
dso = __dsos__findnew_id(dsos, name, id);
|
||||
up_write(&dsos->lock);
|
||||
return dso;
|
||||
}
|
||||
|
@ -374,3 +377,59 @@ int __dsos__hit_all(struct dsos *dsos)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dso *dsos__findnew_module_dso(struct dsos *dsos,
|
||||
struct machine *machine,
|
||||
struct kmod_path *m,
|
||||
const char *filename)
|
||||
{
|
||||
struct dso *dso;
|
||||
|
||||
down_write(&dsos->lock);
|
||||
|
||||
dso = __dsos__find_id(dsos, m->name, NULL, /*cmp_short=*/true);
|
||||
if (!dso) {
|
||||
dso = __dsos__addnew(dsos, m->name);
|
||||
if (dso == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
dso__set_module_info(dso, m, machine);
|
||||
dso__set_long_name(dso, strdup(filename), true);
|
||||
dso->kernel = DSO_SPACE__KERNEL;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
up_write(&dsos->lock);
|
||||
return dso;
|
||||
}
|
||||
|
||||
struct dso *dsos__find_kernel_dso(struct dsos *dsos)
|
||||
{
|
||||
struct dso *dso, *res = NULL;
|
||||
|
||||
down_read(&dsos->lock);
|
||||
list_for_each_entry(dso, &dsos->head, node) {
|
||||
/*
|
||||
* The cpumode passed to is_kernel_module is not the cpumode of
|
||||
* *this* event. If we insist on passing correct cpumode to
|
||||
* is_kernel_module, we should record the cpumode when we adding
|
||||
* this dso to the linked list.
|
||||
*
|
||||
* However we don't really need passing correct cpumode. We
|
||||
* know the correct cpumode must be kernel mode (if not, we
|
||||
* should not link it onto kernel_dsos list).
|
||||
*
|
||||
* Therefore, we pass PERF_RECORD_MISC_CPUMODE_UNKNOWN.
|
||||
* is_kernel_module() treats it as a kernel cpumode.
|
||||
*/
|
||||
if (!dso->kernel ||
|
||||
is_kernel_module(dso->long_name,
|
||||
PERF_RECORD_MISC_CPUMODE_UNKNOWN))
|
||||
continue;
|
||||
|
||||
res = dso__get(dso);
|
||||
break;
|
||||
}
|
||||
up_read(&dsos->lock);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
struct dso;
|
||||
struct dso_id;
|
||||
struct kmod_path;
|
||||
struct machine;
|
||||
|
||||
/*
|
||||
* DSOs are put into both a list for fast iteration and rbtree for fast
|
||||
|
@ -33,7 +35,7 @@ void dsos__exit(struct dsos *dsos);
|
|||
void __dsos__add(struct dsos *dsos, struct dso *dso);
|
||||
void dsos__add(struct dsos *dsos, struct dso *dso);
|
||||
struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
|
||||
struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
|
||||
struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
|
||||
|
||||
struct dso *dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id *id);
|
||||
|
||||
|
@ -48,4 +50,9 @@ size_t __dsos__fprintf(struct dsos *dsos, FILE *fp);
|
|||
|
||||
int __dsos__hit_all(struct dsos *dsos);
|
||||
|
||||
struct dso *dsos__findnew_module_dso(struct dsos *dsos, struct machine *machine,
|
||||
struct kmod_path *m, const char *filename);
|
||||
|
||||
struct dso *dsos__find_kernel_dso(struct dsos *dsos);
|
||||
|
||||
#endif /* __PERF_DSOS */
|
||||
|
|
|
@ -646,31 +646,6 @@ int machine__process_lost_samples_event(struct machine *machine __maybe_unused,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dso *machine__findnew_module_dso(struct machine *machine,
|
||||
struct kmod_path *m,
|
||||
const char *filename)
|
||||
{
|
||||
struct dso *dso;
|
||||
|
||||
down_write(&machine->dsos.lock);
|
||||
|
||||
dso = __dsos__find(&machine->dsos, m->name, true);
|
||||
if (!dso) {
|
||||
dso = __dsos__addnew(&machine->dsos, m->name);
|
||||
if (dso == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
dso__set_module_info(dso, m, machine);
|
||||
dso__set_long_name(dso, strdup(filename), true);
|
||||
dso->kernel = DSO_SPACE__KERNEL;
|
||||
}
|
||||
|
||||
dso__get(dso);
|
||||
out_unlock:
|
||||
up_write(&machine->dsos.lock);
|
||||
return dso;
|
||||
}
|
||||
|
||||
int machine__process_aux_event(struct machine *machine __maybe_unused,
|
||||
union perf_event *event)
|
||||
{
|
||||
|
@ -854,7 +829,7 @@ static struct map *machine__addnew_module_map(struct machine *machine, u64 start
|
|||
if (kmod_path__parse_name(&m, filename))
|
||||
return NULL;
|
||||
|
||||
dso = machine__findnew_module_dso(machine, &m, filename);
|
||||
dso = dsos__findnew_module_dso(&machine->dsos, machine, &m, filename);
|
||||
if (dso == NULL)
|
||||
goto out;
|
||||
|
||||
|
@ -1663,40 +1638,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
|
|||
* Should be there already, from the build-id table in
|
||||
* the header.
|
||||
*/
|
||||
struct dso *kernel = NULL;
|
||||
struct dso *dso;
|
||||
|
||||
down_read(&machine->dsos.lock);
|
||||
|
||||
list_for_each_entry(dso, &machine->dsos.head, node) {
|
||||
|
||||
/*
|
||||
* The cpumode passed to is_kernel_module is not the
|
||||
* cpumode of *this* event. If we insist on passing
|
||||
* correct cpumode to is_kernel_module, we should
|
||||
* record the cpumode when we adding this dso to the
|
||||
* linked list.
|
||||
*
|
||||
* However we don't really need passing correct
|
||||
* cpumode. We know the correct cpumode must be kernel
|
||||
* mode (if not, we should not link it onto kernel_dsos
|
||||
* list).
|
||||
*
|
||||
* Therefore, we pass PERF_RECORD_MISC_CPUMODE_UNKNOWN.
|
||||
* is_kernel_module() treats it as a kernel cpumode.
|
||||
*/
|
||||
|
||||
if (!dso->kernel ||
|
||||
is_kernel_module(dso->long_name,
|
||||
PERF_RECORD_MISC_CPUMODE_UNKNOWN))
|
||||
continue;
|
||||
|
||||
|
||||
kernel = dso__get(dso);
|
||||
break;
|
||||
}
|
||||
|
||||
up_read(&machine->dsos.lock);
|
||||
struct dso *kernel = dsos__find_kernel_dso(&machine->dsos);
|
||||
|
||||
if (kernel == NULL)
|
||||
kernel = machine__findnew_dso(machine, machine->mmap_name);
|
||||
|
|
|
@ -196,9 +196,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
|
|||
* reading the header will have the build ID set and all future mmaps will
|
||||
* have it missing.
|
||||
*/
|
||||
down_read(&machine->dsos.lock);
|
||||
header_bid_dso = __dsos__find(&machine->dsos, filename, false);
|
||||
up_read(&machine->dsos.lock);
|
||||
header_bid_dso = dsos__find(&machine->dsos, filename, false);
|
||||
if (header_bid_dso && header_bid_dso->header_build_id) {
|
||||
dso__set_build_id(dso, &header_bid_dso->bid);
|
||||
dso->header_build_id = 1;
|
||||
|
|
|
@ -133,8 +133,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
|
|||
if (dso != NULL) {
|
||||
__dsos__add(&machine->dsos, dso);
|
||||
dso__set_long_name(dso, long_name, false);
|
||||
/* Put dso here because __dsos_add already got it */
|
||||
dso__put(dso);
|
||||
}
|
||||
|
||||
return dso;
|
||||
|
@ -252,17 +250,15 @@ static struct dso *__machine__findnew_compat(struct machine *machine,
|
|||
const char *file_name;
|
||||
struct dso *dso;
|
||||
|
||||
dso = __dsos__find(&machine->dsos, vdso_file->dso_name, true);
|
||||
dso = dsos__find(&machine->dsos, vdso_file->dso_name, true);
|
||||
if (dso)
|
||||
goto out;
|
||||
return dso;
|
||||
|
||||
file_name = vdso__get_compat_file(vdso_file);
|
||||
if (!file_name)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
dso = __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
|
||||
out:
|
||||
return dso;
|
||||
return __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
|
||||
}
|
||||
|
||||
static int __machine__findnew_vdso_compat(struct machine *machine,
|
||||
|
@ -308,21 +304,21 @@ static struct dso *machine__find_vdso(struct machine *machine,
|
|||
dso_type = machine__thread_dso_type(machine, thread);
|
||||
switch (dso_type) {
|
||||
case DSO__TYPE_32BIT:
|
||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
|
||||
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
|
||||
if (!dso) {
|
||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO,
|
||||
true);
|
||||
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO,
|
||||
true);
|
||||
if (dso && dso_type != dso__type(dso, machine))
|
||||
dso = NULL;
|
||||
}
|
||||
break;
|
||||
case DSO__TYPE_X32BIT:
|
||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
|
||||
dso = dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
|
||||
break;
|
||||
case DSO__TYPE_64BIT:
|
||||
case DSO__TYPE_UNKNOWN:
|
||||
default:
|
||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -334,37 +330,33 @@ struct dso *machine__findnew_vdso(struct machine *machine,
|
|||
{
|
||||
struct vdso_info *vdso_info;
|
||||
struct dso *dso = NULL;
|
||||
char *file;
|
||||
|
||||
down_write(&machine->dsos.lock);
|
||||
if (!machine->vdso_info)
|
||||
machine->vdso_info = vdso_info__new();
|
||||
|
||||
vdso_info = machine->vdso_info;
|
||||
if (!vdso_info)
|
||||
goto out_unlock;
|
||||
return NULL;
|
||||
|
||||
dso = machine__find_vdso(machine, thread);
|
||||
if (dso)
|
||||
goto out_unlock;
|
||||
return dso;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
|
||||
goto out_unlock;
|
||||
return dso;
|
||||
#endif
|
||||
|
||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||
if (!dso) {
|
||||
char *file;
|
||||
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||
if (dso)
|
||||
return dso;
|
||||
|
||||
file = get_file(&vdso_info->vdso);
|
||||
if (file)
|
||||
dso = __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
|
||||
}
|
||||
file = get_file(&vdso_info->vdso);
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
out_unlock:
|
||||
dso__get(dso);
|
||||
up_write(&machine->dsos.lock);
|
||||
return dso;
|
||||
return __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
|
||||
}
|
||||
|
||||
bool dso__is_vdso(struct dso *dso)
|
||||
|
|
Loading…
Reference in a new issue