aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-05-27 12:42:36 -0400
committerIngo Molnar <mingo@kernel.org>2015-05-27 12:42:36 -0400
commit6632c4b4e96c668e19173fa17f2c58c60490bac3 (patch)
tree7d9cae783cc4da0968f6c826ea4954c56217357b /tools
parenta82d24edfeaf1ed244cf8b969916840c6feb5165 (diff)
parentdddc7ee32fa13efc66afa71ebd83bce545c8392a (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Add option in 'perf sched' to merge like comms to lat output (Josef Bacik) - Improve 'perf probe' error messages when not finding a suitable vmlinux (Masami Hiramatsu) Infrastructure changes: - Use atomic.h for various pre-existing reference counts (Arnaldo Carvalho de Melo) - Leg work for refcounting 'struct map' (Arnaldo Carvalho de Melo) - Assign default value for some pointers (Martin Liška) - Improve setting of gcc debug option (Martin Liška) - Separate the tests and tools in installation (Nam T. Nguyen) - Reduce number of arguments of hist_entry_iter__add() (Namhyung Kim) - DSO data cache fixes (Namhyung Kim) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile.perf6
-rw-r--r--tools/perf/arch/common.c2
-rw-r--r--tools/perf/builtin-report.c9
-rw-r--r--tools/perf/builtin-sched.c77
-rw-r--r--tools/perf/builtin-top.c7
-rw-r--r--tools/perf/config/Makefile4
-rw-r--r--tools/perf/config/utilities.mak19
-rw-r--r--tools/perf/tests/dso-data.c11
-rw-r--r--tools/perf/tests/hists_cumulate.c6
-rw-r--r--tools/perf/tests/hists_filter.c4
-rw-r--r--tools/perf/tests/hists_output.c6
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c34
-rw-r--r--tools/perf/util/comm.c13
-rw-r--r--tools/perf/util/dso.c88
-rw-r--r--tools/perf/util/dso.h13
-rw-r--r--tools/perf/util/event.c7
-rw-r--r--tools/perf/util/hist.c24
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/linux/rbtree.h14
-rw-r--r--tools/perf/util/machine.c6
-rw-r--r--tools/perf/util/map.c31
-rw-r--r--tools/perf/util/map.h6
-rw-r--r--tools/perf/util/parse-events.c18
-rw-r--r--tools/perf/util/parse-events.h6
-rw-r--r--tools/perf/util/parse-events.y6
-rw-r--r--tools/perf/util/pmu.c4
-rw-r--r--tools/perf/util/probe-event.c65
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/session.c6
-rw-r--r--tools/perf/util/symbol.c25
-rw-r--r--tools/perf/util/thread.c2
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/unwind-libunwind.c11
33 files changed, 332 insertions, 204 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 03409cc02117..5816a3bb7e9f 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -464,7 +464,7 @@ check: $(OUTPUT)common-cmds.h
464 464
465install-gtk: 465install-gtk:
466 466
467install-bin: all install-gtk 467install-tools: all install-gtk
468 $(call QUIET_INSTALL, binaries) \ 468 $(call QUIET_INSTALL, binaries) \
469 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ 469 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
470 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ 470 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
@@ -502,12 +502,16 @@ endif
502 $(call QUIET_INSTALL, perf_completion-script) \ 502 $(call QUIET_INSTALL, perf_completion-script) \
503 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ 503 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
504 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 504 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
505
506install-tests: all install-gtk
505 $(call QUIET_INSTALL, tests) \ 507 $(call QUIET_INSTALL, tests) \
506 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 508 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
507 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 509 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
508 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 510 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
509 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 511 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
510 512
513install-bin: install-tools install-tests
514
511install: install-bin try-install-man install-traceevent-plugins 515install: install-bin try-install-man install-traceevent-plugins
512 516
513install-python_ext: 517install-python_ext:
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 49776f190abf..b7bb42c44694 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -61,7 +61,7 @@ const char *const mips_triplets[] = {
61static bool lookup_path(char *name) 61static bool lookup_path(char *name)
62{ 62{
63 bool found = false; 63 bool found = false;
64 char *path, *tmp; 64 char *path, *tmp = NULL;
65 char buf[PATH_MAX]; 65 char buf[PATH_MAX];
66 char *env = getenv("PATH"); 66 char *env = getenv("PATH");
67 67
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 92fca2157e5e..56025d90622f 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -139,8 +139,10 @@ static int process_sample_event(struct perf_tool *tool,
139 struct report *rep = container_of(tool, struct report, tool); 139 struct report *rep = container_of(tool, struct report, tool);
140 struct addr_location al; 140 struct addr_location al;
141 struct hist_entry_iter iter = { 141 struct hist_entry_iter iter = {
142 .hide_unresolved = rep->hide_unresolved, 142 .evsel = evsel,
143 .add_entry_cb = hist_iter__report_callback, 143 .sample = sample,
144 .hide_unresolved = rep->hide_unresolved,
145 .add_entry_cb = hist_iter__report_callback,
144 }; 146 };
145 int ret = 0; 147 int ret = 0;
146 148
@@ -168,8 +170,7 @@ static int process_sample_event(struct perf_tool *tool,
168 if (al.map != NULL) 170 if (al.map != NULL)
169 al.map->dso->hit = 1; 171 al.map->dso->hit = 1;
170 172
171 ret = hist_entry_iter__add(&iter, &al, evsel, sample, rep->max_stack, 173 ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
172 rep);
173 if (ret < 0) 174 if (ret < 0)
174 pr_debug("problem adding hist entry, skipping event\n"); 175 pr_debug("problem adding hist entry, skipping event\n");
175out_put: 176out_put:
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 79273ecf92eb..33962612a5e9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -95,6 +95,7 @@ struct work_atoms {
95 u64 total_lat; 95 u64 total_lat;
96 u64 nb_atoms; 96 u64 nb_atoms;
97 u64 total_runtime; 97 u64 total_runtime;
98 int num_merged;
98}; 99};
99 100
100typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); 101typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *);
@@ -168,9 +169,10 @@ struct perf_sched {
168 u64 all_runtime; 169 u64 all_runtime;
169 u64 all_count; 170 u64 all_count;
170 u64 cpu_last_switched[MAX_CPUS]; 171 u64 cpu_last_switched[MAX_CPUS];
171 struct rb_root atom_root, sorted_atom_root; 172 struct rb_root atom_root, sorted_atom_root, merged_atom_root;
172 struct list_head sort_list, cmp_pid; 173 struct list_head sort_list, cmp_pid;
173 bool force; 174 bool force;
175 bool skip_merge;
174}; 176};
175 177
176static u64 get_nsecs(void) 178static u64 get_nsecs(void)
@@ -1182,7 +1184,10 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1182 sched->all_runtime += work_list->total_runtime; 1184 sched->all_runtime += work_list->total_runtime;
1183 sched->all_count += work_list->nb_atoms; 1185 sched->all_count += work_list->nb_atoms;
1184 1186
1185 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid); 1187 if (work_list->num_merged > 1)
1188 ret = printf(" %s:(%d) ", thread__comm_str(work_list->thread), work_list->num_merged);
1189 else
1190 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid);
1186 1191
1187 for (i = 0; i < 24 - ret; i++) 1192 for (i = 0; i < 24 - ret; i++)
1188 printf(" "); 1193 printf(" ");
@@ -1302,17 +1307,22 @@ static int sort_dimension__add(const char *tok, struct list_head *list)
1302static void perf_sched__sort_lat(struct perf_sched *sched) 1307static void perf_sched__sort_lat(struct perf_sched *sched)
1303{ 1308{
1304 struct rb_node *node; 1309 struct rb_node *node;
1305 1310 struct rb_root *root = &sched->atom_root;
1311again:
1306 for (;;) { 1312 for (;;) {
1307 struct work_atoms *data; 1313 struct work_atoms *data;
1308 node = rb_first(&sched->atom_root); 1314 node = rb_first(root);
1309 if (!node) 1315 if (!node)
1310 break; 1316 break;
1311 1317
1312 rb_erase(node, &sched->atom_root); 1318 rb_erase(node, root);
1313 data = rb_entry(node, struct work_atoms, node); 1319 data = rb_entry(node, struct work_atoms, node);
1314 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list); 1320 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list);
1315 } 1321 }
1322 if (root == &sched->atom_root) {
1323 root = &sched->merged_atom_root;
1324 goto again;
1325 }
1316} 1326}
1317 1327
1318static int process_sched_wakeup_event(struct perf_tool *tool, 1328static int process_sched_wakeup_event(struct perf_tool *tool,
@@ -1572,6 +1582,59 @@ static void print_bad_events(struct perf_sched *sched)
1572 } 1582 }
1573} 1583}
1574 1584
1585static void __merge_work_atoms(struct rb_root *root, struct work_atoms *data)
1586{
1587 struct rb_node **new = &(root->rb_node), *parent = NULL;
1588 struct work_atoms *this;
1589 const char *comm = thread__comm_str(data->thread), *this_comm;
1590
1591 while (*new) {
1592 int cmp;
1593
1594 this = container_of(*new, struct work_atoms, node);
1595 parent = *new;
1596
1597 this_comm = thread__comm_str(this->thread);
1598 cmp = strcmp(comm, this_comm);
1599 if (cmp > 0) {
1600 new = &((*new)->rb_left);
1601 } else if (cmp < 0) {
1602 new = &((*new)->rb_right);
1603 } else {
1604 this->num_merged++;
1605 this->total_runtime += data->total_runtime;
1606 this->nb_atoms += data->nb_atoms;
1607 this->total_lat += data->total_lat;
1608 list_splice(&data->work_list, &this->work_list);
1609 if (this->max_lat < data->max_lat) {
1610 this->max_lat = data->max_lat;
1611 this->max_lat_at = data->max_lat_at;
1612 }
1613 zfree(&data);
1614 return;
1615 }
1616 }
1617
1618 data->num_merged++;
1619 rb_link_node(&data->node, parent, new);
1620 rb_insert_color(&data->node, root);
1621}
1622
1623static void perf_sched__merge_lat(struct perf_sched *sched)
1624{
1625 struct work_atoms *data;
1626 struct rb_node *node;
1627
1628 if (sched->skip_merge)
1629 return;
1630
1631 while ((node = rb_first(&sched->atom_root))) {
1632 rb_erase(node, &sched->atom_root);
1633 data = rb_entry(node, struct work_atoms, node);
1634 __merge_work_atoms(&sched->merged_atom_root, data);
1635 }
1636}
1637
1575static int perf_sched__lat(struct perf_sched *sched) 1638static int perf_sched__lat(struct perf_sched *sched)
1576{ 1639{
1577 struct rb_node *next; 1640 struct rb_node *next;
@@ -1581,6 +1644,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1581 if (perf_sched__read_events(sched)) 1644 if (perf_sched__read_events(sched))
1582 return -1; 1645 return -1;
1583 1646
1647 perf_sched__merge_lat(sched);
1584 perf_sched__sort_lat(sched); 1648 perf_sched__sort_lat(sched);
1585 1649
1586 printf("\n -----------------------------------------------------------------------------------------------------------------\n"); 1650 printf("\n -----------------------------------------------------------------------------------------------------------------\n");
@@ -1732,6 +1796,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1732 .profile_cpu = -1, 1796 .profile_cpu = -1,
1733 .next_shortname1 = 'A', 1797 .next_shortname1 = 'A',
1734 .next_shortname2 = '0', 1798 .next_shortname2 = '0',
1799 .skip_merge = 0,
1735 }; 1800 };
1736 const struct option latency_options[] = { 1801 const struct option latency_options[] = {
1737 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1802 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
@@ -1742,6 +1807,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1742 "CPU to profile on"), 1807 "CPU to profile on"),
1743 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1808 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1744 "dump raw trace in ASCII"), 1809 "dump raw trace in ASCII"),
1810 OPT_BOOLEAN('p', "pids", &sched.skip_merge,
1811 "latency stats per pid instead of per comm"),
1745 OPT_END() 1812 OPT_END()
1746 }; 1813 };
1747 const struct option replay_options[] = { 1814 const struct option replay_options[] = {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index a19351728f0f..6b987424d015 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -775,7 +775,9 @@ static void perf_event__process_sample(struct perf_tool *tool,
775 if (al.sym == NULL || !al.sym->ignore) { 775 if (al.sym == NULL || !al.sym->ignore) {
776 struct hists *hists = evsel__hists(evsel); 776 struct hists *hists = evsel__hists(evsel);
777 struct hist_entry_iter iter = { 777 struct hist_entry_iter iter = {
778 .add_entry_cb = hist_iter__top_callback, 778 .evsel = evsel,
779 .sample = sample,
780 .add_entry_cb = hist_iter__top_callback,
779 }; 781 };
780 782
781 if (symbol_conf.cumulate_callchain) 783 if (symbol_conf.cumulate_callchain)
@@ -785,8 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
785 787
786 pthread_mutex_lock(&hists->lock); 788 pthread_mutex_lock(&hists->lock);
787 789
788 err = hist_entry_iter__add(&iter, &al, evsel, sample, 790 err = hist_entry_iter__add(&iter, &al, top->max_stack, top);
789 top->max_stack, top);
790 if (err < 0) 791 if (err < 0)
791 pr_err("Problem incrementing symbol period, skipping event\n"); 792 pr_err("Problem incrementing symbol period, skipping event\n");
792 793
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1b957a1272d0..317001c94660 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -32,7 +32,7 @@ ifeq ($(ARCH),x86)
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64) 33 $(call detected,CONFIG_X86_64)
34 else 34 else
35 LIBUNWIND_LIBS = -lunwind -lunwind-x86 35 LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
36 endif 36 endif
37 NO_PERF_REGS := 0 37 NO_PERF_REGS := 0
38endif 38endif
@@ -130,6 +130,8 @@ endif
130 130
131ifeq ($(DEBUG),0) 131ifeq ($(DEBUG),0)
132 CFLAGS += -O6 132 CFLAGS += -O6
133else
134 CFLAGS += $(call cc-option,-Og,-O0)
133endif 135endif
134 136
135ifdef PARSER_DEBUG 137ifdef PARSER_DEBUG
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index c16ce833079c..0ebef09c0842 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -177,3 +177,22 @@ $(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177endef 177endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
180
181# try-run
182# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
183# Exit code chooses option. "$$TMP" is can be used as temporary file and
184# is automatically cleaned up.
185try-run = $(shell set -e; \
186 TMP="$(TMPOUT).$$$$.tmp"; \
187 TMPO="$(TMPOUT).$$$$.o"; \
188 if ($(1)) >/dev/null 2>&1; \
189 then echo "$(2)"; \
190 else echo "$(3)"; \
191 fi; \
192 rm -f "$$TMP" "$$TMPO")
193
194# cc-option
195# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
196
197cc-option = $(call try-run,\
198 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 513e5febbe5a..3e41c61bd861 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -99,6 +99,17 @@ struct test_data_offset offsets[] = {
99 }, 99 },
100}; 100};
101 101
102/* move it from util/dso.c for compatibility */
103static int dso__data_fd(struct dso *dso, struct machine *machine)
104{
105 int fd = dso__data_get_fd(dso, machine);
106
107 if (fd >= 0)
108 dso__data_put_fd(dso);
109
110 return fd;
111}
112
102int test__dso_data(void) 113int test__dso_data(void)
103{ 114{
104 struct machine machine; 115 struct machine machine;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 620f626e5b35..7d82c8be5e36 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -87,6 +87,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
87 }, 87 },
88 }; 88 };
89 struct hist_entry_iter iter = { 89 struct hist_entry_iter iter = {
90 .evsel = evsel,
91 .sample = &sample,
90 .hide_unresolved = false, 92 .hide_unresolved = false,
91 }; 93 };
92 94
@@ -104,8 +106,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
104 &sample) < 0) 106 &sample) < 0)
105 goto out; 107 goto out;
106 108
107 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 109 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
108 PERF_MAX_STACK_DEPTH, NULL) < 0) { 110 NULL) < 0) {
109 addr_location__put(&al); 111 addr_location__put(&al);
110 goto out; 112 goto out;
111 } 113 }
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 82e1ee52e024..ce48775e6ada 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -63,6 +63,8 @@ static int add_hist_entries(struct perf_evlist *evlist,
63 }, 63 },
64 }; 64 };
65 struct hist_entry_iter iter = { 65 struct hist_entry_iter iter = {
66 .evsel = evsel,
67 .sample = &sample,
66 .ops = &hist_iter_normal, 68 .ops = &hist_iter_normal,
67 .hide_unresolved = false, 69 .hide_unresolved = false,
68 }; 70 };
@@ -81,7 +83,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
81 &sample) < 0) 83 &sample) < 0)
82 goto out; 84 goto out;
83 85
84 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 86 if (hist_entry_iter__add(&iter, &al,
85 PERF_MAX_STACK_DEPTH, NULL) < 0) { 87 PERF_MAX_STACK_DEPTH, NULL) < 0) {
86 addr_location__put(&al); 88 addr_location__put(&al);
87 goto out; 89 goto out;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index fd7ec4f9aeb4..adbebc852cc8 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -57,6 +57,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
57 }, 57 },
58 }; 58 };
59 struct hist_entry_iter iter = { 59 struct hist_entry_iter iter = {
60 .evsel = evsel,
61 .sample = &sample,
60 .ops = &hist_iter_normal, 62 .ops = &hist_iter_normal,
61 .hide_unresolved = false, 63 .hide_unresolved = false,
62 }; 64 };
@@ -70,8 +72,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
70 &sample) < 0) 72 &sample) < 0)
71 goto out; 73 goto out;
72 74
73 if (hist_entry_iter__add(&iter, &al, evsel, &sample, 75 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
74 PERF_MAX_STACK_DEPTH, NULL) < 0) { 76 NULL) < 0) {
75 addr_location__put(&al); 77 addr_location__put(&al);
76 goto out; 78 goto out;
77 } 79 }
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 3d9088003a5b..94ac6924df65 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -23,9 +23,10 @@ int test__vmlinux_matches_kallsyms(void)
23 int err = -1; 23 int err = -1;
24 struct rb_node *nd; 24 struct rb_node *nd;
25 struct symbol *sym; 25 struct symbol *sym;
26 struct map *kallsyms_map, *vmlinux_map; 26 struct map *kallsyms_map, *vmlinux_map, *map;
27 struct machine kallsyms, vmlinux; 27 struct machine kallsyms, vmlinux;
28 enum map_type type = MAP__FUNCTION; 28 enum map_type type = MAP__FUNCTION;
29 struct rb_root *maps = &vmlinux.kmaps.maps[type];
29 u64 mem_start, mem_end; 30 u64 mem_start, mem_end;
30 31
31 /* 32 /*
@@ -184,8 +185,8 @@ detour:
184 185
185 pr_info("Maps only in vmlinux:\n"); 186 pr_info("Maps only in vmlinux:\n");
186 187
187 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { 188 for (map = maps__first(maps); map; map = map__next(map)) {
188 struct map *pos = rb_entry(nd, struct map, rb_node), *pair; 189 struct map *
189 /* 190 /*
190 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while 191 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
191 * the kernel will have the path for the vmlinux file being used, 192 * the kernel will have the path for the vmlinux file being used,
@@ -193,22 +194,22 @@ detour:
193 * both cases. 194 * both cases.
194 */ 195 */
195 pair = map_groups__find_by_name(&kallsyms.kmaps, type, 196 pair = map_groups__find_by_name(&kallsyms.kmaps, type,
196 (pos->dso->kernel ? 197 (map->dso->kernel ?
197 pos->dso->short_name : 198 map->dso->short_name :
198 pos->dso->name)); 199 map->dso->name));
199 if (pair) 200 if (pair)
200 pair->priv = 1; 201 pair->priv = 1;
201 else 202 else
202 map__fprintf(pos, stderr); 203 map__fprintf(map, stderr);
203 } 204 }
204 205
205 pr_info("Maps in vmlinux with a different name in kallsyms:\n"); 206 pr_info("Maps in vmlinux with a different name in kallsyms:\n");
206 207
207 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { 208 for (map = maps__first(maps); map; map = map__next(map)) {
208 struct map *pos = rb_entry(nd, struct map, rb_node), *pair; 209 struct map *pair;
209 210
210 mem_start = vmlinux_map->unmap_ip(vmlinux_map, pos->start); 211 mem_start = vmlinux_map->unmap_ip(vmlinux_map, map->start);
211 mem_end = vmlinux_map->unmap_ip(vmlinux_map, pos->end); 212 mem_end = vmlinux_map->unmap_ip(vmlinux_map, map->end);
212 213
213 pair = map_groups__find(&kallsyms.kmaps, type, mem_start); 214 pair = map_groups__find(&kallsyms.kmaps, type, mem_start);
214 if (pair == NULL || pair->priv) 215 if (pair == NULL || pair->priv)
@@ -217,7 +218,7 @@ detour:
217 if (pair->start == mem_start) { 218 if (pair->start == mem_start) {
218 pair->priv = 1; 219 pair->priv = 1;
219 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 220 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
220 pos->start, pos->end, pos->pgoff, pos->dso->name); 221 map->start, map->end, map->pgoff, map->dso->name);
221 if (mem_end != pair->end) 222 if (mem_end != pair->end)
222 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64, 223 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64,
223 pair->start, pair->end, pair->pgoff); 224 pair->start, pair->end, pair->pgoff);
@@ -228,12 +229,11 @@ detour:
228 229
229 pr_info("Maps only in kallsyms:\n"); 230 pr_info("Maps only in kallsyms:\n");
230 231
231 for (nd = rb_first(&kallsyms.kmaps.maps[type]); 232 maps = &kallsyms.kmaps.maps[type];
232 nd; nd = rb_next(nd)) {
233 struct map *pos = rb_entry(nd, struct map, rb_node);
234 233
235 if (!pos->priv) 234 for (map = maps__first(maps); map; map = map__next(map)) {
236 map__fprintf(pos, stderr); 235 if (!map->priv)
236 map__fprintf(map, stderr);
237 } 237 }
238out: 238out:
239 machine__exit(&kallsyms); 239 machine__exit(&kallsyms);
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index b2bb59df65e1..21b7ff382c3f 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -2,24 +2,27 @@
2#include "util.h" 2#include "util.h"
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <linux/atomic.h>
5 6
6struct comm_str { 7struct comm_str {
7 char *str; 8 char *str;
8 struct rb_node rb_node; 9 struct rb_node rb_node;
9 int ref; 10 atomic_t refcnt;
10}; 11};
11 12
12/* Should perhaps be moved to struct machine */ 13/* Should perhaps be moved to struct machine */
13static struct rb_root comm_str_root; 14static struct rb_root comm_str_root;
14 15
15static void comm_str__get(struct comm_str *cs) 16static struct comm_str *comm_str__get(struct comm_str *cs)
16{ 17{
17 cs->ref++; 18 if (cs)
19 atomic_inc(&cs->refcnt);
20 return cs;
18} 21}
19 22
20static void comm_str__put(struct comm_str *cs) 23static void comm_str__put(struct comm_str *cs)
21{ 24{
22 if (!--cs->ref) { 25 if (cs && atomic_dec_and_test(&cs->refcnt)) {
23 rb_erase(&cs->rb_node, &comm_str_root); 26 rb_erase(&cs->rb_node, &comm_str_root);
24 zfree(&cs->str); 27 zfree(&cs->str);
25 free(cs); 28 free(cs);
@@ -40,6 +43,8 @@ static struct comm_str *comm_str__alloc(const char *str)
40 return NULL; 43 return NULL;
41 } 44 }
42 45
46 atomic_set(&cs->refcnt, 0);
47
43 return cs; 48 return cs;
44} 49}
45 50
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 1b96c8d18435..7e11a700303f 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -440,15 +440,7 @@ void dso__data_close(struct dso *dso)
440 pthread_mutex_unlock(&dso__data_open_lock); 440 pthread_mutex_unlock(&dso__data_open_lock);
441} 441}
442 442
443/** 443static void try_to_open_dso(struct dso *dso, struct machine *machine)
444 * dso__data_fd - Get dso's data file descriptor
445 * @dso: dso object
446 * @machine: machine object
447 *
448 * External interface to find dso's file, open it and
449 * returns file descriptor.
450 */
451int dso__data_fd(struct dso *dso, struct machine *machine)
452{ 444{
453 enum dso_binary_type binary_type_data[] = { 445 enum dso_binary_type binary_type_data[] = {
454 DSO_BINARY_TYPE__BUILD_ID_CACHE, 446 DSO_BINARY_TYPE__BUILD_ID_CACHE,
@@ -457,13 +449,8 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
457 }; 449 };
458 int i = 0; 450 int i = 0;
459 451
460 if (dso->data.status == DSO_DATA_STATUS_ERROR)
461 return -1;
462
463 pthread_mutex_lock(&dso__data_open_lock);
464
465 if (dso->data.fd >= 0) 452 if (dso->data.fd >= 0)
466 goto out; 453 return;
467 454
468 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) { 455 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
469 dso->data.fd = open_dso(dso, machine); 456 dso->data.fd = open_dso(dso, machine);
@@ -483,11 +470,38 @@ out:
483 dso->data.status = DSO_DATA_STATUS_OK; 470 dso->data.status = DSO_DATA_STATUS_OK;
484 else 471 else
485 dso->data.status = DSO_DATA_STATUS_ERROR; 472 dso->data.status = DSO_DATA_STATUS_ERROR;
473}
474
475/**
476 * dso__data_get_fd - Get dso's data file descriptor
477 * @dso: dso object
478 * @machine: machine object
479 *
480 * External interface to find dso's file, open it and
481 * returns file descriptor. It should be paired with
482 * dso__data_put_fd() if it returns non-negative value.
483 */
484int dso__data_get_fd(struct dso *dso, struct machine *machine)
485{
486 if (dso->data.status == DSO_DATA_STATUS_ERROR)
487 return -1;
488
489 if (pthread_mutex_lock(&dso__data_open_lock) < 0)
490 return -1;
491
492 try_to_open_dso(dso, machine);
493
494 if (dso->data.fd < 0)
495 pthread_mutex_unlock(&dso__data_open_lock);
486 496
487 pthread_mutex_unlock(&dso__data_open_lock);
488 return dso->data.fd; 497 return dso->data.fd;
489} 498}
490 499
500void dso__data_put_fd(struct dso *dso __maybe_unused)
501{
502 pthread_mutex_unlock(&dso__data_open_lock);
503}
504
491bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by) 505bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
492{ 506{
493 u32 flag = 1 << by; 507 u32 flag = 1 << by;
@@ -609,13 +623,12 @@ dso_cache__read(struct dso *dso, struct machine *machine,
609 * dso->data.fd might be closed if other thread opened another 623 * dso->data.fd might be closed if other thread opened another
610 * file (dso) due to open file limit (RLIMIT_NOFILE). 624 * file (dso) due to open file limit (RLIMIT_NOFILE).
611 */ 625 */
626 try_to_open_dso(dso, machine);
627
612 if (dso->data.fd < 0) { 628 if (dso->data.fd < 0) {
613 dso->data.fd = open_dso(dso, machine); 629 ret = -errno;
614 if (dso->data.fd < 0) { 630 dso->data.status = DSO_DATA_STATUS_ERROR;
615 ret = -errno; 631 break;
616 dso->data.status = DSO_DATA_STATUS_ERROR;
617 break;
618 }
619 } 632 }
620 633
621 cache_offset = offset & DSO__DATA_CACHE_MASK; 634 cache_offset = offset & DSO__DATA_CACHE_MASK;
@@ -702,19 +715,21 @@ static int data_file_size(struct dso *dso, struct machine *machine)
702 if (dso->data.file_size) 715 if (dso->data.file_size)
703 return 0; 716 return 0;
704 717
718 if (dso->data.status == DSO_DATA_STATUS_ERROR)
719 return -1;
720
705 pthread_mutex_lock(&dso__data_open_lock); 721 pthread_mutex_lock(&dso__data_open_lock);
706 722
707 /* 723 /*
708 * dso->data.fd might be closed if other thread opened another 724 * dso->data.fd might be closed if other thread opened another
709 * file (dso) due to open file limit (RLIMIT_NOFILE). 725 * file (dso) due to open file limit (RLIMIT_NOFILE).
710 */ 726 */
727 try_to_open_dso(dso, machine);
728
711 if (dso->data.fd < 0) { 729 if (dso->data.fd < 0) {
712 dso->data.fd = open_dso(dso, machine); 730 ret = -errno;
713 if (dso->data.fd < 0) { 731 dso->data.status = DSO_DATA_STATUS_ERROR;
714 ret = -errno; 732 goto out;
715 dso->data.status = DSO_DATA_STATUS_ERROR;
716 goto out;
717 }
718 } 733 }
719 734
720 if (fstat(dso->data.fd, &st) < 0) { 735 if (fstat(dso->data.fd, &st) < 0) {
@@ -740,12 +755,6 @@ out:
740 */ 755 */
741off_t dso__data_size(struct dso *dso, struct machine *machine) 756off_t dso__data_size(struct dso *dso, struct machine *machine)
742{ 757{
743 int fd;
744
745 fd = dso__data_fd(dso, machine);
746 if (fd < 0)
747 return fd;
748
749 if (data_file_size(dso, machine)) 758 if (data_file_size(dso, machine))
750 return -1; 759 return -1;
751 760
@@ -1200,12 +1209,15 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
1200enum dso_type dso__type(struct dso *dso, struct machine *machine) 1209enum dso_type dso__type(struct dso *dso, struct machine *machine)
1201{ 1210{
1202 int fd; 1211 int fd;
1212 enum dso_type type = DSO__TYPE_UNKNOWN;
1203 1213
1204 fd = dso__data_fd(dso, machine); 1214 fd = dso__data_get_fd(dso, machine);
1205 if (fd < 0) 1215 if (fd >= 0) {
1206 return DSO__TYPE_UNKNOWN; 1216 type = dso__type_fd(fd);
1217 dso__data_put_fd(dso);
1218 }
1207 1219
1208 return dso__type_fd(fd); 1220 return type;
1209} 1221}
1210 1222
1211int dso__strerror_load(struct dso *dso, char *buf, size_t buflen) 1223int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index b26ec3ab1336..bcec06ad73a2 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -240,7 +240,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
240 240
241/* 241/*
242 * The dso__data_* external interface provides following functions: 242 * The dso__data_* external interface provides following functions:
243 * dso__data_fd 243 * dso__data_get_fd
244 * dso__data_put_fd
244 * dso__data_close 245 * dso__data_close
245 * dso__data_size 246 * dso__data_size
246 * dso__data_read_offset 247 * dso__data_read_offset
@@ -257,8 +258,11 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
257 * The current usage of the dso__data_* interface is as follows: 258 * The current usage of the dso__data_* interface is as follows:
258 * 259 *
259 * Get DSO's fd: 260 * Get DSO's fd:
260 * int fd = dso__data_fd(dso, machine); 261 * int fd = dso__data_get_fd(dso, machine);
261 * USE 'fd' SOMEHOW 262 * if (fd >= 0) {
263 * USE 'fd' SOMEHOW
264 * dso__data_put_fd(dso);
265 * }
262 * 266 *
263 * Read DSO's data: 267 * Read DSO's data:
264 * n = dso__data_read_offset(dso_0, &machine, 0, buf, BUFSIZE); 268 * n = dso__data_read_offset(dso_0, &machine, 0, buf, BUFSIZE);
@@ -277,7 +281,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
277 * 281 *
278 * TODO 282 * TODO
279*/ 283*/
280int dso__data_fd(struct dso *dso, struct machine *machine); 284int dso__data_get_fd(struct dso *dso, struct machine *machine);
285void dso__data_put_fd(struct dso *dso __maybe_unused);
281void dso__data_close(struct dso *dso); 286void dso__data_close(struct dso *dso);
282 287
283off_t dso__data_size(struct dso *dso, struct machine *machine); 288off_t dso__data_size(struct dso *dso, struct machine *machine);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index a513a51f7330..9d3bba175423 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -329,8 +329,9 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
329 struct machine *machine) 329 struct machine *machine)
330{ 330{
331 int rc = 0; 331 int rc = 0;
332 struct rb_node *nd; 332 struct map *pos;
333 struct map_groups *kmaps = &machine->kmaps; 333 struct map_groups *kmaps = &machine->kmaps;
334 struct rb_root *maps = &kmaps->maps[MAP__FUNCTION];
334 union perf_event *event = zalloc((sizeof(event->mmap) + 335 union perf_event *event = zalloc((sizeof(event->mmap) +
335 machine->id_hdr_size)); 336 machine->id_hdr_size));
336 if (event == NULL) { 337 if (event == NULL) {
@@ -350,10 +351,8 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
350 else 351 else
351 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 352 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
352 353
353 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 354 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
354 nd; nd = rb_next(nd)) {
355 size_t size; 355 size_t size;
356 struct map *pos = rb_entry(nd, struct map, rb_node);
357 356
358 if (pos->dso->kernel) 357 if (pos->dso->kernel)
359 continue; 358 continue;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 338770679863..f53d017c7c22 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -362,10 +362,10 @@ static u8 symbol__parent_filter(const struct symbol *parent)
362 return 0; 362 return 0;
363} 363}
364 364
365static struct hist_entry *add_hist_entry(struct hists *hists, 365static struct hist_entry *hists__findnew_entry(struct hists *hists,
366 struct hist_entry *entry, 366 struct hist_entry *entry,
367 struct addr_location *al, 367 struct addr_location *al,
368 bool sample_self) 368 bool sample_self)
369{ 369{
370 struct rb_node **p; 370 struct rb_node **p;
371 struct rb_node *parent = NULL; 371 struct rb_node *parent = NULL;
@@ -468,7 +468,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
468 .transaction = transaction, 468 .transaction = transaction,
469 }; 469 };
470 470
471 return add_hist_entry(hists, &entry, al, sample_self); 471 return hists__findnew_entry(hists, &entry, al, sample_self);
472} 472}
473 473
474static int 474static int
@@ -548,9 +548,9 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
548 548
549out: 549out:
550 /* 550 /*
551 * We don't need to free iter->priv (mem_info) here since 551 * We don't need to free iter->priv (mem_info) here since the mem info
552 * the mem info was either already freed in add_hist_entry() or 552 * was either already freed in hists__findnew_entry() or passed to a
553 * passed to a new hist entry by hist_entry__new(). 553 * new hist entry by hist_entry__new().
554 */ 554 */
555 iter->priv = NULL; 555 iter->priv = NULL;
556 556
@@ -851,19 +851,15 @@ const struct hist_iter_ops hist_iter_cumulative = {
851}; 851};
852 852
853int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 853int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
854 struct perf_evsel *evsel, struct perf_sample *sample,
855 int max_stack_depth, void *arg) 854 int max_stack_depth, void *arg)
856{ 855{
857 int err, err2; 856 int err, err2;
858 857
859 err = sample__resolve_callchain(sample, &iter->parent, evsel, al, 858 err = sample__resolve_callchain(iter->sample, &iter->parent,
860 max_stack_depth); 859 iter->evsel, al, max_stack_depth);
861 if (err) 860 if (err)
862 return err; 861 return err;
863 862
864 iter->evsel = evsel;
865 iter->sample = sample;
866
867 err = iter->ops->prepare_entry(iter, al); 863 err = iter->ops->prepare_entry(iter, al);
868 if (err) 864 if (err)
869 goto out; 865 goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 9f31b89a527a..5ed8d9c22981 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -111,7 +111,6 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
111 u64 weight, u64 transaction, 111 u64 weight, u64 transaction,
112 bool sample_self); 112 bool sample_self);
113int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 113int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
114 struct perf_evsel *evsel, struct perf_sample *sample,
115 int max_stack_depth, void *arg); 114 int max_stack_depth, void *arg);
116 115
117int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 116int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
index 2a030c5af3aa..f06d89f0b867 100644
--- a/tools/perf/util/include/linux/rbtree.h
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -1,2 +1,16 @@
1#ifndef __TOOLS_LINUX_PERF_RBTREE_H
2#define __TOOLS_LINUX_PERF_RBTREE_H
1#include <stdbool.h> 3#include <stdbool.h>
2#include "../../../../include/linux/rbtree.h" 4#include "../../../../include/linux/rbtree.h"
5
6/*
7 * Handy for checking that we are not deleting an entry that is
8 * already in a list, found in block/{blk-throttle,cfq-iosched}.c,
9 * probably should be moved to lib/rbtree.c...
10 */
11static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)
12{
13 rb_erase(n, root);
14 RB_CLEAR_NODE(n);
15}
16#endif /* __TOOLS_LINUX_PERF_RBTREE_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index daa55910ff28..6bf845758ae3 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -333,7 +333,7 @@ static void machine__update_thread_pid(struct machine *machine,
333 if (!map_groups__empty(th->mg)) 333 if (!map_groups__empty(th->mg))
334 pr_err("Discarding thread maps for %d:%d\n", 334 pr_err("Discarding thread maps for %d:%d\n",
335 th->pid_, th->tid); 335 th->pid_, th->tid);
336 map_groups__delete(th->mg); 336 map_groups__put(th->mg);
337 } 337 }
338 338
339 th->mg = map_groups__get(leader->mg); 339 th->mg = map_groups__get(leader->mg);
@@ -400,7 +400,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
400 * leader and that would screwed the rb tree. 400 * leader and that would screwed the rb tree.
401 */ 401 */
402 if (thread__init_map_groups(th, machine)) { 402 if (thread__init_map_groups(th, machine)) {
403 rb_erase(&th->rb_node, &machine->threads); 403 rb_erase_init(&th->rb_node, &machine->threads);
404 RB_CLEAR_NODE(&th->rb_node); 404 RB_CLEAR_NODE(&th->rb_node);
405 thread__delete(th); 405 thread__delete(th);
406 return NULL; 406 return NULL;
@@ -1314,7 +1314,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1314 BUG_ON(atomic_read(&th->refcnt) == 0); 1314 BUG_ON(atomic_read(&th->refcnt) == 0);
1315 if (lock) 1315 if (lock)
1316 pthread_rwlock_wrlock(&machine->threads_lock); 1316 pthread_rwlock_wrlock(&machine->threads_lock);
1317 rb_erase(&th->rb_node, &machine->threads); 1317 rb_erase_init(&th->rb_node, &machine->threads);
1318 RB_CLEAR_NODE(&th->rb_node); 1318 RB_CLEAR_NODE(&th->rb_node);
1319 /* 1319 /*
1320 * Move it first to the dead_threads list, then drop the reference, 1320 * Move it first to the dead_threads list, then drop the reference,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2d20c5ff8653..898ab92a98dd 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -498,28 +498,6 @@ void map_groups__put(struct map_groups *mg)
498 map_groups__delete(mg); 498 map_groups__delete(mg);
499} 499}
500 500
501void map_groups__flush(struct map_groups *mg)
502{
503 int type;
504
505 for (type = 0; type < MAP__NR_TYPES; type++) {
506 struct rb_root *root = &mg->maps[type];
507 struct rb_node *next = rb_first(root);
508
509 while (next) {
510 struct map *pos = rb_entry(next, struct map, rb_node);
511 next = rb_next(&pos->rb_node);
512 rb_erase(&pos->rb_node, root);
513 /*
514 * We may have references to this map, for
515 * instance in some hist_entry instances, so
516 * just move them to a separate list.
517 */
518 list_add_tail(&pos->node, &mg->removed_maps[pos->type]);
519 }
520 }
521}
522
523struct symbol *map_groups__find_symbol(struct map_groups *mg, 501struct symbol *map_groups__find_symbol(struct map_groups *mg,
524 enum map_type type, u64 addr, 502 enum map_type type, u64 addr,
525 struct map **mapp, 503 struct map **mapp,
@@ -710,9 +688,10 @@ move_map:
710int map_groups__clone(struct map_groups *mg, 688int map_groups__clone(struct map_groups *mg,
711 struct map_groups *parent, enum map_type type) 689 struct map_groups *parent, enum map_type type)
712{ 690{
713 struct rb_node *nd; 691 struct map *map;
714 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { 692 struct rb_root *maps = &parent->maps[type];
715 struct map *map = rb_entry(nd, struct map, rb_node); 693
694 for (map = maps__first(maps); map; map = map__next(map)) {
716 struct map *new = map__clone(map); 695 struct map *new = map__clone(map);
717 if (new == NULL) 696 if (new == NULL)
718 return -ENOMEM; 697 return -ENOMEM;
@@ -775,7 +754,7 @@ struct map *maps__first(struct rb_root *maps)
775 return NULL; 754 return NULL;
776} 755}
777 756
778struct map *maps__next(struct map *map) 757struct map *map__next(struct map *map)
779{ 758{
780 struct rb_node *next = rb_next(&map->rb_node); 759 struct rb_node *next = rb_next(&map->rb_node);
781 760
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7f39217d29bf..f2b27566d986 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -166,7 +166,7 @@ void maps__insert(struct rb_root *maps, struct map *map);
166void maps__remove(struct rb_root *maps, struct map *map); 166void maps__remove(struct rb_root *maps, struct map *map);
167struct map *maps__find(struct rb_root *maps, u64 addr); 167struct map *maps__find(struct rb_root *maps, u64 addr);
168struct map *maps__first(struct rb_root *maps); 168struct map *maps__first(struct rb_root *maps);
169struct map *maps__next(struct map *map); 169struct map *map__next(struct map *map);
170void map_groups__init(struct map_groups *mg, struct machine *machine); 170void map_groups__init(struct map_groups *mg, struct machine *machine);
171void map_groups__exit(struct map_groups *mg); 171void map_groups__exit(struct map_groups *mg);
172int map_groups__clone(struct map_groups *mg, 172int map_groups__clone(struct map_groups *mg,
@@ -201,7 +201,7 @@ static inline struct map *map_groups__first(struct map_groups *mg,
201 201
202static inline struct map *map_groups__next(struct map *map) 202static inline struct map *map_groups__next(struct map *map)
203{ 203{
204 return maps__next(map); 204 return map__next(map);
205} 205}
206 206
207struct symbol *map_groups__find_symbol(struct map_groups *mg, 207struct symbol *map_groups__find_symbol(struct map_groups *mg,
@@ -233,6 +233,4 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
233struct map *map_groups__find_by_name(struct map_groups *mg, 233struct map *map_groups__find_by_name(struct map_groups *mg,
234 enum map_type type, const char *name); 234 enum map_type type, const char *name);
235 235
236void map_groups__flush(struct map_groups *mg);
237
238#endif /* __PERF_MAP_H */ 236#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 80a50fdb6d8a..2a4d1ec02846 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -25,12 +25,6 @@
25extern int parse_events_debug; 25extern int parse_events_debug;
26#endif 26#endif
27int parse_events_parse(void *data, void *scanner); 27int parse_events_parse(void *data, void *scanner);
28int parse_events_term__num(struct parse_events_term **term,
29 int type_term, char *config, u64 num,
30 YYLTYPE *loc_term, YYLTYPE *loc_val);
31int parse_events_term__str(struct parse_events_term **term,
32 int type_term, char *config, char *str,
33 YYLTYPE *loc_term, YYLTYPE *loc_val);
34 28
35static struct perf_pmu_event_symbol *perf_pmu_events_list; 29static struct perf_pmu_event_symbol *perf_pmu_events_list;
36/* 30/*
@@ -1601,8 +1595,11 @@ static int new_term(struct parse_events_term **_term, int type_val,
1601 1595
1602int parse_events_term__num(struct parse_events_term **term, 1596int parse_events_term__num(struct parse_events_term **term,
1603 int type_term, char *config, u64 num, 1597 int type_term, char *config, u64 num,
1604 YYLTYPE *loc_term, YYLTYPE *loc_val) 1598 void *loc_term_, void *loc_val_)
1605{ 1599{
1600 YYLTYPE *loc_term = loc_term_;
1601 YYLTYPE *loc_val = loc_val_;
1602
1606 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1603 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1607 config, NULL, num, 1604 config, NULL, num,
1608 loc_term ? loc_term->first_column : 0, 1605 loc_term ? loc_term->first_column : 0,
@@ -1611,8 +1608,11 @@ int parse_events_term__num(struct parse_events_term **term,
1611 1608
1612int parse_events_term__str(struct parse_events_term **term, 1609int parse_events_term__str(struct parse_events_term **term,
1613 int type_term, char *config, char *str, 1610 int type_term, char *config, char *str,
1614 YYLTYPE *loc_term, YYLTYPE *loc_val) 1611 void *loc_term_, void *loc_val_)
1615{ 1612{
1613 YYLTYPE *loc_term = loc_term_;
1614 YYLTYPE *loc_val = loc_val_;
1615
1616 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, 1616 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
1617 config, str, 0, 1617 config, str, 0,
1618 loc_term ? loc_term->first_column : 0, 1618 loc_term ? loc_term->first_column : 0,
@@ -1659,6 +1659,8 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
1659{ 1659{
1660 struct parse_events_error *err = data->error; 1660 struct parse_events_error *err = data->error;
1661 1661
1662 if (!err)
1663 return;
1662 err->idx = idx; 1664 err->idx = idx;
1663 err->str = strdup(str); 1665 err->str = strdup(str);
1664 WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); 1666 WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e236f1b6ac6f..131f29b2f132 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -98,6 +98,12 @@ struct parse_events_terms {
98}; 98};
99 99
100int parse_events__is_hardcoded_term(struct parse_events_term *term); 100int parse_events__is_hardcoded_term(struct parse_events_term *term);
101int parse_events_term__num(struct parse_events_term **term,
102 int type_term, char *config, u64 num,
103 void *loc_term, void *loc_val);
104int parse_events_term__str(struct parse_events_term **term,
105 int type_term, char *config, char *str,
106 void *loc_term, void *loc_val);
101int parse_events_term__sym_hw(struct parse_events_term **term, 107int parse_events_term__sym_hw(struct parse_events_term **term,
102 char *config, unsigned idx); 108 char *config, unsigned idx);
103int parse_events_term__clone(struct parse_events_term **new, 109int parse_events_term__clone(struct parse_events_term **new,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 3d11e00243e3..591905a02b92 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -389,8 +389,10 @@ PE_NAME ':' PE_NAME
389 if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) { 389 if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
390 struct parse_events_error *error = data->error; 390 struct parse_events_error *error = data->error;
391 391
392 error->idx = @1.first_column; 392 if (error) {
393 error->str = strdup("unknown tracepoint"); 393 error->idx = @1.first_column;
394 error->str = strdup("unknown tracepoint");
395 }
394 return -1; 396 return -1;
395 } 397 }
396 $$ = list; 398 $$ = list;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 244c66f89891..5d3ab7c8ceaf 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -442,6 +442,10 @@ static struct perf_pmu *pmu_lookup(const char *name)
442 LIST_HEAD(aliases); 442 LIST_HEAD(aliases);
443 __u32 type; 443 __u32 type;
444 444
445 /* No support for intel_bts or intel_pt so disallow them */
446 if (!strcmp(name, "intel_bts") || !strcmp(name, "intel_pt"))
447 return NULL;
448
445 /* 449 /*
446 * The pmu data we store & need consists of the pmu 450 * The pmu data we store & need consists of the pmu
447 * type value and format definitions. Load both right 451 * type value and format definitions. Load both right
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 1faa1e67398b..97da98481d89 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -162,8 +162,9 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
162 162
163static struct map *kernel_get_module_map(const char *module) 163static struct map *kernel_get_module_map(const char *module)
164{ 164{
165 struct rb_node *nd;
166 struct map_groups *grp = &host_machine->kmaps; 165 struct map_groups *grp = &host_machine->kmaps;
166 struct rb_root *maps = &grp->maps[MAP__FUNCTION];
167 struct map *pos;
167 168
168 /* A file path -- this is an offline module */ 169 /* A file path -- this is an offline module */
169 if (module && strchr(module, '/')) 170 if (module && strchr(module, '/'))
@@ -172,8 +173,7 @@ static struct map *kernel_get_module_map(const char *module)
172 if (!module) 173 if (!module)
173 module = "kernel"; 174 module = "kernel";
174 175
175 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 176 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
176 struct map *pos = rb_entry(nd, struct map, rb_node);
177 if (strncmp(pos->dso->short_name + 1, module, 177 if (strncmp(pos->dso->short_name + 1, module,
178 pos->dso->short_name_len - 2) == 0) { 178 pos->dso->short_name_len - 2) == 0) {
179 return pos; 179 return pos;
@@ -195,17 +195,17 @@ static void put_target_map(struct map *map, bool user)
195{ 195{
196 if (map && user) { 196 if (map && user) {
197 /* Only the user map needs to be released */ 197 /* Only the user map needs to be released */
198 dso__delete(map->dso);
199 map__delete(map); 198 map__delete(map);
200 } 199 }
201} 200}
202 201
203 202
204static struct dso *kernel_get_module_dso(const char *module) 203static int kernel_get_module_dso(const char *module, struct dso **pdso)
205{ 204{
206 struct dso *dso; 205 struct dso *dso;
207 struct map *map; 206 struct map *map;
208 const char *vmlinux_name; 207 const char *vmlinux_name;
208 int ret = 0;
209 209
210 if (module) { 210 if (module) {
211 list_for_each_entry(dso, &host_machine->kernel_dsos.head, 211 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
@@ -215,30 +215,21 @@ static struct dso *kernel_get_module_dso(const char *module)
215 goto found; 215 goto found;
216 } 216 }
217 pr_debug("Failed to find module %s.\n", module); 217 pr_debug("Failed to find module %s.\n", module);
218 return NULL; 218 return -ENOENT;
219 } 219 }
220 220
221 map = host_machine->vmlinux_maps[MAP__FUNCTION]; 221 map = host_machine->vmlinux_maps[MAP__FUNCTION];
222 dso = map->dso; 222 dso = map->dso;
223 223
224 vmlinux_name = symbol_conf.vmlinux_name; 224 vmlinux_name = symbol_conf.vmlinux_name;
225 if (vmlinux_name) { 225 dso->load_errno = 0;
226 if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0) 226 if (vmlinux_name)
227 return NULL; 227 ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL);
228 } else { 228 else
229 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 229 ret = dso__load_vmlinux_path(dso, map, NULL);
230 pr_debug("Failed to load kernel map.\n");
231 return NULL;
232 }
233 }
234found: 230found:
235 return dso; 231 *pdso = dso;
236} 232 return ret;
237
238const char *kernel_get_module_path(const char *module)
239{
240 struct dso *dso = kernel_get_module_dso(module);
241 return (dso) ? dso->long_name : NULL;
242} 233}
243 234
244static int convert_exec_to_group(const char *exec, char **result) 235static int convert_exec_to_group(const char *exec, char **result)
@@ -390,16 +381,25 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
390static struct debuginfo *open_debuginfo(const char *module, bool silent) 381static struct debuginfo *open_debuginfo(const char *module, bool silent)
391{ 382{
392 const char *path = module; 383 const char *path = module;
393 struct debuginfo *ret; 384 char reason[STRERR_BUFSIZE];
385 struct debuginfo *ret = NULL;
386 struct dso *dso = NULL;
387 int err;
394 388
395 if (!module || !strchr(module, '/')) { 389 if (!module || !strchr(module, '/')) {
396 path = kernel_get_module_path(module); 390 err = kernel_get_module_dso(module, &dso);
397 if (!path) { 391 if (err < 0) {
392 if (!dso || dso->load_errno == 0) {
393 if (!strerror_r(-err, reason, STRERR_BUFSIZE))
394 strcpy(reason, "(unknown)");
395 } else
396 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
398 if (!silent) 397 if (!silent)
399 pr_err("Failed to find path of %s module.\n", 398 pr_err("Failed to find the path for %s: %s\n",
400 module ?: "kernel"); 399 module ?: "kernel", reason);
401 return NULL; 400 return NULL;
402 } 401 }
402 path = dso->long_name;
403 } 403 }
404 ret = debuginfo__new(path); 404 ret = debuginfo__new(path);
405 if (!ret && !silent) { 405 if (!ret && !silent) {
@@ -1791,7 +1791,6 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1791 1791
1792out: 1792out:
1793 if (map && !is_kprobe) { 1793 if (map && !is_kprobe) {
1794 dso__delete(map->dso);
1795 map__delete(map); 1794 map__delete(map);
1796 } 1795 }
1797 1796
@@ -2812,13 +2811,14 @@ int del_perf_probe_events(struct strfilter *filter)
2812 goto error; 2811 goto error;
2813 2812
2814 ret2 = del_trace_probe_events(ufd, filter, unamelist); 2813 ret2 = del_trace_probe_events(ufd, filter, unamelist);
2815 if (ret2 < 0 && ret2 != -ENOENT) 2814 if (ret2 < 0 && ret2 != -ENOENT) {
2816 ret = ret2; 2815 ret = ret2;
2817 else if (ret == -ENOENT && ret2 == -ENOENT) { 2816 goto error;
2817 }
2818 if (ret == -ENOENT && ret2 == -ENOENT)
2818 pr_debug("\"%s\" does not hit any event.\n", str); 2819 pr_debug("\"%s\" does not hit any event.\n", str);
2819 /* Note that this is silently ignored */ 2820 /* Note that this is silently ignored */
2820 ret = 0; 2821 ret = 0;
2821 }
2822 2822
2823error: 2823error:
2824 if (kfd >= 0) { 2824 if (kfd >= 0) {
@@ -2884,7 +2884,6 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2884 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2884 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2885end: 2885end:
2886 if (user) { 2886 if (user) {
2887 dso__delete(map->dso);
2888 map__delete(map); 2887 map__delete(map);
2889 } 2888 }
2890 exit_symbol_maps(); 2889 exit_symbol_maps();
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 537eb329c2cf..31db6ee7db54 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -131,9 +131,6 @@ extern void line_range__clear(struct line_range *lr);
131/* Initialize line range */ 131/* Initialize line range */
132extern int line_range__init(struct line_range *lr); 132extern int line_range__init(struct line_range *lr);
133 133
134/* Internal use: Return kernel/module path */
135extern const char *kernel_get_module_path(const char *module);
136
137extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); 134extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
138extern int del_perf_probe_events(struct strfilter *filter); 135extern int del_perf_probe_events(struct strfilter *filter);
139extern int show_perf_probe_events(struct strfilter *filter); 136extern int show_perf_probe_events(struct strfilter *filter);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e722107f932a..39fe09d5a87e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1182,7 +1182,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1182 return -1; 1182 return -1;
1183 1183
1184 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || 1184 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
1185 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz) 1185 readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz)
1186 return -1; 1186 return -1;
1187 1187
1188 event = (union perf_event *)buf; 1188 event = (union perf_event *)buf;
@@ -1190,12 +1190,12 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1190 if (session->header.needs_swap) 1190 if (session->header.needs_swap)
1191 perf_event_header__bswap(&event->header); 1191 perf_event_header__bswap(&event->header);
1192 1192
1193 if (event->header.size < hdr_sz) 1193 if (event->header.size < hdr_sz || event->header.size > buf_sz)
1194 return -1; 1194 return -1;
1195 1195
1196 rest = event->header.size - hdr_sz; 1196 rest = event->header.size - hdr_sz;
1197 1197
1198 if (readn(fd, &buf, rest) != (ssize_t)rest) 1198 if (readn(fd, buf, rest) != (ssize_t)rest)
1199 return -1; 1199 return -1;
1200 1200
1201 if (session->header.needs_swap) 1201 if (session->header.needs_swap)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 82a31fd0fcf5..b9e3eb581884 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -202,18 +202,16 @@ void symbols__fixup_end(struct rb_root *symbols)
202 202
203void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 203void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
204{ 204{
205 struct map *prev, *curr; 205 struct rb_root *maps = &mg->maps[type];
206 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 206 struct map *next, *curr;
207 207
208 if (prevnd == NULL) 208 curr = maps__first(maps);
209 if (curr == NULL)
209 return; 210 return;
210 211
211 curr = rb_entry(prevnd, struct map, rb_node); 212 for (next = map__next(curr); next; next = map__next(curr)) {
212 213 curr->end = next->start;
213 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 214 curr = next;
214 prev = curr;
215 curr = rb_entry(nd, struct map, rb_node);
216 prev->end = curr->start;
217 } 215 }
218 216
219 /* 217 /*
@@ -400,7 +398,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
400 const char *name) 398 const char *name)
401{ 399{
402 struct rb_node *n; 400 struct rb_node *n;
403 struct symbol_name_rb_node *s; 401 struct symbol_name_rb_node *s = NULL;
404 402
405 if (symbols == NULL) 403 if (symbols == NULL)
406 return NULL; 404 return NULL;
@@ -1522,11 +1520,10 @@ out:
1522struct map *map_groups__find_by_name(struct map_groups *mg, 1520struct map *map_groups__find_by_name(struct map_groups *mg,
1523 enum map_type type, const char *name) 1521 enum map_type type, const char *name)
1524{ 1522{
1525 struct rb_node *nd; 1523 struct rb_root *maps = &mg->maps[type];
1526 1524 struct map *map;
1527 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
1528 struct map *map = rb_entry(nd, struct map, rb_node);
1529 1525
1526 for (map = maps__first(maps); map; map = map__next(map)) {
1530 if (map->dso && strcmp(map->dso->short_name, name) == 0) 1527 if (map->dso && strcmp(map->dso->short_name, name) == 0)
1531 return map; 1528 return map;
1532 } 1529 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 16c28a37a9e4..28c4b746baa1 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -54,7 +54,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)
54 54
55 list_add(&comm->list, &thread->comm_list); 55 list_add(&comm->list, &thread->comm_list);
56 atomic_set(&thread->refcnt, 0); 56 atomic_set(&thread->refcnt, 0);
57 INIT_LIST_HEAD(&thread->node);
58 RB_CLEAR_NODE(&thread->rb_node); 57 RB_CLEAR_NODE(&thread->rb_node);
59 } 58 }
60 59
@@ -70,7 +69,6 @@ void thread__delete(struct thread *thread)
70 struct comm *comm, *tmp; 69 struct comm *comm, *tmp;
71 70
72 BUG_ON(!RB_EMPTY_NODE(&thread->rb_node)); 71 BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
73 BUG_ON(!list_empty(&thread->node));
74 72
75 thread_stack__free(thread); 73 thread_stack__free(thread);
76 74
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 25d6c737be3e..d4957418657e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -173,7 +173,7 @@ void parse_ftrace_printk(struct pevent *pevent,
173 char *line; 173 char *line;
174 char *next = NULL; 174 char *next = NULL;
175 char *addr_str; 175 char *addr_str;
176 char *fmt; 176 char *fmt = NULL;
177 177
178 line = strtok_r(file, "\n", &next); 178 line = strtok_r(file, "\n", &next);
179 while (line) { 179 while (line) {
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 7b09a443a280..f079b63f0b7f 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -269,13 +269,14 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
269 u64 offset = dso->data.eh_frame_hdr_offset; 269 u64 offset = dso->data.eh_frame_hdr_offset;
270 270
271 if (offset == 0) { 271 if (offset == 0) {
272 fd = dso__data_fd(dso, machine); 272 fd = dso__data_get_fd(dso, machine);
273 if (fd < 0) 273 if (fd < 0)
274 return -EINVAL; 274 return -EINVAL;
275 275
276 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
277 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.eh_frame_hdr_offset = offset; 278 dso->data.eh_frame_hdr_offset = offset;
279 dso__data_put_fd(dso);
279 } 280 }
280 281
281 if (offset) 282 if (offset)
@@ -294,13 +295,14 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
294 u64 ofs = dso->data.debug_frame_offset; 295 u64 ofs = dso->data.debug_frame_offset;
295 296
296 if (ofs == 0) { 297 if (ofs == 0) {
297 fd = dso__data_fd(dso, machine); 298 fd = dso__data_get_fd(dso, machine);
298 if (fd < 0) 299 if (fd < 0)
299 return -EINVAL; 300 return -EINVAL;
300 301
301 /* Check the .debug_frame section for unwinding info */ 302 /* Check the .debug_frame section for unwinding info */
302 ofs = elf_section_offset(fd, ".debug_frame"); 303 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.debug_frame_offset = ofs; 304 dso->data.debug_frame_offset = ofs;
305 dso__data_put_fd(dso);
304 } 306 }
305 307
306 *offset = ofs; 308 *offset = ofs;
@@ -353,10 +355,13 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
353#ifndef NO_LIBUNWIND_DEBUG_FRAME 355#ifndef NO_LIBUNWIND_DEBUG_FRAME
354 /* Check the .debug_frame section for unwinding info */ 356 /* Check the .debug_frame section for unwinding info */
355 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 357 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
356 int fd = dso__data_fd(map->dso, ui->machine); 358 int fd = dso__data_get_fd(map->dso, ui->machine);
357 int is_exec = elf_is_exec(fd, map->dso->name); 359 int is_exec = elf_is_exec(fd, map->dso->name);
358 unw_word_t base = is_exec ? 0 : map->start; 360 unw_word_t base = is_exec ? 0 : map->start;
359 361
362 if (fd >= 0)
363 dso__data_put_fd(dso);
364
360 memset(&di, 0, sizeof(di)); 365 memset(&di, 0, sizeof(di));
361 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, 366 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name,
362 map->start, map->end)) 367 map->start, map->end))