diff options
| -rw-r--r-- | tools/perf/util/newt.c | 129 |
1 files changed, 84 insertions, 45 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index a2ba3fffe04a..509d921532ef 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
| @@ -381,53 +381,69 @@ static const void *newt__symbol_tree_get_current(newtComponent self) | |||
| 381 | return newtListboxGetCurrent(self); | 381 | return newtListboxGetCurrent(self); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | static void perf_session__selection(newtComponent self, void *data) | 384 | static void hist_browser__selection(newtComponent self, void *data) |
| 385 | { | 385 | { |
| 386 | const struct map_symbol **symbol_ptr = data; | 386 | const struct map_symbol **symbol_ptr = data; |
| 387 | *symbol_ptr = newt__symbol_tree_get_current(self); | 387 | *symbol_ptr = newt__symbol_tree_get_current(self); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | 390 | struct hist_browser { |
| 391 | u64 session_total, const char *helpline) | 391 | newtComponent form, tree; |
| 392 | const struct map_symbol *selection; | ||
| 393 | }; | ||
| 394 | |||
| 395 | static struct hist_browser *hist_browser__new(void) | ||
| 396 | { | ||
| 397 | struct hist_browser *self = malloc(sizeof(*self)); | ||
| 398 | |||
| 399 | if (self != NULL) { | ||
| 400 | char seq[] = "."; | ||
| 401 | int rows; | ||
| 402 | |||
| 403 | newtGetScreenSize(NULL, &rows); | ||
| 404 | |||
| 405 | if (symbol_conf.use_callchain) | ||
| 406 | self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, | ||
| 407 | NEWT_FLAG_SCROLL); | ||
| 408 | else | ||
| 409 | self->tree = newtListbox(0, 0, rows - 5, | ||
| 410 | (NEWT_FLAG_SCROLL | | ||
| 411 | NEWT_FLAG_RETURNEXIT)); | ||
| 412 | newtComponentAddCallback(self->tree, hist_browser__selection, | ||
| 413 | &self->selection); | ||
| 414 | } | ||
| 415 | |||
| 416 | return self; | ||
| 417 | } | ||
| 418 | |||
| 419 | static void hist_browser__delete(struct hist_browser *self) | ||
| 420 | { | ||
| 421 | newtFormDestroy(self->form); | ||
| 422 | newtPopWindow(); | ||
| 423 | free(self); | ||
| 424 | } | ||
| 425 | |||
| 426 | static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists, | ||
| 427 | u64 nr_hists, u64 session_total) | ||
| 392 | { | 428 | { |
| 429 | int max_len = 0, idx, cols, rows; | ||
| 430 | struct ui_progress *progress; | ||
| 393 | struct rb_node *nd; | 431 | struct rb_node *nd; |
| 394 | char seq[] = "."; | ||
| 395 | int rows, cols, idx; | ||
| 396 | int max_len = 0; | ||
| 397 | char str[1024]; | ||
| 398 | newtComponent form, tree; | ||
| 399 | struct newtExitStruct es; | ||
| 400 | const struct map_symbol *selection; | ||
| 401 | u64 curr_hist = 0; | 432 | u64 curr_hist = 0; |
| 402 | struct ui_progress *progress; | ||
| 403 | 433 | ||
| 404 | progress = ui_progress__new("Adding entries to the browser...", nr_hists); | 434 | progress = ui_progress__new("Adding entries to the browser...", nr_hists); |
| 405 | if (progress == NULL) | 435 | if (progress == NULL) |
| 406 | return -1; | 436 | return -1; |
| 407 | 437 | ||
| 408 | snprintf(str, sizeof(str), "Samples: %Ld", session_total); | ||
| 409 | newtDrawRootText(0, 0, str); | ||
| 410 | newtPushHelpLine(helpline); | ||
| 411 | |||
| 412 | newtGetScreenSize(&cols, &rows); | ||
| 413 | |||
| 414 | if (symbol_conf.use_callchain) | ||
| 415 | tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, | ||
| 416 | NEWT_FLAG_SCROLL); | ||
| 417 | else | ||
| 418 | tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL | | ||
| 419 | NEWT_FLAG_RETURNEXIT)); | ||
| 420 | |||
| 421 | newtComponentAddCallback(tree, perf_session__selection, &selection); | ||
| 422 | |||
| 423 | idx = 0; | 438 | idx = 0; |
| 424 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { | 439 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { |
| 425 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 440 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
| 426 | int len = hist_entry__append_browser(h, tree, session_total); | 441 | int len = hist_entry__append_browser(h, self->tree, session_total); |
| 427 | if (len > max_len) | 442 | if (len > max_len) |
| 428 | max_len = len; | 443 | max_len = len; |
| 429 | if (symbol_conf.use_callchain) | 444 | if (symbol_conf.use_callchain) |
| 430 | hist_entry__append_callchain_browser(h, tree, session_total, idx++); | 445 | hist_entry__append_callchain_browser(h, self->tree, |
| 446 | session_total, idx++); | ||
| 431 | ++curr_hist; | 447 | ++curr_hist; |
| 432 | if (curr_hist % 5) | 448 | if (curr_hist % 5) |
| 433 | ui_progress__update(progress, curr_hist); | 449 | ui_progress__update(progress, curr_hist); |
| @@ -435,27 +451,50 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | |||
| 435 | 451 | ||
| 436 | ui_progress__delete(progress); | 452 | ui_progress__delete(progress); |
| 437 | 453 | ||
| 454 | newtGetScreenSize(&cols, &rows); | ||
| 455 | |||
| 438 | if (max_len > cols) | 456 | if (max_len > cols) |
| 439 | max_len = cols - 3; | 457 | max_len = cols - 3; |
| 440 | 458 | ||
| 441 | if (!symbol_conf.use_callchain) | 459 | if (!symbol_conf.use_callchain) |
| 442 | newtListboxSetWidth(tree, max_len); | 460 | newtListboxSetWidth(self->tree, max_len); |
| 443 | 461 | ||
| 444 | newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), | 462 | newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), |
| 445 | rows - 5, "Report"); | 463 | rows - 5, "Report"); |
| 446 | form = newt_form__new(); | 464 | self->form = newt_form__new(); |
| 447 | newtFormAddHotKey(form, 'A'); | 465 | newtFormAddHotKey(self->form, 'A'); |
| 448 | newtFormAddHotKey(form, 'a'); | 466 | newtFormAddHotKey(self->form, 'a'); |
| 449 | newtFormAddHotKey(form, NEWT_KEY_RIGHT); | 467 | newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); |
| 450 | newtFormAddComponents(form, tree, NULL); | 468 | newtFormAddComponents(self->form, self->tree, NULL); |
| 451 | selection = newt__symbol_tree_get_current(tree); | 469 | self->selection = newt__symbol_tree_get_current(self->tree); |
| 470 | |||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | ||
| 475 | u64 session_total, const char *helpline) | ||
| 476 | { | ||
| 477 | struct newtExitStruct es; | ||
| 478 | char str[1024]; | ||
| 479 | int err = -1; | ||
| 480 | struct hist_browser *browser = hist_browser__new(); | ||
| 481 | |||
| 482 | if (browser == NULL) | ||
| 483 | return -1; | ||
| 484 | |||
| 485 | snprintf(str, sizeof(str), "Samples: %Ld", session_total); | ||
| 486 | newtDrawRootText(0, 0, str); | ||
| 487 | newtPushHelpLine(helpline); | ||
| 488 | |||
| 489 | if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) | ||
| 490 | goto out; | ||
| 452 | 491 | ||
| 453 | while (1) { | 492 | while (1) { |
| 454 | char annotate[512]; | 493 | char annotate[512]; |
| 455 | const char *options[2]; | 494 | const char *options[2]; |
| 456 | int nr_options = 0, choice = 0; | 495 | int nr_options = 0, choice = 0; |
| 457 | 496 | ||
| 458 | newtFormRun(form, &es); | 497 | newtFormRun(browser->form, &es); |
| 459 | if (es.reason == NEWT_EXIT_HOTKEY) { | 498 | if (es.reason == NEWT_EXIT_HOTKEY) { |
| 460 | if (toupper(es.u.key) == 'A') | 499 | if (toupper(es.u.key) == 'A') |
| 461 | goto do_annotate; | 500 | goto do_annotate; |
| @@ -469,9 +508,9 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | |||
| 469 | } | 508 | } |
| 470 | } | 509 | } |
| 471 | 510 | ||
| 472 | if (selection->sym != NULL) { | 511 | if (browser->selection->sym != NULL) { |
| 473 | snprintf(annotate, sizeof(annotate), | 512 | snprintf(annotate, sizeof(annotate), |
| 474 | "Annotate %s", selection->sym->name); | 513 | "Annotate %s", browser->selection->sym->name); |
| 475 | options[nr_options++] = annotate; | 514 | options[nr_options++] = annotate; |
| 476 | } | 515 | } |
| 477 | 516 | ||
| @@ -480,21 +519,21 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, | |||
| 480 | if (choice == nr_options - 1) | 519 | if (choice == nr_options - 1) |
| 481 | break; | 520 | break; |
| 482 | do_annotate: | 521 | do_annotate: |
| 483 | if (selection->sym != NULL && choice >= 0) { | 522 | if (browser->selection->sym != NULL && choice >= 0) { |
| 484 | if (selection->map->dso->origin == DSO__ORIG_KERNEL) { | 523 | if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { |
| 485 | newtPopHelpLine(); | 524 | newtPopHelpLine(); |
| 486 | newtPushHelpLine("No vmlinux file found, can't " | 525 | newtPushHelpLine("No vmlinux file found, can't " |
| 487 | "annotate with just a " | 526 | "annotate with just a " |
| 488 | "kallsyms file"); | 527 | "kallsyms file"); |
| 489 | continue; | 528 | continue; |
| 490 | } | 529 | } |
| 491 | map_symbol__annotate_browser(selection); | 530 | map_symbol__annotate_browser(browser->selection); |
| 492 | } | 531 | } |
| 493 | } | 532 | } |
| 494 | 533 | err = 0; | |
| 495 | newtFormDestroy(form); | 534 | out: |
| 496 | newtPopWindow(); | 535 | hist_browser__delete(browser); |
| 497 | return 0; | 536 | return err; |
| 498 | } | 537 | } |
| 499 | 538 | ||
| 500 | void setup_browser(void) | 539 | void setup_browser(void) |
