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.
|
* at the end of the list of duplicates.
|
||||||
*/
|
*/
|
||||||
if (!dso || (dso == this))
|
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.
|
* The core kernel DSOs may have duplicated long name.
|
||||||
* In this case, the short name should be different.
|
* 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) {
|
if (cmp_short) {
|
||||||
list_for_each_entry(pos, &dsos->head, node)
|
list_for_each_entry(pos, &dsos->head, node)
|
||||||
if (__dso__cmp_short_name(name, id, pos) == 0)
|
if (__dso__cmp_short_name(name, id, pos) == 0)
|
||||||
return pos;
|
return dso__get(pos);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return __dsos__findnew_by_longname_id(&dsos->root, name, id);
|
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)
|
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) {
|
if (dso != NULL) {
|
||||||
__dsos__add(dsos, dso);
|
__dsos__add(dsos, dso);
|
||||||
dso__set_basename(dso);
|
dso__set_basename(dso);
|
||||||
/* Put dso here because __dsos_add already got it */
|
|
||||||
dso__put(dso);
|
|
||||||
}
|
}
|
||||||
return dso;
|
return dso;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +331,7 @@ struct dso *dsos__findnew_id(struct dsos *dsos, const char *name, struct dso_id
|
||||||
{
|
{
|
||||||
struct dso *dso;
|
struct dso *dso;
|
||||||
down_write(&dsos->lock);
|
down_write(&dsos->lock);
|
||||||
dso = dso__get(__dsos__findnew_id(dsos, name, id));
|
dso = __dsos__findnew_id(dsos, name, id);
|
||||||
up_write(&dsos->lock);
|
up_write(&dsos->lock);
|
||||||
return dso;
|
return dso;
|
||||||
}
|
}
|
||||||
|
@ -374,3 +377,59 @@ int __dsos__hit_all(struct dsos *dsos)
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
struct dso_id;
|
struct dso_id;
|
||||||
|
struct kmod_path;
|
||||||
|
struct machine;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DSOs are put into both a list for fast iteration and rbtree for fast
|
* 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);
|
||||||
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__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);
|
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);
|
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 */
|
#endif /* __PERF_DSOS */
|
||||||
|
|
|
@ -646,31 +646,6 @@ int machine__process_lost_samples_event(struct machine *machine __maybe_unused,
|
||||||
return 0;
|
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,
|
int machine__process_aux_event(struct machine *machine __maybe_unused,
|
||||||
union perf_event *event)
|
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))
|
if (kmod_path__parse_name(&m, filename))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dso = machine__findnew_module_dso(machine, &m, filename);
|
dso = dsos__findnew_module_dso(&machine->dsos, machine, &m, filename);
|
||||||
if (dso == NULL)
|
if (dso == NULL)
|
||||||
goto out;
|
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
|
* Should be there already, from the build-id table in
|
||||||
* the header.
|
* the header.
|
||||||
*/
|
*/
|
||||||
struct dso *kernel = NULL;
|
struct dso *kernel = dsos__find_kernel_dso(&machine->dsos);
|
||||||
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);
|
|
||||||
|
|
||||||
if (kernel == NULL)
|
if (kernel == NULL)
|
||||||
kernel = machine__findnew_dso(machine, machine->mmap_name);
|
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
|
* reading the header will have the build ID set and all future mmaps will
|
||||||
* have it missing.
|
* have it missing.
|
||||||
*/
|
*/
|
||||||
down_read(&machine->dsos.lock);
|
header_bid_dso = dsos__find(&machine->dsos, filename, false);
|
||||||
header_bid_dso = __dsos__find(&machine->dsos, filename, false);
|
|
||||||
up_read(&machine->dsos.lock);
|
|
||||||
if (header_bid_dso && header_bid_dso->header_build_id) {
|
if (header_bid_dso && header_bid_dso->header_build_id) {
|
||||||
dso__set_build_id(dso, &header_bid_dso->bid);
|
dso__set_build_id(dso, &header_bid_dso->bid);
|
||||||
dso->header_build_id = 1;
|
dso->header_build_id = 1;
|
||||||
|
|
|
@ -133,8 +133,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
|
||||||
if (dso != NULL) {
|
if (dso != NULL) {
|
||||||
__dsos__add(&machine->dsos, dso);
|
__dsos__add(&machine->dsos, dso);
|
||||||
dso__set_long_name(dso, long_name, false);
|
dso__set_long_name(dso, long_name, false);
|
||||||
/* Put dso here because __dsos_add already got it */
|
|
||||||
dso__put(dso);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dso;
|
return dso;
|
||||||
|
@ -252,17 +250,15 @@ static struct dso *__machine__findnew_compat(struct machine *machine,
|
||||||
const char *file_name;
|
const char *file_name;
|
||||||
struct dso *dso;
|
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)
|
if (dso)
|
||||||
goto out;
|
return dso;
|
||||||
|
|
||||||
file_name = vdso__get_compat_file(vdso_file);
|
file_name = vdso__get_compat_file(vdso_file);
|
||||||
if (!file_name)
|
if (!file_name)
|
||||||
goto out;
|
return NULL;
|
||||||
|
|
||||||
dso = __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
|
return __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
|
||||||
out:
|
|
||||||
return dso;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __machine__findnew_vdso_compat(struct machine *machine,
|
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);
|
dso_type = machine__thread_dso_type(machine, thread);
|
||||||
switch (dso_type) {
|
switch (dso_type) {
|
||||||
case DSO__TYPE_32BIT:
|
case DSO__TYPE_32BIT:
|
||||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
|
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
|
||||||
if (!dso) {
|
if (!dso) {
|
||||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO,
|
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO,
|
||||||
true);
|
true);
|
||||||
if (dso && dso_type != dso__type(dso, machine))
|
if (dso && dso_type != dso__type(dso, machine))
|
||||||
dso = NULL;
|
dso = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DSO__TYPE_X32BIT:
|
case DSO__TYPE_X32BIT:
|
||||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
|
dso = dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
|
||||||
break;
|
break;
|
||||||
case DSO__TYPE_64BIT:
|
case DSO__TYPE_64BIT:
|
||||||
case DSO__TYPE_UNKNOWN:
|
case DSO__TYPE_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,37 +330,33 @@ struct dso *machine__findnew_vdso(struct machine *machine,
|
||||||
{
|
{
|
||||||
struct vdso_info *vdso_info;
|
struct vdso_info *vdso_info;
|
||||||
struct dso *dso = NULL;
|
struct dso *dso = NULL;
|
||||||
|
char *file;
|
||||||
|
|
||||||
down_write(&machine->dsos.lock);
|
|
||||||
if (!machine->vdso_info)
|
if (!machine->vdso_info)
|
||||||
machine->vdso_info = vdso_info__new();
|
machine->vdso_info = vdso_info__new();
|
||||||
|
|
||||||
vdso_info = machine->vdso_info;
|
vdso_info = machine->vdso_info;
|
||||||
if (!vdso_info)
|
if (!vdso_info)
|
||||||
goto out_unlock;
|
return NULL;
|
||||||
|
|
||||||
dso = machine__find_vdso(machine, thread);
|
dso = machine__find_vdso(machine, thread);
|
||||||
if (dso)
|
if (dso)
|
||||||
goto out_unlock;
|
return dso;
|
||||||
|
|
||||||
#if BITS_PER_LONG == 64
|
#if BITS_PER_LONG == 64
|
||||||
if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
|
if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
|
||||||
goto out_unlock;
|
return dso;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
dso = dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
|
||||||
if (!dso) {
|
if (dso)
|
||||||
char *file;
|
return dso;
|
||||||
|
|
||||||
file = get_file(&vdso_info->vdso);
|
file = get_file(&vdso_info->vdso);
|
||||||
if (file)
|
if (!file)
|
||||||
dso = __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
out_unlock:
|
return __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
|
||||||
dso__get(dso);
|
|
||||||
up_write(&machine->dsos.lock);
|
|
||||||
return dso;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dso__is_vdso(struct dso *dso)
|
bool dso__is_vdso(struct dso *dso)
|
||||||
|
|
Loading…
Reference in a new issue