forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/tools/perf/ui/browsers/hists.c
....@@ -6,17 +6,31 @@
66 #include <stdlib.h>
77 #include <string.h>
88 #include <linux/rbtree.h>
9
+#include <linux/string.h>
910 #include <sys/ttydefaults.h>
11
+#include <linux/time64.h>
12
+#include <linux/zalloc.h>
1013
14
+#include "../../util/debug.h"
15
+#include "../../util/dso.h"
16
+#include "../../util/callchain.h"
1117 #include "../../util/evsel.h"
1218 #include "../../util/evlist.h"
19
+#include "../../util/header.h"
1320 #include "../../util/hist.h"
21
+#include "../../util/machine.h"
22
+#include "../../util/map.h"
23
+#include "../../util/maps.h"
24
+#include "../../util/symbol.h"
25
+#include "../../util/map_symbol.h"
26
+#include "../../util/branch.h"
1427 #include "../../util/pstack.h"
1528 #include "../../util/sort.h"
16
-#include "../../util/util.h"
1729 #include "../../util/top.h"
1830 #include "../../util/thread.h"
31
+#include "../../util/block-info.h"
1932 #include "../../arch/common.h"
33
+#include "../../perf.h"
2034
2135 #include "../browsers/hists.h"
2236 #include "../helpline.h"
....@@ -27,8 +41,9 @@
2741 #include "srcline.h"
2842 #include "string2.h"
2943 #include "units.h"
44
+#include "time-utils.h"
3045
31
-#include "sane_ctype.h"
46
+#include <linux/ctype.h>
3247
3348 extern void hist_browser__init_hpp(void);
3449
....@@ -49,7 +64,7 @@
4964 struct hists *hists = browser->hists;
5065 int unfolded_rows = 0;
5166
52
- for (nd = rb_first(&hists->entries);
67
+ for (nd = rb_first_cached(&hists->entries);
5368 (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
5469 nd = rb_hierarchy_next(nd)) {
5570 struct hist_entry *he =
....@@ -267,7 +282,7 @@
267282 if (he->has_no_entry)
268283 return 1;
269284
270
- node = rb_first(&he->hroot_out);
285
+ node = rb_first_cached(&he->hroot_out);
271286 while (node) {
272287 float percent;
273288
....@@ -372,10 +387,56 @@
372387 he->has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
373388 callchain__init_have_children(&he->sorted_chain);
374389 } else {
375
- he->has_children = !RB_EMPTY_ROOT(&he->hroot_out);
390
+ he->has_children = !RB_EMPTY_ROOT(&he->hroot_out.rb_root);
376391 }
377392
378393 he->init_have_children = true;
394
+}
395
+
396
+static bool hist_browser__selection_has_children(struct hist_browser *browser)
397
+{
398
+ struct hist_entry *he = browser->he_selection;
399
+ struct map_symbol *ms = browser->selection;
400
+
401
+ if (!he || !ms)
402
+ return false;
403
+
404
+ if (ms == &he->ms)
405
+ return he->has_children;
406
+
407
+ return container_of(ms, struct callchain_list, ms)->has_children;
408
+}
409
+
410
+static bool hist_browser__selection_unfolded(struct hist_browser *browser)
411
+{
412
+ struct hist_entry *he = browser->he_selection;
413
+ struct map_symbol *ms = browser->selection;
414
+
415
+ if (!he || !ms)
416
+ return false;
417
+
418
+ if (ms == &he->ms)
419
+ return he->unfolded;
420
+
421
+ return container_of(ms, struct callchain_list, ms)->unfolded;
422
+}
423
+
424
+static char *hist_browser__selection_sym_name(struct hist_browser *browser, char *bf, size_t size)
425
+{
426
+ struct hist_entry *he = browser->he_selection;
427
+ struct map_symbol *ms = browser->selection;
428
+ struct callchain_list *callchain_entry;
429
+
430
+ if (!he || !ms)
431
+ return NULL;
432
+
433
+ if (ms == &he->ms) {
434
+ hist_entry__sym_snprintf(he, bf, size, 0);
435
+ return bf + 4; // skip the level, e.g. '[k] '
436
+ }
437
+
438
+ callchain_entry = container_of(ms, struct callchain_list, ms);
439
+ return callchain_list__sym_name(callchain_entry, bf, size, browser->show_dso);
379440 }
380441
381442 static bool hist_browser__toggle_fold(struct hist_browser *browser)
....@@ -508,7 +569,7 @@
508569 struct hist_entry *child;
509570 int n = 0;
510571
511
- for (nd = rb_first(&he->hroot_out); nd; nd = rb_next(nd)) {
572
+ for (nd = rb_first_cached(&he->hroot_out); nd; nd = rb_next(nd)) {
512573 child = rb_entry(nd, struct hist_entry, rb_node);
513574 percent = hist_entry__get_percent_limit(child);
514575 if (!child->filtered && percent >= hb->min_pcnt)
....@@ -518,8 +579,8 @@
518579 return n;
519580 }
520581
521
-static void __hist_entry__set_folding(struct hist_entry *he,
522
- struct hist_browser *hb, bool unfold)
582
+static void hist_entry__set_folding(struct hist_entry *he,
583
+ struct hist_browser *hb, bool unfold)
523584 {
524585 hist_entry__init_have_children(he);
525586 he->unfolded = unfold ? he->has_children : false;
....@@ -537,36 +598,14 @@
537598 he->nr_rows = 0;
538599 }
539600
540
-static void hist_entry__set_folding(struct hist_entry *he,
541
- struct hist_browser *browser, bool unfold)
542
-{
543
- double percent;
544
-
545
- percent = hist_entry__get_percent_limit(he);
546
- if (he->filtered || percent < browser->min_pcnt)
547
- return;
548
-
549
- __hist_entry__set_folding(he, browser, unfold);
550
-
551
- if (!he->depth || unfold)
552
- browser->nr_hierarchy_entries++;
553
- if (he->leaf)
554
- browser->nr_callchain_rows += he->nr_rows;
555
- else if (unfold && !hist_entry__has_hierarchy_children(he, browser->min_pcnt)) {
556
- browser->nr_hierarchy_entries++;
557
- he->has_no_entry = true;
558
- he->nr_rows = 1;
559
- } else
560
- he->has_no_entry = false;
561
-}
562
-
563601 static void
564602 __hist_browser__set_folding(struct hist_browser *browser, bool unfold)
565603 {
566604 struct rb_node *nd;
567605 struct hist_entry *he;
606
+ double percent;
568607
569
- nd = rb_first(&browser->hists->entries);
608
+ nd = rb_first_cached(&browser->hists->entries);
570609 while (nd) {
571610 he = rb_entry(nd, struct hist_entry, rb_node);
572611
....@@ -574,6 +613,21 @@
574613 nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);
575614
576615 hist_entry__set_folding(he, browser, unfold);
616
+
617
+ percent = hist_entry__get_percent_limit(he);
618
+ if (he->filtered || percent < browser->min_pcnt)
619
+ continue;
620
+
621
+ if (!he->depth || unfold)
622
+ browser->nr_hierarchy_entries++;
623
+ if (he->leaf)
624
+ browser->nr_callchain_rows += he->nr_rows;
625
+ else if (unfold && !hist_entry__has_hierarchy_children(he, browser->min_pcnt)) {
626
+ browser->nr_hierarchy_entries++;
627
+ he->has_no_entry = true;
628
+ he->nr_rows = 1;
629
+ } else
630
+ he->has_no_entry = false;
577631 }
578632 }
579633
....@@ -593,8 +647,10 @@
593647 if (!browser->he_selection)
594648 return;
595649
596
- hist_entry__set_folding(browser->he_selection, browser, unfold);
597
- browser->b.nr_entries = hist_browser__nr_entries(browser);
650
+ if (unfold == browser->he_selection->unfolded)
651
+ return;
652
+
653
+ hist_browser__toggle_fold(browser);
598654 }
599655
600656 static void ui_browser__warn_lost_events(struct ui_browser *browser)
....@@ -611,10 +667,81 @@
611667 return browser->title ? browser->title(browser, bf, size) : 0;
612668 }
613669
614
-int hist_browser__run(struct hist_browser *browser, const char *help,
615
- bool warn_lost_event)
670
+static int hist_browser__handle_hotkey(struct hist_browser *browser, bool warn_lost_event, char *title, size_t size, int key)
616671 {
617
- int key;
672
+ switch (key) {
673
+ case K_TIMER: {
674
+ struct hist_browser_timer *hbt = browser->hbt;
675
+ u64 nr_entries;
676
+
677
+ WARN_ON_ONCE(!hbt);
678
+
679
+ if (hbt)
680
+ hbt->timer(hbt->arg);
681
+
682
+ if (hist_browser__has_filter(browser) || symbol_conf.report_hierarchy)
683
+ hist_browser__update_nr_entries(browser);
684
+
685
+ nr_entries = hist_browser__nr_entries(browser);
686
+ ui_browser__update_nr_entries(&browser->b, nr_entries);
687
+
688
+ if (warn_lost_event &&
689
+ (browser->hists->stats.nr_lost_warned !=
690
+ browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
691
+ browser->hists->stats.nr_lost_warned =
692
+ browser->hists->stats.nr_events[PERF_RECORD_LOST];
693
+ ui_browser__warn_lost_events(&browser->b);
694
+ }
695
+
696
+ hist_browser__title(browser, title, size);
697
+ ui_browser__show_title(&browser->b, title);
698
+ break;
699
+ }
700
+ case 'D': { /* Debug */
701
+ struct hist_entry *h = rb_entry(browser->b.top, struct hist_entry, rb_node);
702
+ static int seq;
703
+
704
+ ui_helpline__pop();
705
+ ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
706
+ seq++, browser->b.nr_entries, browser->hists->nr_entries,
707
+ browser->b.extra_title_lines, browser->b.rows,
708
+ browser->b.index, browser->b.top_idx, h->row_offset, h->nr_rows);
709
+ }
710
+ break;
711
+ case 'C':
712
+ /* Collapse the whole world. */
713
+ hist_browser__set_folding(browser, false);
714
+ break;
715
+ case 'c':
716
+ /* Collapse the selected entry. */
717
+ hist_browser__set_folding_selected(browser, false);
718
+ break;
719
+ case 'E':
720
+ /* Expand the whole world. */
721
+ hist_browser__set_folding(browser, true);
722
+ break;
723
+ case 'e':
724
+ /* Toggle expand/collapse the selected entry. */
725
+ hist_browser__toggle_fold(browser);
726
+ break;
727
+ case 'H':
728
+ browser->show_headers = !browser->show_headers;
729
+ hist_browser__update_rows(browser);
730
+ break;
731
+ case '+':
732
+ if (hist_browser__toggle_fold(browser))
733
+ break;
734
+ /* fall thru */
735
+ default:
736
+ return -1;
737
+ }
738
+
739
+ return 0;
740
+}
741
+
742
+int hist_browser__run(struct hist_browser *browser, const char *help,
743
+ bool warn_lost_event, int key)
744
+{
618745 char title[160];
619746 struct hist_browser_timer *hbt = browser->hbt;
620747 int delay_secs = hbt ? hbt->refresh : 0;
....@@ -627,79 +754,14 @@
627754 if (ui_browser__show(&browser->b, title, "%s", help) < 0)
628755 return -1;
629756
757
+ if (key && hist_browser__handle_hotkey(browser, warn_lost_event, title, sizeof(title), key))
758
+ goto out;
759
+
630760 while (1) {
631761 key = ui_browser__run(&browser->b, delay_secs);
632762
633
- switch (key) {
634
- case K_TIMER: {
635
- u64 nr_entries;
636
-
637
- WARN_ON_ONCE(!hbt);
638
-
639
- if (hbt)
640
- hbt->timer(hbt->arg);
641
-
642
- if (hist_browser__has_filter(browser) ||
643
- symbol_conf.report_hierarchy)
644
- hist_browser__update_nr_entries(browser);
645
-
646
- nr_entries = hist_browser__nr_entries(browser);
647
- ui_browser__update_nr_entries(&browser->b, nr_entries);
648
-
649
- if (warn_lost_event &&
650
- (browser->hists->stats.nr_lost_warned !=
651
- browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
652
- browser->hists->stats.nr_lost_warned =
653
- browser->hists->stats.nr_events[PERF_RECORD_LOST];
654
- ui_browser__warn_lost_events(&browser->b);
655
- }
656
-
657
- hist_browser__title(browser, title, sizeof(title));
658
- ui_browser__show_title(&browser->b, title);
659
- continue;
660
- }
661
- case 'D': { /* Debug */
662
- static int seq;
663
- struct hist_entry *h = rb_entry(browser->b.top,
664
- struct hist_entry, rb_node);
665
- ui_helpline__pop();
666
- ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
667
- seq++, browser->b.nr_entries,
668
- browser->hists->nr_entries,
669
- browser->b.extra_title_lines,
670
- browser->b.rows,
671
- browser->b.index,
672
- browser->b.top_idx,
673
- h->row_offset, h->nr_rows);
674
- }
763
+ if (hist_browser__handle_hotkey(browser, warn_lost_event, title, sizeof(title), key))
675764 break;
676
- case 'C':
677
- /* Collapse the whole world. */
678
- hist_browser__set_folding(browser, false);
679
- break;
680
- case 'c':
681
- /* Collapse the selected entry. */
682
- hist_browser__set_folding_selected(browser, false);
683
- break;
684
- case 'E':
685
- /* Expand the whole world. */
686
- hist_browser__set_folding(browser, true);
687
- break;
688
- case 'e':
689
- /* Expand the selected entry. */
690
- hist_browser__set_folding_selected(browser, true);
691
- break;
692
- case 'H':
693
- browser->show_headers = !browser->show_headers;
694
- hist_browser__update_rows(browser);
695
- break;
696
- case K_ENTER:
697
- if (hist_browser__toggle_fold(browser))
698
- break;
699
- /* fall thru */
700
- default:
701
- goto out;
702
- }
703765 }
704766 out:
705767 ui_browser__hide(&browser->b);
....@@ -1225,6 +1287,8 @@
12251287 hist_browser__hpp_color_overhead_guest_us;
12261288 perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color =
12271289 hist_browser__hpp_color_overhead_acc;
1290
+
1291
+ res_sample_init();
12281292 }
12291293
12301294 static int hist_browser__show_entry(struct hist_browser *browser,
....@@ -1467,7 +1531,7 @@
14671531 int i = 0;
14681532
14691533 width -= fmt->entry(fmt, &hpp, entry);
1470
- ui_browser__printf(&browser->b, "%s", ltrim(s));
1534
+ ui_browser__printf(&browser->b, "%s", skip_spaces(s));
14711535
14721536 while (isspace(s[i++]))
14731537 width++;
....@@ -1683,7 +1747,7 @@
16831747 ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
16841748 dummy_hpp.buf[ret] = '\0';
16851749
1686
- start = trim(dummy_hpp.buf);
1750
+ start = strim(dummy_hpp.buf);
16871751 ret = strlen(start);
16881752
16891753 if (start != dummy_hpp.buf)
....@@ -1704,7 +1768,7 @@
17041768 hists_browser__scnprintf_hierarchy_headers(browser, headers,
17051769 sizeof(headers));
17061770
1707
- ui_browser__gotorc(&browser->b, 0, 0);
1771
+ ui_browser__gotorc_title(&browser->b, 0, 0);
17081772 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
17091773 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
17101774 }
....@@ -1742,7 +1806,7 @@
17421806 struct hist_browser *hb;
17431807
17441808 hb = container_of(browser, struct hist_browser, b);
1745
- browser->top = rb_first(&hb->hists->entries);
1809
+ browser->top = rb_first_cached(&hb->hists->entries);
17461810 }
17471811 }
17481812
....@@ -1769,7 +1833,11 @@
17691833 continue;
17701834 }
17711835
1772
- percent = hist_entry__get_percent_limit(h);
1836
+ if (symbol_conf.report_individual_block)
1837
+ percent = block_info__total_cycles_percent(h);
1838
+ else
1839
+ percent = hist_entry__get_percent_limit(h);
1840
+
17731841 if (percent < hb->min_pcnt)
17741842 continue;
17751843
....@@ -2067,7 +2135,8 @@
20672135 advance_hpp(&hpp, ret);
20682136 }
20692137
2070
- printed += fprintf(fp, "%s\n", rtrim(s));
2138
+ strim(s);
2139
+ printed += fprintf(fp, "%s\n", s);
20712140
20722141 if (he->leaf && folded_sign == '-') {
20732142 printed += hist_browser__fprintf_callchain(browser, he, fp,
....@@ -2178,7 +2247,7 @@
21782247 }
21792248
21802249 static struct hist_browser *
2181
-perf_evsel_browser__new(struct perf_evsel *evsel,
2250
+perf_evsel_browser__new(struct evsel *evsel,
21822251 struct hist_browser_timer *hbt,
21832252 struct perf_env *env,
21842253 struct annotation_options *annotation_opts)
....@@ -2209,6 +2278,11 @@
22092278 return browser->he_selection->thread;
22102279 }
22112280
2281
+static struct res_sample *hist_browser__selected_res_sample(struct hist_browser *browser)
2282
+{
2283
+ return browser->he_selection ? browser->he_selection->res_samples : NULL;
2284
+}
2285
+
22122286 /* Check whether the browser is for 'top' or 'report' */
22132287 static inline bool is_report_browser(void *timer)
22142288 {
....@@ -2223,9 +2297,20 @@
22232297 if (!is_report_browser(hbt)) {
22242298 struct perf_top *top = hbt->arg;
22252299
2300
+ printed += scnprintf(bf + printed, size - printed,
2301
+ " lost: %" PRIu64 "/%" PRIu64,
2302
+ top->lost, top->lost_total);
2303
+
2304
+ printed += scnprintf(bf + printed, size - printed,
2305
+ " drop: %" PRIu64 "/%" PRIu64,
2306
+ top->drop, top->drop_total);
2307
+
22262308 if (top->zero)
22272309 printed += scnprintf(bf + printed, size - printed, " [z]");
2310
+
2311
+ perf_top__reset_sample_counters(top);
22282312 }
2313
+
22292314
22302315 return printed;
22312316 }
....@@ -2308,7 +2393,7 @@
23082393 closedir(pwd_dir);
23092394
23102395 if (nr_options) {
2311
- choice = ui__popup_menu(nr_options, options);
2396
+ choice = ui__popup_menu(nr_options, options, NULL);
23122397 if (choice < nr_options && choice >= 0) {
23132398 tmp = strdup(abs_path[choice]);
23142399 if (tmp) {
....@@ -2328,9 +2413,12 @@
23282413 }
23292414
23302415 struct popup_action {
2416
+ unsigned long time;
23312417 struct thread *thread;
23322418 struct map_symbol ms;
23332419 int socket;
2420
+ struct evsel *evsel;
2421
+ enum rstype rstype;
23342422
23352423 int (*fn)(struct hist_browser *browser, struct popup_action *act);
23362424 };
....@@ -2338,7 +2426,7 @@
23382426 static int
23392427 do_annotate(struct hist_browser *browser, struct popup_action *act)
23402428 {
2341
- struct perf_evsel *evsel;
2429
+ struct evsel *evsel;
23422430 struct annotation *notes;
23432431 struct hist_entry *he;
23442432 int err;
....@@ -2351,7 +2439,11 @@
23512439 if (!notes->src)
23522440 return 0;
23532441
2354
- evsel = hists_to_evsel(browser->hists);
2442
+ if (browser->block_evsel)
2443
+ evsel = browser->block_evsel;
2444
+ else
2445
+ evsel = hists_to_evsel(browser->hists);
2446
+
23552447 err = map_symbol__tui_annotate(&act->ms, evsel, browser->hbt,
23562448 browser->annotation_opts);
23572449 he = hist_browser__selected_entry(browser);
....@@ -2368,19 +2460,47 @@
23682460 return 0;
23692461 }
23702462
2463
+static struct symbol *symbol__new_unresolved(u64 addr, struct map *map)
2464
+{
2465
+ struct annotated_source *src;
2466
+ struct symbol *sym;
2467
+ char name[64];
2468
+
2469
+ snprintf(name, sizeof(name), "%.*" PRIx64, BITS_PER_LONG / 4, addr);
2470
+
2471
+ sym = symbol__new(addr, ANNOTATION_DUMMY_LEN, 0, 0, name);
2472
+ if (sym) {
2473
+ src = symbol__hists(sym, 1);
2474
+ if (!src) {
2475
+ symbol__delete(sym);
2476
+ return NULL;
2477
+ }
2478
+
2479
+ dso__insert_symbol(map->dso, sym);
2480
+ }
2481
+
2482
+ return sym;
2483
+}
2484
+
23712485 static int
23722486 add_annotate_opt(struct hist_browser *browser __maybe_unused,
23732487 struct popup_action *act, char **optstr,
2374
- struct map *map, struct symbol *sym)
2488
+ struct map_symbol *ms,
2489
+ u64 addr)
23752490 {
2376
- if (sym == NULL || map->dso->annotate_warned)
2491
+ if (!ms->map || !ms->map->dso || ms->map->dso->annotate_warned)
23772492 return 0;
23782493
2379
- if (asprintf(optstr, "Annotate %s", sym->name) < 0)
2494
+ if (!ms->sym)
2495
+ ms->sym = symbol__new_unresolved(addr, ms->map);
2496
+
2497
+ if (ms->sym == NULL || symbol__annotation(ms->sym)->src == NULL)
23802498 return 0;
23812499
2382
- act->ms.map = map;
2383
- act->ms.sym = sym;
2500
+ if (asprintf(optstr, "Annotate %s", ms->sym->name) < 0)
2501
+ return 0;
2502
+
2503
+ act->ms = *ms;
23842504 act->fn = do_annotate;
23852505 return 1;
23862506 }
....@@ -2447,11 +2567,8 @@
24472567 return 1;
24482568 }
24492569
2450
-static int
2451
-do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2570
+static int hists_browser__zoom_map(struct hist_browser *browser, struct map *map)
24522571 {
2453
- struct map *map = act->ms.map;
2454
-
24552572 if (!hists__has(browser->hists, dso) || map == NULL)
24562573 return 0;
24572574
....@@ -2474,19 +2591,47 @@
24742591 }
24752592
24762593 static int
2594
+do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2595
+{
2596
+ return hists_browser__zoom_map(browser, act->ms.map);
2597
+}
2598
+
2599
+static int
24772600 add_dso_opt(struct hist_browser *browser, struct popup_action *act,
24782601 char **optstr, struct map *map)
24792602 {
24802603 if (!hists__has(browser->hists, dso) || map == NULL)
24812604 return 0;
24822605
2483
- if (asprintf(optstr, "Zoom %s %s DSO",
2606
+ if (asprintf(optstr, "Zoom %s %s DSO (use the 'k' hotkey to zoom directly into the kernel)",
24842607 browser->hists->dso_filter ? "out of" : "into",
24852608 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0)
24862609 return 0;
24872610
24882611 act->ms.map = map;
24892612 act->fn = do_zoom_dso;
2613
+ return 1;
2614
+}
2615
+
2616
+static int do_toggle_callchain(struct hist_browser *browser, struct popup_action *act __maybe_unused)
2617
+{
2618
+ hist_browser__toggle_fold(browser);
2619
+ return 0;
2620
+}
2621
+
2622
+static int add_callchain_toggle_opt(struct hist_browser *browser, struct popup_action *act, char **optstr)
2623
+{
2624
+ char sym_name[512];
2625
+
2626
+ if (!hist_browser__selection_has_children(browser))
2627
+ return 0;
2628
+
2629
+ if (asprintf(optstr, "%s [%s] callchain (one level, same as '+' hotkey, use 'e'/'c' for the whole main level entry)",
2630
+ hist_browser__selection_unfolded(browser) ? "Collapse" : "Expand",
2631
+ hist_browser__selection_sym_name(browser, sym_name, sizeof(sym_name))) < 0)
2632
+ return 0;
2633
+
2634
+ act->fn = do_toggle_callchain;
24902635 return 1;
24912636 }
24922637
....@@ -2517,42 +2662,133 @@
25172662 do_run_script(struct hist_browser *browser __maybe_unused,
25182663 struct popup_action *act)
25192664 {
2520
- char script_opt[64];
2521
- memset(script_opt, 0, sizeof(script_opt));
2665
+ char *script_opt;
2666
+ int len;
2667
+ int n = 0;
25222668
2669
+ len = 100;
2670
+ if (act->thread)
2671
+ len += strlen(thread__comm_str(act->thread));
2672
+ else if (act->ms.sym)
2673
+ len += strlen(act->ms.sym->name);
2674
+ script_opt = malloc(len);
2675
+ if (!script_opt)
2676
+ return -1;
2677
+
2678
+ script_opt[0] = 0;
25232679 if (act->thread) {
2524
- scnprintf(script_opt, sizeof(script_opt), " -c %s ",
2680
+ n = scnprintf(script_opt, len, " -c %s ",
25252681 thread__comm_str(act->thread));
25262682 } else if (act->ms.sym) {
2527
- scnprintf(script_opt, sizeof(script_opt), " -S %s ",
2683
+ n = scnprintf(script_opt, len, " -S %s ",
25282684 act->ms.sym->name);
25292685 }
25302686
2531
- script_browse(script_opt);
2687
+ if (act->time) {
2688
+ char start[32], end[32];
2689
+ unsigned long starttime = act->time;
2690
+ unsigned long endtime = act->time + symbol_conf.time_quantum;
2691
+
2692
+ if (starttime == endtime) { /* Display 1ms as fallback */
2693
+ starttime -= 1*NSEC_PER_MSEC;
2694
+ endtime += 1*NSEC_PER_MSEC;
2695
+ }
2696
+ timestamp__scnprintf_usec(starttime, start, sizeof start);
2697
+ timestamp__scnprintf_usec(endtime, end, sizeof end);
2698
+ n += snprintf(script_opt + n, len - n, " --time %s,%s", start, end);
2699
+ }
2700
+
2701
+ script_browse(script_opt, act->evsel);
2702
+ free(script_opt);
25322703 return 0;
25332704 }
25342705
25352706 static int
2536
-add_script_opt(struct hist_browser *browser __maybe_unused,
2537
- struct popup_action *act, char **optstr,
2538
- struct thread *thread, struct symbol *sym)
2707
+do_res_sample_script(struct hist_browser *browser __maybe_unused,
2708
+ struct popup_action *act)
25392709 {
2710
+ struct hist_entry *he;
2711
+
2712
+ he = hist_browser__selected_entry(browser);
2713
+ res_sample_browse(he->res_samples, he->num_res, act->evsel, act->rstype);
2714
+ return 0;
2715
+}
2716
+
2717
+static int
2718
+add_script_opt_2(struct hist_browser *browser __maybe_unused,
2719
+ struct popup_action *act, char **optstr,
2720
+ struct thread *thread, struct symbol *sym,
2721
+ struct evsel *evsel, const char *tstr)
2722
+{
2723
+
25402724 if (thread) {
2541
- if (asprintf(optstr, "Run scripts for samples of thread [%s]",
2542
- thread__comm_str(thread)) < 0)
2725
+ if (asprintf(optstr, "Run scripts for samples of thread [%s]%s",
2726
+ thread__comm_str(thread), tstr) < 0)
25432727 return 0;
25442728 } else if (sym) {
2545
- if (asprintf(optstr, "Run scripts for samples of symbol [%s]",
2546
- sym->name) < 0)
2729
+ if (asprintf(optstr, "Run scripts for samples of symbol [%s]%s",
2730
+ sym->name, tstr) < 0)
25472731 return 0;
25482732 } else {
2549
- if (asprintf(optstr, "Run scripts for all samples") < 0)
2733
+ if (asprintf(optstr, "Run scripts for all samples%s", tstr) < 0)
25502734 return 0;
25512735 }
25522736
25532737 act->thread = thread;
25542738 act->ms.sym = sym;
2739
+ act->evsel = evsel;
25552740 act->fn = do_run_script;
2741
+ return 1;
2742
+}
2743
+
2744
+static int
2745
+add_script_opt(struct hist_browser *browser,
2746
+ struct popup_action *act, char **optstr,
2747
+ struct thread *thread, struct symbol *sym,
2748
+ struct evsel *evsel)
2749
+{
2750
+ int n, j;
2751
+ struct hist_entry *he;
2752
+
2753
+ n = add_script_opt_2(browser, act, optstr, thread, sym, evsel, "");
2754
+
2755
+ he = hist_browser__selected_entry(browser);
2756
+ if (sort_order && strstr(sort_order, "time")) {
2757
+ char tstr[128];
2758
+
2759
+ optstr++;
2760
+ act++;
2761
+ j = sprintf(tstr, " in ");
2762
+ j += timestamp__scnprintf_usec(he->time, tstr + j,
2763
+ sizeof tstr - j);
2764
+ j += sprintf(tstr + j, "-");
2765
+ timestamp__scnprintf_usec(he->time + symbol_conf.time_quantum,
2766
+ tstr + j, sizeof tstr - j);
2767
+ n += add_script_opt_2(browser, act, optstr, thread, sym,
2768
+ evsel, tstr);
2769
+ act->time = he->time;
2770
+ }
2771
+ return n;
2772
+}
2773
+
2774
+static int
2775
+add_res_sample_opt(struct hist_browser *browser __maybe_unused,
2776
+ struct popup_action *act, char **optstr,
2777
+ struct res_sample *res_sample,
2778
+ struct evsel *evsel,
2779
+ enum rstype type)
2780
+{
2781
+ if (!res_sample)
2782
+ return 0;
2783
+
2784
+ if (asprintf(optstr, "Show context for individual samples %s",
2785
+ type == A_ASM ? "with assembler" :
2786
+ type == A_SOURCE ? "with source" : "") < 0)
2787
+ return 0;
2788
+
2789
+ act->fn = do_res_sample_script;
2790
+ act->evsel = evsel;
2791
+ act->rstype = type;
25562792 return 1;
25572793 }
25582794
....@@ -2642,7 +2878,7 @@
26422878 static void hist_browser__update_nr_entries(struct hist_browser *hb)
26432879 {
26442880 u64 nr_entries = 0;
2645
- struct rb_node *nd = rb_first(&hb->hists->entries);
2881
+ struct rb_node *nd = rb_first_cached(&hb->hists->entries);
26462882
26472883 if (hb->min_pcnt == 0 && !symbol_conf.report_hierarchy) {
26482884 hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
....@@ -2662,7 +2898,7 @@
26622898 double percent)
26632899 {
26642900 struct hist_entry *he;
2665
- struct rb_node *nd = rb_first(&hb->hists->entries);
2901
+ struct rb_node *nd = rb_first_cached(&hb->hists->entries);
26662902 u64 total = hists__total_period(hb->hists);
26672903 u64 min_callchain_hits = total * (percent / 100);
26682904
....@@ -2700,7 +2936,7 @@
27002936 }
27012937 }
27022938
2703
-static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2939
+static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events,
27042940 const char *helpline,
27052941 bool left_exits,
27062942 struct hist_browser_timer *hbt,
....@@ -2717,7 +2953,7 @@
27172953 struct popup_action actions[MAX_OPTIONS];
27182954 int nr_options = 0;
27192955 int key = -1;
2720
- char buf[64];
2956
+ char buf[128];
27212957 int delay_secs = hbt ? hbt->refresh : 0;
27222958
27232959 #define HIST_BROWSER_HELP_COMMON \
....@@ -2730,26 +2966,30 @@
27302966 "For symbolic views (--sort has sym):\n\n" \
27312967 "ENTER Zoom into DSO/Threads & Annotate current symbol\n" \
27322968 "ESC Zoom out\n" \
2969
+ "+ Expand/Collapse one callchain level\n" \
27332970 "a Annotate current symbol\n" \
27342971 "C Collapse all callchains\n" \
27352972 "d Zoom into current DSO\n" \
2973
+ "e Expand/Collapse main entry callchains\n" \
27362974 "E Expand all callchains\n" \
27372975 "F Toggle percentage of filtered entries\n" \
27382976 "H Display column headers\n" \
2977
+ "k Zoom into the kernel map\n" \
27392978 "L Change percent limit\n" \
27402979 "m Display context menu\n" \
27412980 "S Zoom into current Processor Socket\n" \
27422981
27432982 /* help messages are sorted by lexical order of the hotkey */
2744
- const char report_help[] = HIST_BROWSER_HELP_COMMON
2983
+ static const char report_help[] = HIST_BROWSER_HELP_COMMON
27452984 "i Show header information\n"
27462985 "P Print histograms to perf.hist.N\n"
27472986 "r Run available scripts\n"
27482987 "s Switch to another data file in PWD\n"
27492988 "t Zoom into current Thread\n"
27502989 "V Verbose (DSO names in callchains, etc)\n"
2751
- "/ Filter symbol by name";
2752
- const char top_help[] = HIST_BROWSER_HELP_COMMON
2990
+ "/ Filter symbol by name\n"
2991
+ "0-9 Sort by event n in group";
2992
+ static const char top_help[] = HIST_BROWSER_HELP_COMMON
27532993 "P Print histograms to perf.hist.N\n"
27542994 "t Zoom into current Thread\n"
27552995 "V Verbose (DSO names in callchains, etc)\n"
....@@ -2780,16 +3020,19 @@
27803020 if (symbol_conf.col_width_list_str)
27813021 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
27823022
3023
+ if (!is_report_browser(hbt))
3024
+ browser->b.no_samples_msg = "Collecting samples...";
3025
+
27833026 while (1) {
27843027 struct thread *thread = NULL;
27853028 struct map *map = NULL;
2786
- int choice = 0;
3029
+ int choice;
27873030 int socked_id = -1;
27883031
2789
- nr_options = 0;
2790
-
2791
- key = hist_browser__run(browser, helpline,
2792
- warn_lost_event);
3032
+ key = 0; // reset key
3033
+do_hotkey: // key came straight from options ui__popup_menu()
3034
+ choice = nr_options = 0;
3035
+ key = hist_browser__run(browser, helpline, warn_lost_event, key);
27933036
27943037 if (browser->he_selection != NULL) {
27953038 thread = hist_browser__selected_thread(browser);
....@@ -2806,6 +3049,31 @@
28063049 * go to the next or previous
28073050 */
28083051 goto out_free_stack;
3052
+ case '0' ... '9':
3053
+ if (!symbol_conf.event_group ||
3054
+ evsel->core.nr_members < 2) {
3055
+ snprintf(buf, sizeof(buf),
3056
+ "Sort by index only available with group events!");
3057
+ helpline = buf;
3058
+ continue;
3059
+ }
3060
+
3061
+ if (key - '0' == symbol_conf.group_sort_idx)
3062
+ continue;
3063
+
3064
+ symbol_conf.group_sort_idx = key - '0';
3065
+
3066
+ if (symbol_conf.group_sort_idx >= evsel->core.nr_members) {
3067
+ snprintf(buf, sizeof(buf),
3068
+ "Max event group index to sort is %d (index from 0 to %d)",
3069
+ evsel->core.nr_members - 1,
3070
+ evsel->core.nr_members - 1);
3071
+ helpline = buf;
3072
+ continue;
3073
+ }
3074
+
3075
+ key = K_RELOAD;
3076
+ goto out_free_stack;
28093077 case 'a':
28103078 if (!hists__has(hists, sym)) {
28113079 ui_browser__warning(&browser->b, delay_secs * 2,
....@@ -2814,13 +3082,45 @@
28143082 continue;
28153083 }
28163084
2817
- if (browser->selection == NULL ||
2818
- browser->selection->sym == NULL ||
2819
- browser->selection->map->dso->annotate_warned)
3085
+ if (!browser->selection ||
3086
+ !browser->selection->map ||
3087
+ !browser->selection->map->dso ||
3088
+ browser->selection->map->dso->annotate_warned) {
28203089 continue;
3090
+ }
28213091
2822
- actions->ms.map = browser->selection->map;
2823
- actions->ms.sym = browser->selection->sym;
3092
+ if (!browser->selection->sym) {
3093
+ if (!browser->he_selection)
3094
+ continue;
3095
+
3096
+ if (sort__mode == SORT_MODE__BRANCH) {
3097
+ bi = browser->he_selection->branch_info;
3098
+ if (!bi || !bi->to.ms.map)
3099
+ continue;
3100
+
3101
+ actions->ms.sym = symbol__new_unresolved(bi->to.al_addr, bi->to.ms.map);
3102
+ actions->ms.map = bi->to.ms.map;
3103
+ } else {
3104
+ actions->ms.sym = symbol__new_unresolved(browser->he_selection->ip,
3105
+ browser->selection->map);
3106
+ actions->ms.map = browser->selection->map;
3107
+ }
3108
+
3109
+ if (!actions->ms.sym)
3110
+ continue;
3111
+ } else {
3112
+ if (symbol__annotation(browser->selection->sym)->src == NULL) {
3113
+ ui_browser__warning(&browser->b, delay_secs * 2,
3114
+ "No samples for the \"%s\" symbol.\n\n"
3115
+ "Probably appeared just in a callchain",
3116
+ browser->selection->sym->name);
3117
+ continue;
3118
+ }
3119
+
3120
+ actions->ms.map = browser->selection->map;
3121
+ actions->ms.sym = browser->selection->sym;
3122
+ }
3123
+
28243124 do_annotate(browser, actions);
28253125 continue;
28263126 case 'P':
....@@ -2829,6 +3129,10 @@
28293129 case 'd':
28303130 actions->ms.map = map;
28313131 do_zoom_dso(browser, actions);
3132
+ continue;
3133
+ case 'k':
3134
+ if (browser->selection != NULL)
3135
+ hists_browser__zoom_map(browser, browser->selection->maps->machine->vmlinux_map);
28323136 continue;
28333137 case 'V':
28343138 verbose = (verbose + 1) % 4;
....@@ -2988,26 +3292,27 @@
29883292 nr_options += add_annotate_opt(browser,
29893293 &actions[nr_options],
29903294 &options[nr_options],
2991
- bi->from.map,
2992
- bi->from.sym);
2993
- if (bi->to.sym != bi->from.sym)
3295
+ &bi->from.ms,
3296
+ bi->from.al_addr);
3297
+ if (bi->to.ms.sym != bi->from.ms.sym)
29943298 nr_options += add_annotate_opt(browser,
29953299 &actions[nr_options],
29963300 &options[nr_options],
2997
- bi->to.map,
2998
- bi->to.sym);
3301
+ &bi->to.ms,
3302
+ bi->to.al_addr);
29993303 } else {
30003304 nr_options += add_annotate_opt(browser,
30013305 &actions[nr_options],
30023306 &options[nr_options],
3003
- browser->selection->map,
3004
- browser->selection->sym);
3307
+ browser->selection,
3308
+ browser->he_selection->ip);
30053309 }
30063310 skip_annotation:
30073311 nr_options += add_thread_opt(browser, &actions[nr_options],
30083312 &options[nr_options], thread);
30093313 nr_options += add_dso_opt(browser, &actions[nr_options],
30103314 &options[nr_options], map);
3315
+ nr_options += add_callchain_toggle_opt(browser, &actions[nr_options], &options[nr_options]);
30113316 nr_options += add_map_opt(browser, &actions[nr_options],
30123317 &options[nr_options],
30133318 browser->selection ?
....@@ -3024,7 +3329,7 @@
30243329 nr_options += add_script_opt(browser,
30253330 &actions[nr_options],
30263331 &options[nr_options],
3027
- thread, NULL);
3332
+ thread, NULL, evsel);
30283333 }
30293334 /*
30303335 * Note that browser->selection != NULL
....@@ -3039,11 +3344,24 @@
30393344 nr_options += add_script_opt(browser,
30403345 &actions[nr_options],
30413346 &options[nr_options],
3042
- NULL, browser->selection->sym);
3347
+ NULL, browser->selection->sym,
3348
+ evsel);
30433349 }
30443350 }
30453351 nr_options += add_script_opt(browser, &actions[nr_options],
3046
- &options[nr_options], NULL, NULL);
3352
+ &options[nr_options], NULL, NULL, evsel);
3353
+ nr_options += add_res_sample_opt(browser, &actions[nr_options],
3354
+ &options[nr_options],
3355
+ hist_browser__selected_res_sample(browser),
3356
+ evsel, A_NORMAL);
3357
+ nr_options += add_res_sample_opt(browser, &actions[nr_options],
3358
+ &options[nr_options],
3359
+ hist_browser__selected_res_sample(browser),
3360
+ evsel, A_ASM);
3361
+ nr_options += add_res_sample_opt(browser, &actions[nr_options],
3362
+ &options[nr_options],
3363
+ hist_browser__selected_res_sample(browser),
3364
+ evsel, A_SOURCE);
30473365 nr_options += add_switch_opt(browser, &actions[nr_options],
30483366 &options[nr_options]);
30493367 skip_scripting:
....@@ -3053,9 +3371,12 @@
30533371 do {
30543372 struct popup_action *act;
30553373
3056
- choice = ui__popup_menu(nr_options, options);
3057
- if (choice == -1 || choice >= nr_options)
3374
+ choice = ui__popup_menu(nr_options, options, &key);
3375
+ if (choice == -1)
30583376 break;
3377
+
3378
+ if (choice == nr_options)
3379
+ goto do_hotkey;
30593380
30603381 act = &actions[choice];
30613382 key = act->fn(browser, act);
....@@ -3072,9 +3393,9 @@
30723393 return key;
30733394 }
30743395
3075
-struct perf_evsel_menu {
3396
+struct evsel_menu {
30763397 struct ui_browser b;
3077
- struct perf_evsel *selection;
3398
+ struct evsel *selection;
30783399 struct annotation_options *annotation_opts;
30793400 bool lost_events, lost_events_warned;
30803401 float min_pcnt;
....@@ -3084,13 +3405,13 @@
30843405 static void perf_evsel_menu__write(struct ui_browser *browser,
30853406 void *entry, int row)
30863407 {
3087
- struct perf_evsel_menu *menu = container_of(browser,
3088
- struct perf_evsel_menu, b);
3089
- struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
3408
+ struct evsel_menu *menu = container_of(browser,
3409
+ struct evsel_menu, b);
3410
+ struct evsel *evsel = list_entry(entry, struct evsel, core.node);
30903411 struct hists *hists = evsel__hists(evsel);
30913412 bool current_entry = ui_browser__is_current_entry(browser, row);
30923413 unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
3093
- const char *ev_name = perf_evsel__name(evsel);
3414
+ const char *ev_name = evsel__name(evsel);
30943415 char bf[256], unit;
30953416 const char *warn = " ";
30963417 size_t printed;
....@@ -3098,10 +3419,10 @@
30983419 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
30993420 HE_COLORSET_NORMAL);
31003421
3101
- if (perf_evsel__is_group_event(evsel)) {
3102
- struct perf_evsel *pos;
3422
+ if (evsel__is_group_event(evsel)) {
3423
+ struct evsel *pos;
31033424
3104
- ev_name = perf_evsel__group_name(evsel);
3425
+ ev_name = evsel__group_name(evsel);
31053426
31063427 for_each_group_member(pos, evsel) {
31073428 struct hists *pos_hists = evsel__hists(pos);
....@@ -3131,13 +3452,13 @@
31313452 menu->selection = evsel;
31323453 }
31333454
3134
-static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
3455
+static int perf_evsel_menu__run(struct evsel_menu *menu,
31353456 int nr_events, const char *help,
31363457 struct hist_browser_timer *hbt,
31373458 bool warn_lost_event)
31383459 {
3139
- struct perf_evlist *evlist = menu->b.priv;
3140
- struct perf_evsel *pos;
3460
+ struct evlist *evlist = menu->b.priv;
3461
+ struct evsel *pos;
31413462 const char *title = "Available samples";
31423463 int delay_secs = hbt ? hbt->refresh : 0;
31433464 int key;
....@@ -3183,18 +3504,19 @@
31833504 ui_browser__show_title(&menu->b, title);
31843505 switch (key) {
31853506 case K_TAB:
3186
- if (pos->node.next == &evlist->entries)
3187
- pos = perf_evlist__first(evlist);
3507
+ if (pos->core.node.next == &evlist->core.entries)
3508
+ pos = evlist__first(evlist);
31883509 else
3189
- pos = perf_evsel__next(pos);
3510
+ pos = evsel__next(pos);
31903511 goto browse_hists;
31913512 case K_UNTAB:
3192
- if (pos->node.prev == &evlist->entries)
3193
- pos = perf_evlist__last(evlist);
3513
+ if (pos->core.node.prev == &evlist->core.entries)
3514
+ pos = evlist__last(evlist);
31943515 else
3195
- pos = perf_evsel__prev(pos);
3516
+ pos = evsel__prev(pos);
31963517 goto browse_hists;
31973518 case K_SWITCH_INPUT_DATA:
3519
+ case K_RELOAD:
31983520 case 'q':
31993521 case CTRL('c'):
32003522 goto out;
....@@ -3225,15 +3547,15 @@
32253547 static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
32263548 void *entry)
32273549 {
3228
- struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
3550
+ struct evsel *evsel = list_entry(entry, struct evsel, core.node);
32293551
3230
- if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
3552
+ if (symbol_conf.event_group && !evsel__is_group_leader(evsel))
32313553 return true;
32323554
32333555 return false;
32343556 }
32353557
3236
-static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3558
+static int __perf_evlist__tui_browse_hists(struct evlist *evlist,
32373559 int nr_entries, const char *help,
32383560 struct hist_browser_timer *hbt,
32393561 float min_pcnt,
....@@ -3241,10 +3563,10 @@
32413563 bool warn_lost_event,
32423564 struct annotation_options *annotation_opts)
32433565 {
3244
- struct perf_evsel *pos;
3245
- struct perf_evsel_menu menu = {
3566
+ struct evsel *pos;
3567
+ struct evsel_menu menu = {
32463568 .b = {
3247
- .entries = &evlist->entries,
3569
+ .entries = &evlist->core.entries,
32483570 .refresh = ui_browser__list_head_refresh,
32493571 .seek = ui_browser__list_head_seek,
32503572 .write = perf_evsel_menu__write,
....@@ -3260,7 +3582,7 @@
32603582 ui_helpline__push("Press ESC to exit");
32613583
32623584 evlist__for_each_entry(evlist, pos) {
3263
- const char *ev_name = perf_evsel__name(pos);
3585
+ const char *ev_name = evsel__name(pos);
32643586 size_t line_len = strlen(ev_name) + 7;
32653587
32663588 if (menu.b.width < line_len)
....@@ -3271,31 +3593,49 @@
32713593 hbt, warn_lost_event);
32723594 }
32733595
3274
-int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
3596
+static bool perf_evlist__single_entry(struct evlist *evlist)
3597
+{
3598
+ int nr_entries = evlist->core.nr_entries;
3599
+
3600
+ if (nr_entries == 1)
3601
+ return true;
3602
+
3603
+ if (nr_entries == 2) {
3604
+ struct evsel *last = evlist__last(evlist);
3605
+
3606
+ if (evsel__is_dummy_event(last))
3607
+ return true;
3608
+ }
3609
+
3610
+ return false;
3611
+}
3612
+
3613
+int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
32753614 struct hist_browser_timer *hbt,
32763615 float min_pcnt,
32773616 struct perf_env *env,
32783617 bool warn_lost_event,
32793618 struct annotation_options *annotation_opts)
32803619 {
3281
- int nr_entries = evlist->nr_entries;
3620
+ int nr_entries = evlist->core.nr_entries;
32823621
3283
-single_entry:
3284
- if (nr_entries == 1) {
3285
- struct perf_evsel *first = perf_evlist__first(evlist);
3622
+ if (perf_evlist__single_entry(evlist)) {
3623
+single_entry: {
3624
+ struct evsel *first = evlist__first(evlist);
32863625
32873626 return perf_evsel__hists_browse(first, nr_entries, help,
32883627 false, hbt, min_pcnt,
32893628 env, warn_lost_event,
32903629 annotation_opts);
32913630 }
3631
+ }
32923632
32933633 if (symbol_conf.event_group) {
3294
- struct perf_evsel *pos;
3634
+ struct evsel *pos;
32953635
32963636 nr_entries = 0;
32973637 evlist__for_each_entry(evlist, pos) {
3298
- if (perf_evsel__is_group_leader(pos))
3638
+ if (evsel__is_group_leader(pos))
32993639 nr_entries++;
33003640 }
33013641
....@@ -3308,3 +3648,75 @@
33083648 warn_lost_event,
33093649 annotation_opts);
33103650 }
3651
+
3652
+static int block_hists_browser__title(struct hist_browser *browser, char *bf,
3653
+ size_t size)
3654
+{
3655
+ struct hists *hists = evsel__hists(browser->block_evsel);
3656
+ const char *evname = evsel__name(browser->block_evsel);
3657
+ unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
3658
+ int ret;
3659
+
3660
+ ret = scnprintf(bf, size, "# Samples: %lu", nr_samples);
3661
+ if (evname)
3662
+ scnprintf(bf + ret, size - ret, " of event '%s'", evname);
3663
+
3664
+ return 0;
3665
+}
3666
+
3667
+int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel,
3668
+ float min_percent, struct perf_env *env,
3669
+ struct annotation_options *annotation_opts)
3670
+{
3671
+ struct hists *hists = &bh->block_hists;
3672
+ struct hist_browser *browser;
3673
+ int key = -1;
3674
+ struct popup_action action;
3675
+ static const char help[] =
3676
+ " q Quit \n";
3677
+
3678
+ browser = hist_browser__new(hists);
3679
+ if (!browser)
3680
+ return -1;
3681
+
3682
+ browser->block_evsel = evsel;
3683
+ browser->title = block_hists_browser__title;
3684
+ browser->min_pcnt = min_percent;
3685
+ browser->env = env;
3686
+ browser->annotation_opts = annotation_opts;
3687
+
3688
+ /* reset abort key so that it can get Ctrl-C as a key */
3689
+ SLang_reset_tty();
3690
+ SLang_init_tty(0, 0, 0);
3691
+
3692
+ memset(&action, 0, sizeof(action));
3693
+
3694
+ while (1) {
3695
+ key = hist_browser__run(browser, "? - help", true, 0);
3696
+
3697
+ switch (key) {
3698
+ case 'q':
3699
+ goto out;
3700
+ case '?':
3701
+ ui_browser__help_window(&browser->b, help);
3702
+ break;
3703
+ case 'a':
3704
+ case K_ENTER:
3705
+ if (!browser->selection ||
3706
+ !browser->selection->sym) {
3707
+ continue;
3708
+ }
3709
+
3710
+ action.ms.map = browser->selection->map;
3711
+ action.ms.sym = browser->selection->sym;
3712
+ do_annotate(browser, &action);
3713
+ continue;
3714
+ default:
3715
+ break;
3716
+ }
3717
+ }
3718
+
3719
+out:
3720
+ hist_browser__delete(browser);
3721
+ return 0;
3722
+}