diff options
Diffstat (limited to 'tools/perf/util/newt.c')
-rw-r--r-- | tools/perf/util/newt.c | 82 |
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 | ||
493 | enum hist_filter { | ||
494 | HIST_FILTER__DSO, | ||
495 | HIST_FILTER__THREAD, | ||
496 | }; | ||
497 | |||
493 | static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, | 498 | static 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 | ||
521 | static 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 | |||
544 | static 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; | ||
559 | out: | ||
560 | return *(struct thread **)(self->selection + 1); | ||
561 | } | ||
562 | |||
516 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | 563 | int 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; | ||
573 | do_annotate: | 631 | do_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; |