aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c90
1 files changed, 52 insertions, 38 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5b389ce4cd15..377971dc89a3 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(&notes->lock); 197 pthread_mutex_unlock(&notes->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
208static void perf_top__show_details(struct perf_top *top) 216static void perf_top__show_details(struct perf_top *top)
@@ -238,27 +246,6 @@ out_unlock:
238 pthread_mutex_unlock(&notes->lock); 246 pthread_mutex_unlock(&notes->lock);
239} 247}
240 248
241static 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);
251 pthread_mutex_unlock(&evsel->hists.lock);
252 if (he == NULL)
253 return NULL;
254
255 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
256 if (!he->filtered)
257 evsel->hists.stats.nr_non_filtered_samples++;
258
259 return he;
260}
261
262static void perf_top__print_sym_table(struct perf_top *top) 249static void perf_top__print_sym_table(struct perf_top *top)
263{ 250{
264 char bf[160]; 251 char bf[160];
@@ -662,6 +649,26 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
662 return 0; 649 return 0;
663} 650}
664 651
652static 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
665static void perf_event__process_sample(struct perf_tool *tool, 672static void perf_event__process_sample(struct perf_tool *tool,
666 const union perf_event *event, 673 const union perf_event *event,
667 struct perf_evsel *evsel, 674 struct perf_evsel *evsel,
@@ -669,8 +676,6 @@ static void perf_event__process_sample(struct perf_tool *tool,
669 struct machine *machine) 676 struct machine *machine)
670{ 677{
671 struct perf_top *top = container_of(tool, struct perf_top, tool); 678 struct perf_top *top = container_of(tool, struct perf_top, tool);
672 struct symbol *parent = NULL;
673 u64 ip = sample->ip;
674 struct addr_location al; 679 struct addr_location al;
675 int err; 680 int err;
676 681
@@ -745,25 +750,23 @@ static void perf_event__process_sample(struct perf_tool *tool,
745 } 750 }
746 751
747 if (al.sym == NULL || !al.sym->ignore) { 752 if (al.sym == NULL || !al.sym->ignore) {
748 struct hist_entry *he; 753 struct hist_entry_iter iter = {
754 .add_entry_cb = hist_iter__top_callback,
755 };
749 756
750 err = sample__resolve_callchain(sample, &parent, evsel, &al, 757 if (symbol_conf.cumulate_callchain)
751 top->max_stack); 758 iter.ops = &hist_iter_cumulative;
752 if (err) 759 else
753 return; 760 iter.ops = &hist_iter_normal;
754 761
755 he = perf_evsel__add_hist_entry(evsel, &al, sample); 762 pthread_mutex_lock(&evsel->hists.lock);
756 if (he == NULL) {
757 pr_err("Problem incrementing symbol period, skipping event\n");
758 return;
759 }
760 763
761 err = hist_entry__append_callchain(he, sample); 764 err = hist_entry_iter__add(&iter, &al, evsel, sample,
762 if (err) 765 top->max_stack, top);
763 return; 766 if (err < 0)
767 pr_err("Problem incrementing symbol period, skipping event\n");
764 768
765 if (sort__has_sym) 769 pthread_mutex_unlock(&evsel->hists.lock);
766 perf_top__record_precise_ip(top, he, evsel->idx, ip);
767 } 770 }
768 771
769 return; 772 return;
@@ -1001,6 +1004,10 @@ static int perf_top_config(const char *var, const char *value, void *cb)
1001 1004
1002 if (!strcmp(var, "top.call-graph")) 1005 if (!strcmp(var, "top.call-graph"))
1003 return record_parse_callchain(value, &top->record_opts); 1006 return record_parse_callchain(value, &top->record_opts);
1007 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0;
1010 }
1004 1011
1005 return perf_default_config(var, value, cb); 1012 return perf_default_config(var, value, cb);
1006} 1013}
@@ -1095,6 +1102,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1095 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1102 OPT_CALLBACK(0, "call-graph", &top.record_opts,
1096 "mode[,dump_size]", record_callchain_help, 1103 "mode[,dump_size]", record_callchain_help,
1097 &parse_callchain_opt), 1104 &parse_callchain_opt),
1105 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1106 "Accumulate callchains of children and show total overhead as well"),
1098 OPT_INTEGER(0, "max-stack", &top.max_stack, 1107 OPT_INTEGER(0, "max-stack", &top.max_stack,
1099 "Set the maximum stack depth when parsing the callchain. " 1108 "Set the maximum stack depth when parsing the callchain. "
1100 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 1109 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
@@ -1200,6 +1209,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1200 1209
1201 top.sym_evsel = perf_evlist__first(top.evlist); 1210 top.sym_evsel = perf_evlist__first(top.evlist);
1202 1211
1212 if (!symbol_conf.use_callchain) {
1213 symbol_conf.cumulate_callchain = false;
1214 perf_hpp__cancel_cumulate();
1215 }
1216
1203 symbol_conf.priv_size = sizeof(struct annotation); 1217 symbol_conf.priv_size = sizeof(struct annotation);
1204 1218
1205 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);