.. | .. |
---|
2 | 2 | #include <errno.h> |
---|
3 | 3 | #include <inttypes.h> |
---|
4 | 4 | #include <regex.h> |
---|
| 5 | +#include <stdlib.h> |
---|
5 | 6 | #include <linux/mman.h> |
---|
| 7 | +#include <linux/time64.h> |
---|
| 8 | +#include "debug.h" |
---|
| 9 | +#include "dso.h" |
---|
6 | 10 | #include "sort.h" |
---|
7 | 11 | #include "hist.h" |
---|
| 12 | +#include "cacheline.h" |
---|
8 | 13 | #include "comm.h" |
---|
| 14 | +#include "map.h" |
---|
| 15 | +#include "maps.h" |
---|
9 | 16 | #include "symbol.h" |
---|
| 17 | +#include "map_symbol.h" |
---|
| 18 | +#include "branch.h" |
---|
10 | 19 | #include "thread.h" |
---|
11 | 20 | #include "evsel.h" |
---|
12 | 21 | #include "evlist.h" |
---|
| 22 | +#include "srcline.h" |
---|
13 | 23 | #include "strlist.h" |
---|
| 24 | +#include "strbuf.h" |
---|
14 | 25 | #include <traceevent/event-parse.h> |
---|
15 | 26 | #include "mem-events.h" |
---|
| 27 | +#include "annotate.h" |
---|
| 28 | +#include "time-utils.h" |
---|
| 29 | +#include "cgroup.h" |
---|
| 30 | +#include "machine.h" |
---|
16 | 31 | #include <linux/kernel.h> |
---|
| 32 | +#include <linux/string.h> |
---|
17 | 33 | |
---|
18 | 34 | regex_t parent_regex; |
---|
19 | 35 | const char default_parent_pattern[] = "^sys_|^do_page_fault"; |
---|
.. | .. |
---|
36 | 52 | * -t, --field-separator |
---|
37 | 53 | * |
---|
38 | 54 | * option, that uses a special separator character and don't pad with spaces, |
---|
39 | | - * replacing all occurances of this separator in symbol names (and other |
---|
| 55 | + * replacing all occurrences of this separator in symbol names (and other |
---|
40 | 56 | * output) with a '.' character, that thus it's the only non valid separator. |
---|
41 | 57 | */ |
---|
42 | 58 | static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) |
---|
.. | .. |
---|
221 | 237 | return (int64_t)(right_ip - left_ip); |
---|
222 | 238 | } |
---|
223 | 239 | |
---|
224 | | -static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) |
---|
| 240 | +int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) |
---|
225 | 241 | { |
---|
226 | 242 | if (!sym_l || !sym_r) |
---|
227 | 243 | return cmp_null(sym_l, sym_r); |
---|
.. | .. |
---|
274 | 290 | return strcmp(right->ms.sym->name, left->ms.sym->name); |
---|
275 | 291 | } |
---|
276 | 292 | |
---|
277 | | -static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, |
---|
| 293 | +static int _hist_entry__sym_snprintf(struct map_symbol *ms, |
---|
278 | 294 | u64 ip, char level, char *bf, size_t size, |
---|
279 | 295 | unsigned int width) |
---|
280 | 296 | { |
---|
| 297 | + struct symbol *sym = ms->sym; |
---|
| 298 | + struct map *map = ms->map; |
---|
281 | 299 | size_t ret = 0; |
---|
282 | 300 | |
---|
283 | 301 | if (verbose > 0) { |
---|
284 | 302 | char o = map ? dso__symtab_origin(map->dso) : '!'; |
---|
| 303 | + u64 rip = ip; |
---|
| 304 | + |
---|
| 305 | + if (map && map->dso && map->dso->kernel |
---|
| 306 | + && map->dso->adjust_symbols) |
---|
| 307 | + rip = map->unmap_ip(map, ip); |
---|
| 308 | + |
---|
285 | 309 | ret += repsep_snprintf(bf, size, "%-#*llx %c ", |
---|
286 | | - BITS_PER_LONG / 4 + 2, ip, o); |
---|
| 310 | + BITS_PER_LONG / 4 + 2, rip, o); |
---|
287 | 311 | } |
---|
288 | 312 | |
---|
289 | 313 | ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); |
---|
.. | .. |
---|
309 | 333 | return ret; |
---|
310 | 334 | } |
---|
311 | 335 | |
---|
312 | | -static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, |
---|
313 | | - size_t size, unsigned int width) |
---|
| 336 | +int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) |
---|
314 | 337 | { |
---|
315 | | - return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip, |
---|
| 338 | + return _hist_entry__sym_snprintf(&he->ms, he->ip, |
---|
316 | 339 | he->level, bf, size, width); |
---|
317 | 340 | } |
---|
318 | 341 | |
---|
.. | .. |
---|
373 | 396 | |
---|
374 | 397 | static char *addr_map_symbol__srcline(struct addr_map_symbol *ams) |
---|
375 | 398 | { |
---|
376 | | - return map__srcline(ams->map, ams->al_addr, ams->sym); |
---|
| 399 | + return map__srcline(ams->ms.map, ams->al_addr, ams->ms.sym); |
---|
377 | 400 | } |
---|
378 | 401 | |
---|
379 | 402 | static int64_t |
---|
.. | .. |
---|
426 | 449 | .se_cmp = sort__srcline_to_cmp, |
---|
427 | 450 | .se_snprintf = hist_entry__srcline_to_snprintf, |
---|
428 | 451 | .se_width_idx = HISTC_SRCLINE_TO, |
---|
| 452 | +}; |
---|
| 453 | + |
---|
| 454 | +static int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf, |
---|
| 455 | + size_t size, unsigned int width) |
---|
| 456 | +{ |
---|
| 457 | + |
---|
| 458 | + struct symbol *sym = he->ms.sym; |
---|
| 459 | + struct annotation *notes; |
---|
| 460 | + double ipc = 0.0, coverage = 0.0; |
---|
| 461 | + char tmp[64]; |
---|
| 462 | + |
---|
| 463 | + if (!sym) |
---|
| 464 | + return repsep_snprintf(bf, size, "%-*s", width, "-"); |
---|
| 465 | + |
---|
| 466 | + notes = symbol__annotation(sym); |
---|
| 467 | + |
---|
| 468 | + if (notes->hit_cycles) |
---|
| 469 | + ipc = notes->hit_insn / ((double)notes->hit_cycles); |
---|
| 470 | + |
---|
| 471 | + if (notes->total_insn) { |
---|
| 472 | + coverage = notes->cover_insn * 100.0 / |
---|
| 473 | + ((double)notes->total_insn); |
---|
| 474 | + } |
---|
| 475 | + |
---|
| 476 | + snprintf(tmp, sizeof(tmp), "%-5.2f [%5.1f%%]", ipc, coverage); |
---|
| 477 | + return repsep_snprintf(bf, size, "%-*s", width, tmp); |
---|
| 478 | +} |
---|
| 479 | + |
---|
| 480 | +struct sort_entry sort_sym_ipc = { |
---|
| 481 | + .se_header = "IPC [IPC Coverage]", |
---|
| 482 | + .se_cmp = sort__sym_cmp, |
---|
| 483 | + .se_snprintf = hist_entry__sym_ipc_snprintf, |
---|
| 484 | + .se_width_idx = HISTC_SYMBOL_IPC, |
---|
| 485 | +}; |
---|
| 486 | + |
---|
| 487 | +static int hist_entry__sym_ipc_null_snprintf(struct hist_entry *he |
---|
| 488 | + __maybe_unused, |
---|
| 489 | + char *bf, size_t size, |
---|
| 490 | + unsigned int width) |
---|
| 491 | +{ |
---|
| 492 | + char tmp[64]; |
---|
| 493 | + |
---|
| 494 | + snprintf(tmp, sizeof(tmp), "%-5s %2s", "-", "-"); |
---|
| 495 | + return repsep_snprintf(bf, size, "%-*s", width, tmp); |
---|
| 496 | +} |
---|
| 497 | + |
---|
| 498 | +struct sort_entry sort_sym_ipc_null = { |
---|
| 499 | + .se_header = "IPC [IPC Coverage]", |
---|
| 500 | + .se_cmp = sort__sym_cmp, |
---|
| 501 | + .se_snprintf = hist_entry__sym_ipc_null_snprintf, |
---|
| 502 | + .se_width_idx = HISTC_SYMBOL_IPC, |
---|
429 | 503 | }; |
---|
430 | 504 | |
---|
431 | 505 | /* --sort srcfile */ |
---|
.. | .. |
---|
569 | 643 | .se_width_idx = HISTC_CGROUP_ID, |
---|
570 | 644 | }; |
---|
571 | 645 | |
---|
| 646 | +/* --sort cgroup */ |
---|
| 647 | + |
---|
| 648 | +static int64_t |
---|
| 649 | +sort__cgroup_cmp(struct hist_entry *left, struct hist_entry *right) |
---|
| 650 | +{ |
---|
| 651 | + return right->cgroup - left->cgroup; |
---|
| 652 | +} |
---|
| 653 | + |
---|
| 654 | +static int hist_entry__cgroup_snprintf(struct hist_entry *he, |
---|
| 655 | + char *bf, size_t size, |
---|
| 656 | + unsigned int width __maybe_unused) |
---|
| 657 | +{ |
---|
| 658 | + const char *cgrp_name = "N/A"; |
---|
| 659 | + |
---|
| 660 | + if (he->cgroup) { |
---|
| 661 | + struct cgroup *cgrp = cgroup__find(he->ms.maps->machine->env, |
---|
| 662 | + he->cgroup); |
---|
| 663 | + if (cgrp != NULL) |
---|
| 664 | + cgrp_name = cgrp->name; |
---|
| 665 | + else |
---|
| 666 | + cgrp_name = "unknown"; |
---|
| 667 | + } |
---|
| 668 | + |
---|
| 669 | + return repsep_snprintf(bf, size, "%s", cgrp_name); |
---|
| 670 | +} |
---|
| 671 | + |
---|
| 672 | +struct sort_entry sort_cgroup = { |
---|
| 673 | + .se_header = "Cgroup", |
---|
| 674 | + .se_cmp = sort__cgroup_cmp, |
---|
| 675 | + .se_snprintf = hist_entry__cgroup_snprintf, |
---|
| 676 | + .se_width_idx = HISTC_CGROUP, |
---|
| 677 | +}; |
---|
| 678 | + |
---|
572 | 679 | /* --sort socket */ |
---|
573 | 680 | |
---|
574 | 681 | static int64_t |
---|
.. | .. |
---|
601 | 708 | .se_width_idx = HISTC_SOCKET, |
---|
602 | 709 | }; |
---|
603 | 710 | |
---|
| 711 | +/* --sort time */ |
---|
| 712 | + |
---|
| 713 | +static int64_t |
---|
| 714 | +sort__time_cmp(struct hist_entry *left, struct hist_entry *right) |
---|
| 715 | +{ |
---|
| 716 | + return right->time - left->time; |
---|
| 717 | +} |
---|
| 718 | + |
---|
| 719 | +static int hist_entry__time_snprintf(struct hist_entry *he, char *bf, |
---|
| 720 | + size_t size, unsigned int width) |
---|
| 721 | +{ |
---|
| 722 | + char he_time[32]; |
---|
| 723 | + |
---|
| 724 | + if (symbol_conf.nanosecs) |
---|
| 725 | + timestamp__scnprintf_nsec(he->time, he_time, |
---|
| 726 | + sizeof(he_time)); |
---|
| 727 | + else |
---|
| 728 | + timestamp__scnprintf_usec(he->time, he_time, |
---|
| 729 | + sizeof(he_time)); |
---|
| 730 | + |
---|
| 731 | + return repsep_snprintf(bf, size, "%-.*s", width, he_time); |
---|
| 732 | +} |
---|
| 733 | + |
---|
| 734 | +struct sort_entry sort_time = { |
---|
| 735 | + .se_header = "Time", |
---|
| 736 | + .se_cmp = sort__time_cmp, |
---|
| 737 | + .se_snprintf = hist_entry__time_snprintf, |
---|
| 738 | + .se_width_idx = HISTC_TIME, |
---|
| 739 | +}; |
---|
| 740 | + |
---|
604 | 741 | /* --sort trace */ |
---|
605 | 742 | |
---|
606 | 743 | static char *get_trace_output(struct hist_entry *he) |
---|
607 | 744 | { |
---|
608 | 745 | struct trace_seq seq; |
---|
609 | | - struct perf_evsel *evsel; |
---|
| 746 | + struct evsel *evsel; |
---|
610 | 747 | struct tep_record rec = { |
---|
611 | 748 | .data = he->raw_data, |
---|
612 | 749 | .size = he->raw_size, |
---|
.. | .. |
---|
619 | 756 | tep_print_fields(&seq, he->raw_data, he->raw_size, |
---|
620 | 757 | evsel->tp_format); |
---|
621 | 758 | } else { |
---|
622 | | - tep_event_info(&seq, evsel->tp_format, &rec); |
---|
| 759 | + tep_print_event(evsel->tp_format->tep, |
---|
| 760 | + &seq, &rec, "%s", TEP_PRINT_INFO); |
---|
623 | 761 | } |
---|
624 | 762 | /* |
---|
625 | 763 | * Trim the buffer, it starts at 4KB and we're not going to |
---|
.. | .. |
---|
631 | 769 | static int64_t |
---|
632 | 770 | sort__trace_cmp(struct hist_entry *left, struct hist_entry *right) |
---|
633 | 771 | { |
---|
634 | | - struct perf_evsel *evsel; |
---|
| 772 | + struct evsel *evsel; |
---|
635 | 773 | |
---|
636 | 774 | evsel = hists_to_evsel(left->hists); |
---|
637 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
---|
| 775 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) |
---|
638 | 776 | return 0; |
---|
639 | 777 | |
---|
640 | 778 | if (left->trace_output == NULL) |
---|
.. | .. |
---|
648 | 786 | static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, |
---|
649 | 787 | size_t size, unsigned int width) |
---|
650 | 788 | { |
---|
651 | | - struct perf_evsel *evsel; |
---|
| 789 | + struct evsel *evsel; |
---|
652 | 790 | |
---|
653 | 791 | evsel = hists_to_evsel(he->hists); |
---|
654 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
---|
| 792 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) |
---|
655 | 793 | return scnprintf(bf, size, "%-.*s", width, "N/A"); |
---|
656 | 794 | |
---|
657 | 795 | if (he->trace_output == NULL) |
---|
.. | .. |
---|
674 | 812 | if (!left->branch_info || !right->branch_info) |
---|
675 | 813 | return cmp_null(left->branch_info, right->branch_info); |
---|
676 | 814 | |
---|
677 | | - return _sort__dso_cmp(left->branch_info->from.map, |
---|
678 | | - right->branch_info->from.map); |
---|
| 815 | + return _sort__dso_cmp(left->branch_info->from.ms.map, |
---|
| 816 | + right->branch_info->from.ms.map); |
---|
679 | 817 | } |
---|
680 | 818 | |
---|
681 | 819 | static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, |
---|
682 | 820 | size_t size, unsigned int width) |
---|
683 | 821 | { |
---|
684 | 822 | if (he->branch_info) |
---|
685 | | - return _hist_entry__dso_snprintf(he->branch_info->from.map, |
---|
| 823 | + return _hist_entry__dso_snprintf(he->branch_info->from.ms.map, |
---|
686 | 824 | bf, size, width); |
---|
687 | 825 | else |
---|
688 | 826 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); |
---|
.. | .. |
---|
696 | 834 | if (type != HIST_FILTER__DSO) |
---|
697 | 835 | return -1; |
---|
698 | 836 | |
---|
699 | | - return dso && (!he->branch_info || !he->branch_info->from.map || |
---|
700 | | - he->branch_info->from.map->dso != dso); |
---|
| 837 | + return dso && (!he->branch_info || !he->branch_info->from.ms.map || |
---|
| 838 | + he->branch_info->from.ms.map->dso != dso); |
---|
701 | 839 | } |
---|
702 | 840 | |
---|
703 | 841 | static int64_t |
---|
.. | .. |
---|
706 | 844 | if (!left->branch_info || !right->branch_info) |
---|
707 | 845 | return cmp_null(left->branch_info, right->branch_info); |
---|
708 | 846 | |
---|
709 | | - return _sort__dso_cmp(left->branch_info->to.map, |
---|
710 | | - right->branch_info->to.map); |
---|
| 847 | + return _sort__dso_cmp(left->branch_info->to.ms.map, |
---|
| 848 | + right->branch_info->to.ms.map); |
---|
711 | 849 | } |
---|
712 | 850 | |
---|
713 | 851 | static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, |
---|
714 | 852 | size_t size, unsigned int width) |
---|
715 | 853 | { |
---|
716 | 854 | if (he->branch_info) |
---|
717 | | - return _hist_entry__dso_snprintf(he->branch_info->to.map, |
---|
| 855 | + return _hist_entry__dso_snprintf(he->branch_info->to.ms.map, |
---|
718 | 856 | bf, size, width); |
---|
719 | 857 | else |
---|
720 | 858 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); |
---|
.. | .. |
---|
728 | 866 | if (type != HIST_FILTER__DSO) |
---|
729 | 867 | return -1; |
---|
730 | 868 | |
---|
731 | | - return dso && (!he->branch_info || !he->branch_info->to.map || |
---|
732 | | - he->branch_info->to.map->dso != dso); |
---|
| 869 | + return dso && (!he->branch_info || !he->branch_info->to.ms.map || |
---|
| 870 | + he->branch_info->to.ms.map->dso != dso); |
---|
733 | 871 | } |
---|
734 | 872 | |
---|
735 | 873 | static int64_t |
---|
736 | 874 | sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) |
---|
737 | 875 | { |
---|
738 | | - struct addr_map_symbol *from_l = &left->branch_info->from; |
---|
739 | | - struct addr_map_symbol *from_r = &right->branch_info->from; |
---|
| 876 | + struct addr_map_symbol *from_l, *from_r; |
---|
740 | 877 | |
---|
741 | 878 | if (!left->branch_info || !right->branch_info) |
---|
742 | 879 | return cmp_null(left->branch_info, right->branch_info); |
---|
.. | .. |
---|
744 | 881 | from_l = &left->branch_info->from; |
---|
745 | 882 | from_r = &right->branch_info->from; |
---|
746 | 883 | |
---|
747 | | - if (!from_l->sym && !from_r->sym) |
---|
| 884 | + if (!from_l->ms.sym && !from_r->ms.sym) |
---|
748 | 885 | return _sort__addr_cmp(from_l->addr, from_r->addr); |
---|
749 | 886 | |
---|
750 | | - return _sort__sym_cmp(from_l->sym, from_r->sym); |
---|
| 887 | + return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym); |
---|
751 | 888 | } |
---|
752 | 889 | |
---|
753 | 890 | static int64_t |
---|
.. | .. |
---|
761 | 898 | to_l = &left->branch_info->to; |
---|
762 | 899 | to_r = &right->branch_info->to; |
---|
763 | 900 | |
---|
764 | | - if (!to_l->sym && !to_r->sym) |
---|
| 901 | + if (!to_l->ms.sym && !to_r->ms.sym) |
---|
765 | 902 | return _sort__addr_cmp(to_l->addr, to_r->addr); |
---|
766 | 903 | |
---|
767 | | - return _sort__sym_cmp(to_l->sym, to_r->sym); |
---|
| 904 | + return _sort__sym_cmp(to_l->ms.sym, to_r->ms.sym); |
---|
768 | 905 | } |
---|
769 | 906 | |
---|
770 | 907 | static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, |
---|
.. | .. |
---|
773 | 910 | if (he->branch_info) { |
---|
774 | 911 | struct addr_map_symbol *from = &he->branch_info->from; |
---|
775 | 912 | |
---|
776 | | - return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, |
---|
| 913 | + return _hist_entry__sym_snprintf(&from->ms, from->al_addr, |
---|
777 | 914 | he->level, bf, size, width); |
---|
778 | 915 | } |
---|
779 | 916 | |
---|
.. | .. |
---|
786 | 923 | if (he->branch_info) { |
---|
787 | 924 | struct addr_map_symbol *to = &he->branch_info->to; |
---|
788 | 925 | |
---|
789 | | - return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, |
---|
| 926 | + return _hist_entry__sym_snprintf(&to->ms, to->al_addr, |
---|
790 | 927 | he->level, bf, size, width); |
---|
791 | 928 | } |
---|
792 | 929 | |
---|
.. | .. |
---|
801 | 938 | if (type != HIST_FILTER__SYMBOL) |
---|
802 | 939 | return -1; |
---|
803 | 940 | |
---|
804 | | - return sym && !(he->branch_info && he->branch_info->from.sym && |
---|
805 | | - strstr(he->branch_info->from.sym->name, sym)); |
---|
| 941 | + return sym && !(he->branch_info && he->branch_info->from.ms.sym && |
---|
| 942 | + strstr(he->branch_info->from.ms.sym->name, sym)); |
---|
806 | 943 | } |
---|
807 | 944 | |
---|
808 | 945 | static int hist_entry__sym_to_filter(struct hist_entry *he, int type, |
---|
.. | .. |
---|
813 | 950 | if (type != HIST_FILTER__SYMBOL) |
---|
814 | 951 | return -1; |
---|
815 | 952 | |
---|
816 | | - return sym && !(he->branch_info && he->branch_info->to.sym && |
---|
817 | | - strstr(he->branch_info->to.sym->name, sym)); |
---|
| 953 | + return sym && !(he->branch_info && he->branch_info->to.ms.sym && |
---|
| 954 | + strstr(he->branch_info->to.ms.sym->name, sym)); |
---|
818 | 955 | } |
---|
819 | 956 | |
---|
820 | 957 | struct sort_entry sort_dso_from = { |
---|
.. | .. |
---|
922 | 1059 | size_t size, unsigned int width) |
---|
923 | 1060 | { |
---|
924 | 1061 | uint64_t addr = 0; |
---|
925 | | - struct map *map = NULL; |
---|
926 | | - struct symbol *sym = NULL; |
---|
| 1062 | + struct map_symbol *ms = NULL; |
---|
927 | 1063 | |
---|
928 | 1064 | if (he->mem_info) { |
---|
929 | 1065 | addr = he->mem_info->daddr.addr; |
---|
930 | | - map = he->mem_info->daddr.map; |
---|
931 | | - sym = he->mem_info->daddr.sym; |
---|
| 1066 | + ms = &he->mem_info->daddr.ms; |
---|
932 | 1067 | } |
---|
933 | | - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, |
---|
934 | | - width); |
---|
| 1068 | + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); |
---|
935 | 1069 | } |
---|
936 | 1070 | |
---|
937 | 1071 | int64_t |
---|
.. | .. |
---|
951 | 1085 | size_t size, unsigned int width) |
---|
952 | 1086 | { |
---|
953 | 1087 | uint64_t addr = 0; |
---|
954 | | - struct map *map = NULL; |
---|
955 | | - struct symbol *sym = NULL; |
---|
| 1088 | + struct map_symbol *ms = NULL; |
---|
956 | 1089 | |
---|
957 | 1090 | if (he->mem_info) { |
---|
958 | 1091 | addr = he->mem_info->iaddr.addr; |
---|
959 | | - map = he->mem_info->iaddr.map; |
---|
960 | | - sym = he->mem_info->iaddr.sym; |
---|
| 1092 | + ms = &he->mem_info->iaddr.ms; |
---|
961 | 1093 | } |
---|
962 | | - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, |
---|
963 | | - width); |
---|
| 1094 | + return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); |
---|
964 | 1095 | } |
---|
965 | 1096 | |
---|
966 | 1097 | static int64_t |
---|
.. | .. |
---|
970 | 1101 | struct map *map_r = NULL; |
---|
971 | 1102 | |
---|
972 | 1103 | if (left->mem_info) |
---|
973 | | - map_l = left->mem_info->daddr.map; |
---|
| 1104 | + map_l = left->mem_info->daddr.ms.map; |
---|
974 | 1105 | if (right->mem_info) |
---|
975 | | - map_r = right->mem_info->daddr.map; |
---|
| 1106 | + map_r = right->mem_info->daddr.ms.map; |
---|
976 | 1107 | |
---|
977 | 1108 | return _sort__dso_cmp(map_l, map_r); |
---|
978 | 1109 | } |
---|
.. | .. |
---|
983 | 1114 | struct map *map = NULL; |
---|
984 | 1115 | |
---|
985 | 1116 | if (he->mem_info) |
---|
986 | | - map = he->mem_info->daddr.map; |
---|
| 1117 | + map = he->mem_info->daddr.ms.map; |
---|
987 | 1118 | |
---|
988 | 1119 | return _hist_entry__dso_snprintf(map, bf, size, width); |
---|
989 | 1120 | } |
---|
.. | .. |
---|
1105 | 1236 | { |
---|
1106 | 1237 | u64 l, r; |
---|
1107 | 1238 | struct map *l_map, *r_map; |
---|
| 1239 | + int rc; |
---|
1108 | 1240 | |
---|
1109 | 1241 | if (!left->mem_info) return -1; |
---|
1110 | 1242 | if (!right->mem_info) return 1; |
---|
.. | .. |
---|
1113 | 1245 | if (left->cpumode > right->cpumode) return -1; |
---|
1114 | 1246 | if (left->cpumode < right->cpumode) return 1; |
---|
1115 | 1247 | |
---|
1116 | | - l_map = left->mem_info->daddr.map; |
---|
1117 | | - r_map = right->mem_info->daddr.map; |
---|
| 1248 | + l_map = left->mem_info->daddr.ms.map; |
---|
| 1249 | + r_map = right->mem_info->daddr.ms.map; |
---|
1118 | 1250 | |
---|
1119 | 1251 | /* if both are NULL, jump to sort on al_addr instead */ |
---|
1120 | 1252 | if (!l_map && !r_map) |
---|
.. | .. |
---|
1123 | 1255 | if (!l_map) return -1; |
---|
1124 | 1256 | if (!r_map) return 1; |
---|
1125 | 1257 | |
---|
1126 | | - if (l_map->maj > r_map->maj) return -1; |
---|
1127 | | - if (l_map->maj < r_map->maj) return 1; |
---|
1128 | | - |
---|
1129 | | - if (l_map->min > r_map->min) return -1; |
---|
1130 | | - if (l_map->min < r_map->min) return 1; |
---|
1131 | | - |
---|
1132 | | - if (l_map->ino > r_map->ino) return -1; |
---|
1133 | | - if (l_map->ino < r_map->ino) return 1; |
---|
1134 | | - |
---|
1135 | | - if (l_map->ino_generation > r_map->ino_generation) return -1; |
---|
1136 | | - if (l_map->ino_generation < r_map->ino_generation) return 1; |
---|
1137 | | - |
---|
| 1258 | + rc = dso__cmp_id(l_map->dso, r_map->dso); |
---|
| 1259 | + if (rc) |
---|
| 1260 | + return rc; |
---|
1138 | 1261 | /* |
---|
1139 | 1262 | * Addresses with no major/minor numbers are assumed to be |
---|
1140 | 1263 | * anonymous in userspace. Sort those on pid then address. |
---|
.. | .. |
---|
1145 | 1268 | |
---|
1146 | 1269 | if ((left->cpumode != PERF_RECORD_MISC_KERNEL) && |
---|
1147 | 1270 | (!(l_map->flags & MAP_SHARED)) && |
---|
1148 | | - !l_map->maj && !l_map->min && !l_map->ino && |
---|
1149 | | - !l_map->ino_generation) { |
---|
| 1271 | + !l_map->dso->id.maj && !l_map->dso->id.min && |
---|
| 1272 | + !l_map->dso->id.ino && !l_map->dso->id.ino_generation) { |
---|
1150 | 1273 | /* userspace anonymous */ |
---|
1151 | 1274 | |
---|
1152 | 1275 | if (left->thread->pid_ > right->thread->pid_) return -1; |
---|
.. | .. |
---|
1169 | 1292 | { |
---|
1170 | 1293 | |
---|
1171 | 1294 | uint64_t addr = 0; |
---|
1172 | | - struct map *map = NULL; |
---|
1173 | | - struct symbol *sym = NULL; |
---|
| 1295 | + struct map_symbol *ms = NULL; |
---|
1174 | 1296 | char level = he->level; |
---|
1175 | 1297 | |
---|
1176 | 1298 | if (he->mem_info) { |
---|
| 1299 | + struct map *map = he->mem_info->daddr.ms.map; |
---|
| 1300 | + |
---|
1177 | 1301 | addr = cl_address(he->mem_info->daddr.al_addr); |
---|
1178 | | - map = he->mem_info->daddr.map; |
---|
1179 | | - sym = he->mem_info->daddr.sym; |
---|
| 1302 | + ms = &he->mem_info->daddr.ms; |
---|
1180 | 1303 | |
---|
1181 | 1304 | /* print [s] for shared data mmaps */ |
---|
1182 | 1305 | if ((he->cpumode != PERF_RECORD_MISC_KERNEL) && |
---|
1183 | 1306 | map && !(map->prot & PROT_EXEC) && |
---|
1184 | 1307 | (map->flags & MAP_SHARED) && |
---|
1185 | | - (map->maj || map->min || map->ino || |
---|
1186 | | - map->ino_generation)) |
---|
| 1308 | + (map->dso->id.maj || map->dso->id.min || |
---|
| 1309 | + map->dso->id.ino || map->dso->id.ino_generation)) |
---|
1187 | 1310 | level = 's'; |
---|
1188 | 1311 | else if (!map) |
---|
1189 | 1312 | level = 'X'; |
---|
1190 | 1313 | } |
---|
1191 | | - return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size, |
---|
1192 | | - width); |
---|
| 1314 | + return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width); |
---|
1193 | 1315 | } |
---|
1194 | 1316 | |
---|
1195 | 1317 | struct sort_entry sort_mispredict = { |
---|
.. | .. |
---|
1579 | 1701 | DIM(SORT_TRACE, "trace", sort_trace), |
---|
1580 | 1702 | DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), |
---|
1581 | 1703 | DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), |
---|
| 1704 | + DIM(SORT_CGROUP, "cgroup", sort_cgroup), |
---|
1582 | 1705 | DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), |
---|
| 1706 | + DIM(SORT_SYM_IPC_NULL, "ipc_null", sort_sym_ipc_null), |
---|
| 1707 | + DIM(SORT_TIME, "time", sort_time), |
---|
1583 | 1708 | }; |
---|
1584 | 1709 | |
---|
1585 | 1710 | #undef DIM |
---|
.. | .. |
---|
1597 | 1722 | DIM(SORT_CYCLES, "cycles", sort_cycles), |
---|
1598 | 1723 | DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from), |
---|
1599 | 1724 | DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to), |
---|
| 1725 | + DIM(SORT_SYM_IPC, "ipc_lbr", sort_sym_ipc), |
---|
1600 | 1726 | }; |
---|
1601 | 1727 | |
---|
1602 | 1728 | #undef DIM |
---|
.. | .. |
---|
1889 | 2015 | |
---|
1890 | 2016 | struct hpp_dynamic_entry { |
---|
1891 | 2017 | struct perf_hpp_fmt hpp; |
---|
1892 | | - struct perf_evsel *evsel; |
---|
1893 | | - struct format_field *field; |
---|
| 2018 | + struct evsel *evsel; |
---|
| 2019 | + struct tep_format_field *field; |
---|
1894 | 2020 | unsigned dynamic_len; |
---|
1895 | 2021 | bool raw_trace; |
---|
1896 | 2022 | }; |
---|
.. | .. |
---|
1905 | 2031 | if (namelen > len) |
---|
1906 | 2032 | len = namelen; |
---|
1907 | 2033 | |
---|
1908 | | - if (!(hde->field->flags & FIELD_IS_STRING)) { |
---|
| 2034 | + if (!(hde->field->flags & TEP_FIELD_IS_STRING)) { |
---|
1909 | 2035 | /* length for print hex numbers */ |
---|
1910 | 2036 | fieldlen = hde->field->size * 2 + 2; |
---|
1911 | 2037 | } |
---|
.. | .. |
---|
1921 | 2047 | struct hist_entry *he) |
---|
1922 | 2048 | { |
---|
1923 | 2049 | char *str, *pos; |
---|
1924 | | - struct format_field *field = hde->field; |
---|
| 2050 | + struct tep_format_field *field = hde->field; |
---|
1925 | 2051 | size_t namelen; |
---|
1926 | 2052 | bool last = false; |
---|
1927 | 2053 | |
---|
.. | .. |
---|
2006 | 2132 | struct hpp_dynamic_entry *hde; |
---|
2007 | 2133 | size_t len = fmt->user_len; |
---|
2008 | 2134 | char *str, *pos; |
---|
2009 | | - struct format_field *field; |
---|
| 2135 | + struct tep_format_field *field; |
---|
2010 | 2136 | size_t namelen; |
---|
2011 | 2137 | bool last = false; |
---|
2012 | 2138 | int ret; |
---|
.. | .. |
---|
2066 | 2192 | struct hist_entry *a, struct hist_entry *b) |
---|
2067 | 2193 | { |
---|
2068 | 2194 | struct hpp_dynamic_entry *hde; |
---|
2069 | | - struct format_field *field; |
---|
| 2195 | + struct tep_format_field *field; |
---|
2070 | 2196 | unsigned offset, size; |
---|
2071 | 2197 | |
---|
2072 | 2198 | hde = container_of(fmt, struct hpp_dynamic_entry, hpp); |
---|
.. | .. |
---|
2077 | 2203 | } |
---|
2078 | 2204 | |
---|
2079 | 2205 | field = hde->field; |
---|
2080 | | - if (field->flags & FIELD_IS_DYNAMIC) { |
---|
| 2206 | + if (field->flags & TEP_FIELD_IS_DYNAMIC) { |
---|
2081 | 2207 | unsigned long long dyn; |
---|
2082 | 2208 | |
---|
2083 | 2209 | tep_read_number_field(field, a->raw_data, &dyn); |
---|
.. | .. |
---|
2123 | 2249 | } |
---|
2124 | 2250 | |
---|
2125 | 2251 | static struct hpp_dynamic_entry * |
---|
2126 | | -__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, |
---|
| 2252 | +__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field, |
---|
2127 | 2253 | int level) |
---|
2128 | 2254 | { |
---|
2129 | 2255 | struct hpp_dynamic_entry *hde; |
---|
.. | .. |
---|
2218 | 2344 | * 2. full event name (e.g. sched:sched_switch) |
---|
2219 | 2345 | * 3. partial event name (should not contain ':') |
---|
2220 | 2346 | */ |
---|
2221 | | -static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name) |
---|
| 2347 | +static struct evsel *find_evsel(struct evlist *evlist, char *event_name) |
---|
2222 | 2348 | { |
---|
2223 | | - struct perf_evsel *evsel = NULL; |
---|
2224 | | - struct perf_evsel *pos; |
---|
| 2349 | + struct evsel *evsel = NULL; |
---|
| 2350 | + struct evsel *pos; |
---|
2225 | 2351 | bool full_name; |
---|
2226 | 2352 | |
---|
2227 | 2353 | /* case 1 */ |
---|
2228 | 2354 | if (event_name[0] == '%') { |
---|
2229 | 2355 | int nr = strtol(event_name+1, NULL, 0); |
---|
2230 | 2356 | |
---|
2231 | | - if (nr > evlist->nr_entries) |
---|
| 2357 | + if (nr > evlist->core.nr_entries) |
---|
2232 | 2358 | return NULL; |
---|
2233 | 2359 | |
---|
2234 | | - evsel = perf_evlist__first(evlist); |
---|
| 2360 | + evsel = evlist__first(evlist); |
---|
2235 | 2361 | while (--nr > 0) |
---|
2236 | | - evsel = perf_evsel__next(evsel); |
---|
| 2362 | + evsel = evsel__next(evsel); |
---|
2237 | 2363 | |
---|
2238 | 2364 | return evsel; |
---|
2239 | 2365 | } |
---|
.. | .. |
---|
2257 | 2383 | return evsel; |
---|
2258 | 2384 | } |
---|
2259 | 2385 | |
---|
2260 | | -static int __dynamic_dimension__add(struct perf_evsel *evsel, |
---|
2261 | | - struct format_field *field, |
---|
| 2386 | +static int __dynamic_dimension__add(struct evsel *evsel, |
---|
| 2387 | + struct tep_format_field *field, |
---|
2262 | 2388 | bool raw_trace, int level) |
---|
2263 | 2389 | { |
---|
2264 | 2390 | struct hpp_dynamic_entry *hde; |
---|
.. | .. |
---|
2273 | 2399 | return 0; |
---|
2274 | 2400 | } |
---|
2275 | 2401 | |
---|
2276 | | -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) |
---|
| 2402 | +static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level) |
---|
2277 | 2403 | { |
---|
2278 | 2404 | int ret; |
---|
2279 | | - struct format_field *field; |
---|
| 2405 | + struct tep_format_field *field; |
---|
2280 | 2406 | |
---|
2281 | 2407 | field = evsel->tp_format->format.fields; |
---|
2282 | 2408 | while (field) { |
---|
.. | .. |
---|
2289 | 2415 | return 0; |
---|
2290 | 2416 | } |
---|
2291 | 2417 | |
---|
2292 | | -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, |
---|
| 2418 | +static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace, |
---|
2293 | 2419 | int level) |
---|
2294 | 2420 | { |
---|
2295 | 2421 | int ret; |
---|
2296 | | - struct perf_evsel *evsel; |
---|
| 2422 | + struct evsel *evsel; |
---|
2297 | 2423 | |
---|
2298 | 2424 | evlist__for_each_entry(evlist, evsel) { |
---|
2299 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
---|
| 2425 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) |
---|
2300 | 2426 | continue; |
---|
2301 | 2427 | |
---|
2302 | 2428 | ret = add_evsel_fields(evsel, raw_trace, level); |
---|
.. | .. |
---|
2306 | 2432 | return 0; |
---|
2307 | 2433 | } |
---|
2308 | 2434 | |
---|
2309 | | -static int add_all_matching_fields(struct perf_evlist *evlist, |
---|
| 2435 | +static int add_all_matching_fields(struct evlist *evlist, |
---|
2310 | 2436 | char *field_name, bool raw_trace, int level) |
---|
2311 | 2437 | { |
---|
2312 | 2438 | int ret = -ESRCH; |
---|
2313 | | - struct perf_evsel *evsel; |
---|
2314 | | - struct format_field *field; |
---|
| 2439 | + struct evsel *evsel; |
---|
| 2440 | + struct tep_format_field *field; |
---|
2315 | 2441 | |
---|
2316 | 2442 | evlist__for_each_entry(evlist, evsel) { |
---|
2317 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
---|
| 2443 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) |
---|
2318 | 2444 | continue; |
---|
2319 | 2445 | |
---|
2320 | 2446 | field = tep_find_any_field(evsel->tp_format, field_name); |
---|
.. | .. |
---|
2328 | 2454 | return ret; |
---|
2329 | 2455 | } |
---|
2330 | 2456 | |
---|
2331 | | -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, |
---|
| 2457 | +static int add_dynamic_entry(struct evlist *evlist, const char *tok, |
---|
2332 | 2458 | int level) |
---|
2333 | 2459 | { |
---|
2334 | 2460 | char *str, *event_name, *field_name, *opt_name; |
---|
2335 | | - struct perf_evsel *evsel; |
---|
2336 | | - struct format_field *field; |
---|
| 2461 | + struct evsel *evsel; |
---|
| 2462 | + struct tep_format_field *field; |
---|
2337 | 2463 | bool raw_trace = symbol_conf.raw_trace; |
---|
2338 | 2464 | int ret = 0; |
---|
2339 | 2465 | |
---|
.. | .. |
---|
2375 | 2501 | goto out; |
---|
2376 | 2502 | } |
---|
2377 | 2503 | |
---|
2378 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { |
---|
| 2504 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { |
---|
2379 | 2505 | pr_debug("%s is not a tracepoint event\n", event_name); |
---|
2380 | 2506 | ret = -EINVAL; |
---|
2381 | 2507 | goto out; |
---|
.. | .. |
---|
2472 | 2598 | } |
---|
2473 | 2599 | |
---|
2474 | 2600 | int sort_dimension__add(struct perf_hpp_list *list, const char *tok, |
---|
2475 | | - struct perf_evlist *evlist, |
---|
| 2601 | + struct evlist *evlist, |
---|
2476 | 2602 | int level) |
---|
2477 | 2603 | { |
---|
2478 | 2604 | unsigned int i; |
---|
.. | .. |
---|
2568 | 2694 | } |
---|
2569 | 2695 | |
---|
2570 | 2696 | static int setup_sort_list(struct perf_hpp_list *list, char *str, |
---|
2571 | | - struct perf_evlist *evlist) |
---|
| 2697 | + struct evlist *evlist) |
---|
2572 | 2698 | { |
---|
2573 | 2699 | char *tmp, *tok; |
---|
2574 | 2700 | int ret = 0; |
---|
.. | .. |
---|
2598 | 2724 | ret = sort_dimension__add(list, tok, evlist, level); |
---|
2599 | 2725 | if (ret == -EINVAL) { |
---|
2600 | 2726 | if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok))) |
---|
2601 | | - pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); |
---|
| 2727 | + ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); |
---|
2602 | 2728 | else |
---|
2603 | | - pr_err("Invalid --sort key: `%s'", tok); |
---|
| 2729 | + ui__error("Invalid --sort key: `%s'", tok); |
---|
2604 | 2730 | break; |
---|
2605 | 2731 | } else if (ret == -ESRCH) { |
---|
2606 | | - pr_err("Unknown --sort key: `%s'", tok); |
---|
| 2732 | + ui__error("Unknown --sort key: `%s'", tok); |
---|
2607 | 2733 | break; |
---|
2608 | 2734 | } |
---|
2609 | 2735 | } |
---|
.. | .. |
---|
2614 | 2740 | return ret; |
---|
2615 | 2741 | } |
---|
2616 | 2742 | |
---|
2617 | | -static const char *get_default_sort_order(struct perf_evlist *evlist) |
---|
| 2743 | +static const char *get_default_sort_order(struct evlist *evlist) |
---|
2618 | 2744 | { |
---|
2619 | 2745 | const char *default_sort_orders[] = { |
---|
2620 | 2746 | default_sort_order, |
---|
.. | .. |
---|
2625 | 2751 | default_tracepoint_sort_order, |
---|
2626 | 2752 | }; |
---|
2627 | 2753 | bool use_trace = true; |
---|
2628 | | - struct perf_evsel *evsel; |
---|
| 2754 | + struct evsel *evsel; |
---|
2629 | 2755 | |
---|
2630 | 2756 | BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); |
---|
2631 | 2757 | |
---|
.. | .. |
---|
2633 | 2759 | goto out_no_evlist; |
---|
2634 | 2760 | |
---|
2635 | 2761 | evlist__for_each_entry(evlist, evsel) { |
---|
2636 | | - if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { |
---|
| 2762 | + if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { |
---|
2637 | 2763 | use_trace = false; |
---|
2638 | 2764 | break; |
---|
2639 | 2765 | } |
---|
.. | .. |
---|
2648 | 2774 | return default_sort_orders[sort__mode]; |
---|
2649 | 2775 | } |
---|
2650 | 2776 | |
---|
2651 | | -static int setup_sort_order(struct perf_evlist *evlist) |
---|
| 2777 | +static int setup_sort_order(struct evlist *evlist) |
---|
2652 | 2778 | { |
---|
2653 | 2779 | char *new_sort_order; |
---|
2654 | 2780 | |
---|
.. | .. |
---|
2660 | 2786 | return 0; |
---|
2661 | 2787 | |
---|
2662 | 2788 | if (sort_order[1] == '\0') { |
---|
2663 | | - pr_err("Invalid --sort key: `+'"); |
---|
| 2789 | + ui__error("Invalid --sort key: `+'"); |
---|
2664 | 2790 | return -EINVAL; |
---|
2665 | 2791 | } |
---|
2666 | 2792 | |
---|
.. | .. |
---|
2709 | 2835 | return keys; |
---|
2710 | 2836 | } |
---|
2711 | 2837 | |
---|
2712 | | -static int __setup_sorting(struct perf_evlist *evlist) |
---|
| 2838 | +static int __setup_sorting(struct evlist *evlist) |
---|
2713 | 2839 | { |
---|
2714 | 2840 | char *str; |
---|
2715 | 2841 | const char *sort_keys; |
---|
.. | .. |
---|
2876 | 3002 | if (strncasecmp(tok, sd->name, strlen(tok))) |
---|
2877 | 3003 | continue; |
---|
2878 | 3004 | |
---|
| 3005 | + if (sort__mode != SORT_MODE__BRANCH) |
---|
| 3006 | + return -EINVAL; |
---|
| 3007 | + |
---|
2879 | 3008 | return __sort_dimension__add_output(list, sd); |
---|
2880 | 3009 | } |
---|
2881 | 3010 | |
---|
.. | .. |
---|
2884 | 3013 | |
---|
2885 | 3014 | if (strncasecmp(tok, sd->name, strlen(tok))) |
---|
2886 | 3015 | continue; |
---|
| 3016 | + |
---|
| 3017 | + if (sort__mode != SORT_MODE__MEMORY) |
---|
| 3018 | + return -EINVAL; |
---|
2887 | 3019 | |
---|
2888 | 3020 | return __sort_dimension__add_output(list, sd); |
---|
2889 | 3021 | } |
---|
.. | .. |
---|
2951 | 3083 | strp++; |
---|
2952 | 3084 | |
---|
2953 | 3085 | if (!strlen(strp)) { |
---|
2954 | | - pr_err("Invalid --fields key: `+'"); |
---|
| 3086 | + ui__error("Invalid --fields key: `+'"); |
---|
2955 | 3087 | goto out; |
---|
2956 | 3088 | } |
---|
2957 | 3089 | |
---|
.. | .. |
---|
2962 | 3094 | return ret; |
---|
2963 | 3095 | } |
---|
2964 | 3096 | |
---|
2965 | | -int setup_sorting(struct perf_evlist *evlist) |
---|
| 3097 | +int setup_sorting(struct evlist *evlist) |
---|
2966 | 3098 | { |
---|
2967 | 3099 | int err; |
---|
2968 | 3100 | |
---|
.. | .. |
---|
3013 | 3145 | reset_dimensions(); |
---|
3014 | 3146 | perf_hpp__reset_output_field(&perf_hpp_list); |
---|
3015 | 3147 | } |
---|
| 3148 | + |
---|
| 3149 | +#define INDENT (3*8 + 1) |
---|
| 3150 | + |
---|
| 3151 | +static void add_key(struct strbuf *sb, const char *str, int *llen) |
---|
| 3152 | +{ |
---|
| 3153 | + if (*llen >= 75) { |
---|
| 3154 | + strbuf_addstr(sb, "\n\t\t\t "); |
---|
| 3155 | + *llen = INDENT; |
---|
| 3156 | + } |
---|
| 3157 | + strbuf_addf(sb, " %s", str); |
---|
| 3158 | + *llen += strlen(str) + 1; |
---|
| 3159 | +} |
---|
| 3160 | + |
---|
| 3161 | +static void add_sort_string(struct strbuf *sb, struct sort_dimension *s, int n, |
---|
| 3162 | + int *llen) |
---|
| 3163 | +{ |
---|
| 3164 | + int i; |
---|
| 3165 | + |
---|
| 3166 | + for (i = 0; i < n; i++) |
---|
| 3167 | + add_key(sb, s[i].name, llen); |
---|
| 3168 | +} |
---|
| 3169 | + |
---|
| 3170 | +static void add_hpp_sort_string(struct strbuf *sb, struct hpp_dimension *s, int n, |
---|
| 3171 | + int *llen) |
---|
| 3172 | +{ |
---|
| 3173 | + int i; |
---|
| 3174 | + |
---|
| 3175 | + for (i = 0; i < n; i++) |
---|
| 3176 | + add_key(sb, s[i].name, llen); |
---|
| 3177 | +} |
---|
| 3178 | + |
---|
| 3179 | +char *sort_help(const char *prefix) |
---|
| 3180 | +{ |
---|
| 3181 | + struct strbuf sb; |
---|
| 3182 | + char *s; |
---|
| 3183 | + int len = strlen(prefix) + INDENT; |
---|
| 3184 | + |
---|
| 3185 | + strbuf_init(&sb, 300); |
---|
| 3186 | + strbuf_addstr(&sb, prefix); |
---|
| 3187 | + add_hpp_sort_string(&sb, hpp_sort_dimensions, |
---|
| 3188 | + ARRAY_SIZE(hpp_sort_dimensions), &len); |
---|
| 3189 | + add_sort_string(&sb, common_sort_dimensions, |
---|
| 3190 | + ARRAY_SIZE(common_sort_dimensions), &len); |
---|
| 3191 | + add_sort_string(&sb, bstack_sort_dimensions, |
---|
| 3192 | + ARRAY_SIZE(bstack_sort_dimensions), &len); |
---|
| 3193 | + add_sort_string(&sb, memory_sort_dimensions, |
---|
| 3194 | + ARRAY_SIZE(memory_sort_dimensions), &len); |
---|
| 3195 | + s = strbuf_detach(&sb, NULL); |
---|
| 3196 | + strbuf_release(&sb); |
---|
| 3197 | + return s; |
---|
| 3198 | +} |
---|