diff options
-rw-r--r-- | tools/perf/util/dso.c | 70 | ||||
-rw-r--r-- | tools/perf/util/dso.h | 5 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 1 |
3 files changed, 71 insertions, 5 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 901a58fa3f22..0247acfdfaca 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -653,6 +653,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, | |||
653 | return dso; | 653 | return dso; |
654 | } | 654 | } |
655 | 655 | ||
656 | /* | ||
657 | * Find a matching entry and/or link current entry to RB tree. | ||
658 | * Either one of the dso or name parameter must be non-NULL or the | ||
659 | * function will not work. | ||
660 | */ | ||
661 | static struct dso *dso__findlink_by_longname(struct rb_root *root, | ||
662 | struct dso *dso, const char *name) | ||
663 | { | ||
664 | struct rb_node **p = &root->rb_node; | ||
665 | struct rb_node *parent = NULL; | ||
666 | |||
667 | if (!name) | ||
668 | name = dso->long_name; | ||
669 | /* | ||
670 | * Find node with the matching name | ||
671 | */ | ||
672 | while (*p) { | ||
673 | struct dso *this = rb_entry(*p, struct dso, rb_node); | ||
674 | int rc = strcmp(name, this->long_name); | ||
675 | |||
676 | parent = *p; | ||
677 | if (rc == 0) { | ||
678 | /* | ||
679 | * In case the new DSO is a duplicate of an existing | ||
680 | * one, print an one-time warning & put the new entry | ||
681 | * at the end of the list of duplicates. | ||
682 | */ | ||
683 | if (!dso || (dso == this)) | ||
684 | return this; /* Find matching dso */ | ||
685 | /* | ||
686 | * The core kernel DSOs may have duplicated long name. | ||
687 | * In this case, the short name should be different. | ||
688 | * Comparing the short names to differentiate the DSOs. | ||
689 | */ | ||
690 | rc = strcmp(dso->short_name, this->short_name); | ||
691 | if (rc == 0) { | ||
692 | pr_err("Duplicated dso name: %s\n", name); | ||
693 | return NULL; | ||
694 | } | ||
695 | } | ||
696 | if (rc < 0) | ||
697 | p = &parent->rb_left; | ||
698 | else | ||
699 | p = &parent->rb_right; | ||
700 | } | ||
701 | if (dso) { | ||
702 | /* Add new node and rebalance tree */ | ||
703 | rb_link_node(&dso->rb_node, parent, p); | ||
704 | rb_insert_color(&dso->rb_node, root); | ||
705 | } | ||
706 | return NULL; | ||
707 | } | ||
708 | |||
709 | static inline struct dso * | ||
710 | dso__find_by_longname(const struct rb_root *root, const char *name) | ||
711 | { | ||
712 | return dso__findlink_by_longname((struct rb_root *)root, NULL, name); | ||
713 | } | ||
714 | |||
656 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) | 715 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) |
657 | { | 716 | { |
658 | if (name == NULL) | 717 | if (name == NULL) |
@@ -755,6 +814,7 @@ struct dso *dso__new(const char *name) | |||
755 | dso->a2l_fails = 1; | 814 | dso->a2l_fails = 1; |
756 | dso->kernel = DSO_TYPE_USER; | 815 | dso->kernel = DSO_TYPE_USER; |
757 | dso->needs_swap = DSO_SWAP__UNSET; | 816 | dso->needs_swap = DSO_SWAP__UNSET; |
817 | RB_CLEAR_NODE(&dso->rb_node); | ||
758 | INIT_LIST_HEAD(&dso->node); | 818 | INIT_LIST_HEAD(&dso->node); |
759 | INIT_LIST_HEAD(&dso->data.open_entry); | 819 | INIT_LIST_HEAD(&dso->data.open_entry); |
760 | } | 820 | } |
@@ -765,6 +825,10 @@ struct dso *dso__new(const char *name) | |||
765 | void dso__delete(struct dso *dso) | 825 | void dso__delete(struct dso *dso) |
766 | { | 826 | { |
767 | int i; | 827 | int i; |
828 | |||
829 | if (!RB_EMPTY_NODE(&dso->rb_node)) | ||
830 | pr_err("DSO %s is still in rbtree when being deleted!\n", | ||
831 | dso->long_name); | ||
768 | for (i = 0; i < MAP__NR_TYPES; ++i) | 832 | for (i = 0; i < MAP__NR_TYPES; ++i) |
769 | symbols__delete(&dso->symbols[i]); | 833 | symbols__delete(&dso->symbols[i]); |
770 | 834 | ||
@@ -854,6 +918,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | |||
854 | void dsos__add(struct dsos *dsos, struct dso *dso) | 918 | void dsos__add(struct dsos *dsos, struct dso *dso) |
855 | { | 919 | { |
856 | list_add_tail(&dso->node, &dsos->head); | 920 | list_add_tail(&dso->node, &dsos->head); |
921 | dso__findlink_by_longname(&dsos->root, dso, NULL); | ||
857 | } | 922 | } |
858 | 923 | ||
859 | struct dso *dsos__find(const struct dsos *dsos, const char *name, | 924 | struct dso *dsos__find(const struct dsos *dsos, const char *name, |
@@ -867,10 +932,7 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name, | |||
867 | return pos; | 932 | return pos; |
868 | return NULL; | 933 | return NULL; |
869 | } | 934 | } |
870 | list_for_each_entry(pos, &dsos->head, node) | 935 | return dso__find_by_longname(&dsos->root, name); |
871 | if (strcmp(pos->long_name, name) == 0) | ||
872 | return pos; | ||
873 | return NULL; | ||
874 | } | 936 | } |
875 | 937 | ||
876 | struct dso *__dsos__findnew(struct dsos *dsos, const char *name) | 938 | struct dso *__dsos__findnew(struct dsos *dsos, const char *name) |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index b63dc98ad71d..acb651acc7fd 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -91,14 +91,17 @@ struct dso_cache { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * DSOs are put into a list for fast iteration. | 94 | * DSOs are put into both a list for fast iteration and rbtree for fast |
95 | * long name lookup. | ||
95 | */ | 96 | */ |
96 | struct dsos { | 97 | struct dsos { |
97 | struct list_head head; | 98 | struct list_head head; |
99 | struct rb_root root; /* rbtree root sorted by long name */ | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | struct dso { | 102 | struct dso { |
101 | struct list_head node; | 103 | struct list_head node; |
104 | struct rb_node rb_node; /* rbtree node sorted by long name */ | ||
102 | struct rb_root symbols[MAP__NR_TYPES]; | 105 | struct rb_root symbols[MAP__NR_TYPES]; |
103 | struct rb_root symbol_names[MAP__NR_TYPES]; | 106 | struct rb_root symbol_names[MAP__NR_TYPES]; |
104 | void *a2l; | 107 | void *a2l; |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 49a75ec4c47b..b7d477fbda02 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -77,6 +77,7 @@ static void dsos__delete(struct dsos *dsos) | |||
77 | struct dso *pos, *n; | 77 | struct dso *pos, *n; |
78 | 78 | ||
79 | list_for_each_entry_safe(pos, n, &dsos->head, node) { | 79 | list_for_each_entry_safe(pos, n, &dsos->head, node) { |
80 | RB_CLEAR_NODE(&pos->rb_node); | ||
80 | list_del(&pos->node); | 81 | list_del(&pos->node); |
81 | dso__delete(pos); | 82 | dso__delete(pos); |
82 | } | 83 | } |