aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/newt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/newt.c')
-rw-r--r--tools/perf/util/newt.c82
1 files changed, 74 insertions, 8 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index bbf725d4b38d..6d6e022d7708 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -490,6 +490,11 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his
490 return 0; 490 return 0;
491} 491}
492 492
493enum hist_filter {
494 HIST_FILTER__DSO,
495 HIST_FILTER__THREAD,
496};
497
493static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, 498static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso,
494 u64 *session_total) 499 u64 *session_total)
495{ 500{
@@ -502,10 +507,10 @@ static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso,
502 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 507 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
503 508
504 if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { 509 if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) {
505 h->filtered = true; 510 h->filtered |= (1 << HIST_FILTER__DSO);
506 continue; 511 continue;
507 } 512 }
508 h->filtered = false; 513 h->filtered &= ~(1 << HIST_FILTER__DSO);
509 ++nr_hists; 514 ++nr_hists;
510 *session_total += h->count; 515 *session_total += h->count;
511 } 516 }
@@ -513,12 +518,54 @@ static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso,
513 return nr_hists; 518 return nr_hists;
514} 519}
515 520
521static u64 hists__filter_by_thread(struct rb_root *hists, const struct thread *thread,
522 u64 *session_total)
523{
524 struct rb_node *nd;
525 u64 nr_hists = 0;
526
527 *session_total = 0;
528
529 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
530 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
531
532 if (thread != NULL && h->thread != thread) {
533 h->filtered |= (1 << HIST_FILTER__THREAD);
534 continue;
535 }
536 h->filtered &= ~(1 << HIST_FILTER__THREAD);
537 ++nr_hists;
538 *session_total += h->count;
539 }
540
541 return nr_hists;
542}
543
544static struct thread *hist_browser__selected_thread(struct hist_browser *self)
545{
546 int *indexes;
547
548 if (!symbol_conf.use_callchain)
549 goto out;
550
551 indexes = newtCheckboxTreeFindItem(self->tree, (void *)self->selection);
552 if (indexes) {
553 bool is_hist_entry = indexes[1] == NEWT_ARG_LAST;
554 free(indexes);
555 if (is_hist_entry)
556 goto out;
557 }
558 return NULL;
559out:
560 return *(struct thread **)(self->selection + 1);
561}
562
516int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, 563int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
517 u64 session_total, const char *helpline, 564 u64 session_total, const char *helpline,
518 const char *input_name) 565 const char *input_name)
519{ 566{
520 struct newtExitStruct es; 567 struct newtExitStruct es;
521 bool dso_filtered = false; 568 bool dso_filtered = false, thread_filtered = false;
522 int err = -1; 569 int err = -1;
523 struct hist_browser *browser = hist_browser__new(); 570 struct hist_browser *browser = hist_browser__new();
524 571
@@ -531,9 +578,10 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
531 goto out; 578 goto out;
532 579
533 while (1) { 580 while (1) {
581 const struct thread *thread;
534 char *options[16]; 582 char *options[16];
535 int nr_options = 0, choice = 0, i, 583 int nr_options = 0, choice = 0, i,
536 annotate = -2, zoom_dso = -2; 584 annotate = -2, zoom_dso = -2, zoom_thread = -2;
537 585
538 newtFormRun(browser->form, &es); 586 newtFormRun(browser->form, &es);
539 if (es.reason == NEWT_EXIT_HOTKEY) { 587 if (es.reason == NEWT_EXIT_HOTKEY) {
@@ -561,6 +609,13 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
561 browser->selection->map->dso->short_name)) > 0) 609 browser->selection->map->dso->short_name)) > 0)
562 zoom_dso = nr_options++; 610 zoom_dso = nr_options++;
563 611
612 thread = hist_browser__selected_thread(browser);
613 if (thread != NULL &&
614 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
615 (thread_filtered ? "out of" : "into"),
616 (thread->comm_set ? thread->comm : ""), thread->pid) > 0)
617 zoom_thread = nr_options++;
618
564 options[nr_options++] = (char *)"Exit"; 619 options[nr_options++] = (char *)"Exit";
565 620
566 choice = popup_menu(nr_options, options); 621 choice = popup_menu(nr_options, options);
@@ -570,6 +625,9 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
570 625
571 if (choice == nr_options - 1) 626 if (choice == nr_options - 1)
572 break; 627 break;
628
629 if (choice == -1)
630 continue;
573do_annotate: 631do_annotate:
574 if (choice == annotate) { 632 if (choice == annotate) {
575 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { 633 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
@@ -581,13 +639,21 @@ do_annotate:
581 } 639 }
582 map_symbol__annotate_browser(browser->selection, 640 map_symbol__annotate_browser(browser->selection,
583 input_name); 641 input_name);
584 } if (choice == zoom_dso) { 642 } else if (choice == zoom_dso) {
585 hists__filter_by_dso(hists, 643 nr_hists = hists__filter_by_dso(hists,
586 dso_filtered ? NULL : browser->selection->map->dso, 644 (dso_filtered ? NULL :
587 &session_total); 645 browser->selection->map->dso),
646 &session_total);
588 dso_filtered = !dso_filtered; 647 dso_filtered = !dso_filtered;
589 if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) 648 if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0)
590 goto out; 649 goto out;
650 } else if (choice == zoom_thread) {
651 nr_hists = hists__filter_by_thread(hists,
652 (thread_filtered ? NULL : thread),
653 &session_total);
654 thread_filtered = !thread_filtered;
655 if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0)
656 goto out;
591 } 657 }
592 } 658 }
593 err = 0; 659 err = 0;