diff options
-rw-r--r-- | tools/perf/util/newt.c | 119 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 3 |
2 files changed, 90 insertions, 32 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index c93bc2a2d137..bbf725d4b38d 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
@@ -94,7 +94,7 @@ static newtComponent newt_form__new(void) | |||
94 | return self; | 94 | return self; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int popup_menu(int argc, const char *argv[]) | 97 | static int popup_menu(int argc, char * const argv[]) |
98 | { | 98 | { |
99 | struct newtExitStruct es; | 99 | struct newtExitStruct es; |
100 | int i, rc = -1, max_len = 5; | 100 | int i, rc = -1, max_len = 5; |
@@ -397,22 +397,8 @@ static struct hist_browser *hist_browser__new(void) | |||
397 | { | 397 | { |
398 | struct hist_browser *self = malloc(sizeof(*self)); | 398 | struct hist_browser *self = malloc(sizeof(*self)); |
399 | 399 | ||
400 | if (self != NULL) { | 400 | if (self != NULL) |
401 | char seq[] = "."; | 401 | self->form = NULL; |
402 | int rows; | ||
403 | |||
404 | newtGetScreenSize(NULL, &rows); | ||
405 | |||
406 | if (symbol_conf.use_callchain) | ||
407 | self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, | ||
408 | NEWT_FLAG_SCROLL); | ||
409 | else | ||
410 | self->tree = newtListbox(0, 0, rows - 5, | ||
411 | (NEWT_FLAG_SCROLL | | ||
412 | NEWT_FLAG_RETURNEXIT)); | ||
413 | newtComponentAddCallback(self->tree, hist_browser__selection, | ||
414 | &self->selection); | ||
415 | } | ||
416 | 402 | ||
417 | return self; | 403 | return self; |
418 | } | 404 | } |
@@ -431,6 +417,30 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his | |||
431 | struct ui_progress *progress; | 417 | struct ui_progress *progress; |
432 | struct rb_node *nd; | 418 | struct rb_node *nd; |
433 | u64 curr_hist = 0; | 419 | u64 curr_hist = 0; |
420 | char seq[] = "."; | ||
421 | char str[256]; | ||
422 | |||
423 | if (self->form) { | ||
424 | newtFormDestroy(self->form); | ||
425 | newtPopWindow(); | ||
426 | } | ||
427 | |||
428 | snprintf(str, sizeof(str), "Samples: %Ld ", | ||
429 | session_total); | ||
430 | newtDrawRootText(0, 0, str); | ||
431 | |||
432 | newtGetScreenSize(NULL, &rows); | ||
433 | |||
434 | if (symbol_conf.use_callchain) | ||
435 | self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, | ||
436 | NEWT_FLAG_SCROLL); | ||
437 | else | ||
438 | self->tree = newtListbox(0, 0, rows - 5, | ||
439 | (NEWT_FLAG_SCROLL | | ||
440 | NEWT_FLAG_RETURNEXIT)); | ||
441 | |||
442 | newtComponentAddCallback(self->tree, hist_browser__selection, | ||
443 | &self->selection); | ||
434 | 444 | ||
435 | progress = ui_progress__new("Adding entries to the browser...", nr_hists); | 445 | progress = ui_progress__new("Adding entries to the browser...", nr_hists); |
436 | if (progress == NULL) | 446 | if (progress == NULL) |
@@ -439,7 +449,12 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his | |||
439 | idx = 0; | 449 | idx = 0; |
440 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { | 450 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { |
441 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 451 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
442 | int len = hist_entry__append_browser(h, self->tree, session_total); | 452 | int len; |
453 | |||
454 | if (h->filtered) | ||
455 | continue; | ||
456 | |||
457 | len = hist_entry__append_browser(h, self->tree, session_total); | ||
443 | if (len > max_len) | 458 | if (len > max_len) |
444 | max_len = len; | 459 | max_len = len; |
445 | if (symbol_conf.use_callchain) | 460 | if (symbol_conf.use_callchain) |
@@ -463,6 +478,9 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his | |||
463 | newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), | 478 | newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), |
464 | rows - 5, "Report"); | 479 | rows - 5, "Report"); |
465 | self->form = newt_form__new(); | 480 | self->form = newt_form__new(); |
481 | if (self->form == NULL) | ||
482 | return -1; | ||
483 | |||
466 | newtFormAddHotKey(self->form, 'A'); | 484 | newtFormAddHotKey(self->form, 'A'); |
467 | newtFormAddHotKey(self->form, 'a'); | 485 | newtFormAddHotKey(self->form, 'a'); |
468 | newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); | 486 | newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); |
@@ -472,29 +490,50 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his | |||
472 | return 0; | 490 | return 0; |
473 | } | 491 | } |
474 | 492 | ||
493 | static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, | ||
494 | u64 *session_total) | ||
495 | { | ||
496 | struct rb_node *nd; | ||
497 | u64 nr_hists = 0; | ||
498 | |||
499 | *session_total = 0; | ||
500 | |||
501 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { | ||
502 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | ||
503 | |||
504 | if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { | ||
505 | h->filtered = true; | ||
506 | continue; | ||
507 | } | ||
508 | h->filtered = false; | ||
509 | ++nr_hists; | ||
510 | *session_total += h->count; | ||
511 | } | ||
512 | |||
513 | return nr_hists; | ||
514 | } | ||
515 | |||
475 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | 516 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, |
476 | u64 session_total, const char *helpline, | 517 | u64 session_total, const char *helpline, |
477 | const char *input_name) | 518 | const char *input_name) |
478 | { | 519 | { |
479 | struct newtExitStruct es; | 520 | struct newtExitStruct es; |
480 | char str[1024]; | 521 | bool dso_filtered = false; |
481 | int err = -1; | 522 | int err = -1; |
482 | struct hist_browser *browser = hist_browser__new(); | 523 | struct hist_browser *browser = hist_browser__new(); |
483 | 524 | ||
484 | if (browser == NULL) | 525 | if (browser == NULL) |
485 | return -1; | 526 | return -1; |
486 | 527 | ||
487 | snprintf(str, sizeof(str), "Samples: %Ld", session_total); | ||
488 | newtDrawRootText(0, 0, str); | ||
489 | newtPushHelpLine(helpline); | 528 | newtPushHelpLine(helpline); |
490 | 529 | ||
491 | if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) | 530 | if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) |
492 | goto out; | 531 | goto out; |
493 | 532 | ||
494 | while (1) { | 533 | while (1) { |
495 | char annotate[512]; | 534 | char *options[16]; |
496 | const char *options[2]; | 535 | int nr_options = 0, choice = 0, i, |
497 | int nr_options = 0, choice = 0; | 536 | annotate = -2, zoom_dso = -2; |
498 | 537 | ||
499 | newtFormRun(browser->form, &es); | 538 | newtFormRun(browser->form, &es); |
500 | if (es.reason == NEWT_EXIT_HOTKEY) { | 539 | if (es.reason == NEWT_EXIT_HOTKEY) { |
@@ -510,18 +549,29 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | |||
510 | } | 549 | } |
511 | } | 550 | } |
512 | 551 | ||
513 | if (browser->selection->sym != NULL) { | 552 | if (browser->selection->sym != NULL && |
514 | snprintf(annotate, sizeof(annotate), | 553 | asprintf(&options[nr_options], "Annotate %s", |
515 | "Annotate %s", browser->selection->sym->name); | 554 | browser->selection->sym->name) > 0) |
516 | options[nr_options++] = annotate; | 555 | annotate = nr_options++; |
517 | } | 556 | |
557 | if (browser->selection->map != NULL && | ||
558 | asprintf(&options[nr_options], "Zoom %s %s DSO", | ||
559 | dso_filtered ? "out of" : "into", | ||
560 | (browser->selection->map->dso->kernel ? "the Kernel" : | ||
561 | browser->selection->map->dso->short_name)) > 0) | ||
562 | zoom_dso = nr_options++; | ||
563 | |||
564 | options[nr_options++] = (char *)"Exit"; | ||
518 | 565 | ||
519 | options[nr_options++] = "Exit"; | ||
520 | choice = popup_menu(nr_options, options); | 566 | choice = popup_menu(nr_options, options); |
567 | |||
568 | for (i = 0; i < nr_options - 1; ++i) | ||
569 | free(options[i]); | ||
570 | |||
521 | if (choice == nr_options - 1) | 571 | if (choice == nr_options - 1) |
522 | break; | 572 | break; |
523 | do_annotate: | 573 | do_annotate: |
524 | if (browser->selection->sym != NULL && choice >= 0) { | 574 | if (choice == annotate) { |
525 | if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { | 575 | if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { |
526 | newtPopHelpLine(); | 576 | newtPopHelpLine(); |
527 | newtPushHelpLine("No vmlinux file found, can't " | 577 | newtPushHelpLine("No vmlinux file found, can't " |
@@ -531,6 +581,13 @@ do_annotate: | |||
531 | } | 581 | } |
532 | map_symbol__annotate_browser(browser->selection, | 582 | map_symbol__annotate_browser(browser->selection, |
533 | input_name); | 583 | input_name); |
584 | } if (choice == zoom_dso) { | ||
585 | hists__filter_by_dso(hists, | ||
586 | dso_filtered ? NULL : browser->selection->map->dso, | ||
587 | &session_total); | ||
588 | dso_filtered = !dso_filtered; | ||
589 | if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) | ||
590 | goto out; | ||
534 | } | 591 | } |
535 | } | 592 | } |
536 | err = 0; | 593 | err = 0; |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 5bf2b744e7b2..dce79d33e339 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -48,7 +48,8 @@ struct hist_entry { | |||
48 | struct map_symbol ms; | 48 | struct map_symbol ms; |
49 | u64 ip; | 49 | u64 ip; |
50 | char level; | 50 | char level; |
51 | struct symbol *parent; | 51 | bool filtered; |
52 | struct symbol *parent; | ||
52 | union { | 53 | union { |
53 | unsigned long position; | 54 | unsigned long position; |
54 | struct hist_entry *pair; | 55 | struct hist_entry *pair; |