diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-top.c | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 12e2e1227e47..b1cb5f589ade 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -196,6 +196,12 @@ static void perf_top__record_precise_ip(struct perf_top *top, | |||
196 | 196 | ||
197 | pthread_mutex_unlock(¬es->lock); | 197 | pthread_mutex_unlock(¬es->lock); |
198 | 198 | ||
199 | /* | ||
200 | * This function is now called with he->hists->lock held. | ||
201 | * Release it before going to sleep. | ||
202 | */ | ||
203 | pthread_mutex_unlock(&he->hists->lock); | ||
204 | |||
199 | if (err == -ERANGE && !he->ms.map->erange_warned) | 205 | if (err == -ERANGE && !he->ms.map->erange_warned) |
200 | ui__warn_map_erange(he->ms.map, sym, ip); | 206 | ui__warn_map_erange(he->ms.map, sym, ip); |
201 | else if (err == -ENOMEM) { | 207 | else if (err == -ENOMEM) { |
@@ -203,6 +209,8 @@ static void perf_top__record_precise_ip(struct perf_top *top, | |||
203 | sym->name); | 209 | sym->name); |
204 | sleep(1); | 210 | sleep(1); |
205 | } | 211 | } |
212 | |||
213 | pthread_mutex_lock(&he->hists->lock); | ||
206 | } | 214 | } |
207 | 215 | ||
208 | static void perf_top__show_details(struct perf_top *top) | 216 | static void perf_top__show_details(struct perf_top *top) |
@@ -238,24 +246,6 @@ out_unlock: | |||
238 | pthread_mutex_unlock(¬es->lock); | 246 | pthread_mutex_unlock(¬es->lock); |
239 | } | 247 | } |
240 | 248 | ||
241 | static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, | ||
242 | struct addr_location *al, | ||
243 | struct perf_sample *sample) | ||
244 | { | ||
245 | struct hist_entry *he; | ||
246 | |||
247 | pthread_mutex_lock(&evsel->hists.lock); | ||
248 | he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, | ||
249 | sample->period, sample->weight, | ||
250 | sample->transaction, true); | ||
251 | pthread_mutex_unlock(&evsel->hists.lock); | ||
252 | if (he == NULL) | ||
253 | return NULL; | ||
254 | |||
255 | hists__inc_nr_samples(&evsel->hists, he->filtered); | ||
256 | return he; | ||
257 | } | ||
258 | |||
259 | static void perf_top__print_sym_table(struct perf_top *top) | 249 | static void perf_top__print_sym_table(struct perf_top *top) |
260 | { | 250 | { |
261 | char bf[160]; | 251 | char bf[160]; |
@@ -659,6 +649,26 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) | |||
659 | return 0; | 649 | return 0; |
660 | } | 650 | } |
661 | 651 | ||
652 | static int hist_iter__top_callback(struct hist_entry_iter *iter, | ||
653 | struct addr_location *al, bool single, | ||
654 | void *arg) | ||
655 | { | ||
656 | struct perf_top *top = arg; | ||
657 | struct hist_entry *he = iter->he; | ||
658 | struct perf_evsel *evsel = iter->evsel; | ||
659 | |||
660 | if (sort__has_sym && single) { | ||
661 | u64 ip = al->addr; | ||
662 | |||
663 | if (al->map) | ||
664 | ip = al->map->unmap_ip(al->map, ip); | ||
665 | |||
666 | perf_top__record_precise_ip(top, he, evsel->idx, ip); | ||
667 | } | ||
668 | |||
669 | return 0; | ||
670 | } | ||
671 | |||
662 | static void perf_event__process_sample(struct perf_tool *tool, | 672 | static void perf_event__process_sample(struct perf_tool *tool, |
663 | const union perf_event *event, | 673 | const union perf_event *event, |
664 | struct perf_evsel *evsel, | 674 | struct perf_evsel *evsel, |
@@ -666,8 +676,6 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
666 | struct machine *machine) | 676 | struct machine *machine) |
667 | { | 677 | { |
668 | struct perf_top *top = container_of(tool, struct perf_top, tool); | 678 | struct perf_top *top = container_of(tool, struct perf_top, tool); |
669 | struct symbol *parent = NULL; | ||
670 | u64 ip = sample->ip; | ||
671 | struct addr_location al; | 679 | struct addr_location al; |
672 | int err; | 680 | int err; |
673 | 681 | ||
@@ -742,25 +750,23 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
742 | } | 750 | } |
743 | 751 | ||
744 | if (al.sym == NULL || !al.sym->ignore) { | 752 | if (al.sym == NULL || !al.sym->ignore) { |
745 | struct hist_entry *he; | 753 | struct hist_entry_iter iter = { |
754 | .add_entry_cb = hist_iter__top_callback, | ||
755 | }; | ||
746 | 756 | ||
747 | err = sample__resolve_callchain(sample, &parent, evsel, &al, | 757 | if (symbol_conf.cumulate_callchain) |
748 | top->max_stack); | 758 | iter.ops = &hist_iter_cumulative; |
749 | if (err) | 759 | else |
750 | return; | 760 | iter.ops = &hist_iter_normal; |
751 | 761 | ||
752 | he = perf_evsel__add_hist_entry(evsel, &al, sample); | 762 | pthread_mutex_lock(&evsel->hists.lock); |
753 | if (he == NULL) { | ||
754 | pr_err("Problem incrementing symbol period, skipping event\n"); | ||
755 | return; | ||
756 | } | ||
757 | 763 | ||
758 | err = hist_entry__append_callchain(he, sample); | 764 | err = hist_entry_iter__add(&iter, &al, evsel, sample, |
759 | if (err) | 765 | top->max_stack, top); |
760 | return; | 766 | if (err < 0) |
767 | pr_err("Problem incrementing symbol period, skipping event\n"); | ||
761 | 768 | ||
762 | if (sort__has_sym) | 769 | pthread_mutex_unlock(&evsel->hists.lock); |
763 | perf_top__record_precise_ip(top, he, evsel->idx, ip); | ||
764 | } | 770 | } |
765 | 771 | ||
766 | return; | 772 | return; |