~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to tools/perf/util/ui/browsers/hists.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
#include <newt.h>
8
8
#include <linux/rbtree.h>
9
9
 
 
10
#include "../../evsel.h"
 
11
#include "../../evlist.h"
10
12
#include "../../hist.h"
11
13
#include "../../pstack.h"
12
14
#include "../../sort.h"
292
294
{
293
295
        int key;
294
296
        int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't',
295
 
                            NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT, 0, };
 
297
                            NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT,
 
298
                            NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0, };
296
299
 
297
300
        self->b.entries = &self->hists->entries;
298
301
        self->b.nr_entries = self->hists->nr_entries;
377
380
        while (node) {
378
381
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
379
382
                struct rb_node *next = rb_next(node);
380
 
                u64 cumul = cumul_hits(child);
 
383
                u64 cumul = callchain_cumul_hits(child);
381
384
                struct callchain_list *chain;
382
385
                char folded_sign = ' ';
383
386
                int first = true;
638
641
        struct rb_node *nd;
639
642
        bool first = true;
640
643
 
 
644
        if (self->nr_entries == 0)
 
645
                return;
 
646
 
641
647
        switch (whence) {
642
648
        case SEEK_SET:
643
649
                nd = hists__filter_entries(rb_first(self->entries));
797
803
        return printed;
798
804
}
799
805
 
800
 
int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 
806
static int perf_evsel__hists_browse(struct perf_evsel *evsel,
 
807
                                    const char *helpline, const char *ev_name,
 
808
                                    bool left_exits)
801
809
{
 
810
        struct hists *self = &evsel->hists;
802
811
        struct hist_browser *browser = hist_browser__new(self);
803
812
        struct pstack *fstack;
804
813
        const struct thread *thread_filter = NULL;
818
827
        hists__browser_title(self, msg, sizeof(msg), ev_name,
819
828
                             dso_filter, thread_filter);
820
829
        while (1) {
821
 
                const struct thread *thread;
822
 
                const struct dso *dso;
 
830
                const struct thread *thread = NULL;
 
831
                const struct dso *dso = NULL;
823
832
                char *options[16];
824
833
                int nr_options = 0, choice = 0, i,
825
834
                    annotate = -2, zoom_dso = -2, zoom_thread = -2,
827
836
 
828
837
                key = hist_browser__run(browser, msg);
829
838
 
830
 
                thread = hist_browser__selected_thread(browser);
831
 
                dso = browser->selection->map ? browser->selection->map->dso : NULL;
 
839
                if (browser->he_selection != NULL) {
 
840
                        thread = hist_browser__selected_thread(browser);
 
841
                        dso = browser->selection->map ? browser->selection->map->dso : NULL;
 
842
                }
832
843
 
833
844
                switch (key) {
834
845
                case NEWT_KEY_TAB:
839
850
                         */
840
851
                        goto out_free_stack;
841
852
                case 'a':
842
 
                        if (browser->selection->map == NULL &&
 
853
                        if (browser->selection == NULL ||
 
854
                            browser->selection->sym == NULL ||
843
855
                            browser->selection->map->dso->annotate_warned)
844
856
                                continue;
845
857
                        goto do_annotate;
858
870
                                        "E         Expand all callchains\n"
859
871
                                        "d         Zoom into current DSO\n"
860
872
                                        "t         Zoom into current Thread\n"
 
873
                                        "TAB/UNTAB Switch events\n"
861
874
                                        "q/CTRL+C  Exit browser");
862
875
                        continue;
863
876
                case NEWT_KEY_ENTER:
867
880
                case NEWT_KEY_LEFT: {
868
881
                        const void *top;
869
882
 
870
 
                        if (pstack__empty(fstack))
 
883
                        if (pstack__empty(fstack)) {
 
884
                                /*
 
885
                                 * Go back to the perf_evsel_menu__run or other user
 
886
                                 */
 
887
                                if (left_exits)
 
888
                                        goto out_free_stack;
871
889
                                continue;
 
890
                        }
872
891
                        top = pstack__pop(fstack);
873
892
                        if (top == &dso_filter)
874
893
                                goto zoom_out_dso;
877
896
                        continue;
878
897
                }
879
898
                case NEWT_KEY_ESCAPE:
880
 
                        if (!ui__dialog_yesno("Do you really want to exit?"))
 
899
                        if (!left_exits &&
 
900
                            !ui__dialog_yesno("Do you really want to exit?"))
881
901
                                continue;
882
902
                        /* Fall thru */
883
903
                default:
884
904
                        goto out_free_stack;
885
905
                }
886
906
 
887
 
                if (browser->selection->sym != NULL &&
 
907
                if (browser->selection != NULL &&
 
908
                    browser->selection->sym != NULL &&
888
909
                    !browser->selection->map->dso->annotate_warned &&
889
910
                    asprintf(&options[nr_options], "Annotate %s",
890
911
                             browser->selection->sym->name) > 0)
903
924
                             (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
904
925
                        zoom_dso = nr_options++;
905
926
 
906
 
                if (browser->selection->map != NULL &&
 
927
                if (browser->selection != NULL &&
 
928
                    browser->selection->map != NULL &&
907
929
                    asprintf(&options[nr_options], "Browse map details") > 0)
908
930
                        browse_map = nr_options++;
909
931
 
923
945
                if (choice == annotate) {
924
946
                        struct hist_entry *he;
925
947
do_annotate:
926
 
                        if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
927
 
                                browser->selection->map->dso->annotate_warned = 1;
928
 
                                ui_helpline__puts("No vmlinux file found, can't "
929
 
                                                 "annotate with just a "
930
 
                                                 "kallsyms file");
931
 
                                continue;
932
 
                        }
933
 
 
934
948
                        he = hist_browser__selected_entry(browser);
935
949
                        if (he == NULL)
936
950
                                continue;
937
951
 
938
 
                        hist_entry__tui_annotate(he);
 
952
                        hist_entry__tui_annotate(he, evsel->idx);
939
953
                } else if (choice == browse_map)
940
954
                        map__browse(browser->selection->map);
941
955
                else if (choice == zoom_dso) {
984
998
        return key;
985
999
}
986
1000
 
987
 
int hists__tui_browse_tree(struct rb_root *self, const char *help)
988
 
{
989
 
        struct rb_node *first = rb_first(self), *nd = first, *next;
990
 
        int key = 0;
991
 
 
992
 
        while (nd) {
993
 
                struct hists *hists = rb_entry(nd, struct hists, rb_node);
994
 
                const char *ev_name = __event_name(hists->type, hists->config);
995
 
 
996
 
                key = hists__browse(hists, help, ev_name);
 
1001
struct perf_evsel_menu {
 
1002
        struct ui_browser b;
 
1003
        struct perf_evsel *selection;
 
1004
};
 
1005
 
 
1006
static void perf_evsel_menu__write(struct ui_browser *browser,
 
1007
                                   void *entry, int row)
 
1008
{
 
1009
        struct perf_evsel_menu *menu = container_of(browser,
 
1010
                                                    struct perf_evsel_menu, b);
 
1011
        struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
 
1012
        bool current_entry = ui_browser__is_current_entry(browser, row);
 
1013
        unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
 
1014
        const char *ev_name = event_name(evsel);
 
1015
        char bf[256], unit;
 
1016
 
 
1017
        ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
 
1018
                                                       HE_COLORSET_NORMAL);
 
1019
 
 
1020
        nr_events = convert_unit(nr_events, &unit);
 
1021
        snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
 
1022
                 unit, unit == ' ' ? "" : " ", ev_name);
 
1023
        slsmg_write_nstring(bf, browser->width);
 
1024
 
 
1025
        if (current_entry)
 
1026
                menu->selection = evsel;
 
1027
}
 
1028
 
 
1029
static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help)
 
1030
{
 
1031
        int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
 
1032
        struct perf_evlist *evlist = menu->b.priv;
 
1033
        struct perf_evsel *pos;
 
1034
        const char *ev_name, *title = "Available samples";
 
1035
        int key;
 
1036
 
 
1037
        if (ui_browser__show(&menu->b, title,
 
1038
                             "ESC: exit, ENTER|->: Browse histograms") < 0)
 
1039
                return -1;
 
1040
 
 
1041
        ui_browser__add_exit_keys(&menu->b, exit_keys);
 
1042
 
 
1043
        while (1) {
 
1044
                key = ui_browser__run(&menu->b);
 
1045
 
 
1046
                switch (key) {
 
1047
                case NEWT_KEY_RIGHT:
 
1048
                case NEWT_KEY_ENTER:
 
1049
                        if (!menu->selection)
 
1050
                                continue;
 
1051
                        pos = menu->selection;
 
1052
browse_hists:
 
1053
                        ev_name = event_name(pos);
 
1054
                        key = perf_evsel__hists_browse(pos, help, ev_name, true);
 
1055
                        ui_browser__show_title(&menu->b, title);
 
1056
                        break;
 
1057
                case NEWT_KEY_LEFT:
 
1058
                        continue;
 
1059
                case NEWT_KEY_ESCAPE:
 
1060
                        if (!ui__dialog_yesno("Do you really want to exit?"))
 
1061
                                continue;
 
1062
                        /* Fall thru */
 
1063
                default:
 
1064
                        goto out;
 
1065
                }
 
1066
 
997
1067
                switch (key) {
998
1068
                case NEWT_KEY_TAB:
999
 
                        next = rb_next(nd);
1000
 
                        if (next)
1001
 
                                nd = next;
1002
 
                        break;
 
1069
                        if (pos->node.next == &evlist->entries)
 
1070
                                pos = list_entry(evlist->entries.next, struct perf_evsel, node);
 
1071
                        else
 
1072
                                pos = list_entry(pos->node.next, struct perf_evsel, node);
 
1073
                        goto browse_hists;
1003
1074
                case NEWT_KEY_UNTAB:
1004
 
                        if (nd == first)
1005
 
                                continue;
1006
 
                        nd = rb_prev(nd);
 
1075
                        if (pos->node.prev == &evlist->entries)
 
1076
                                pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
 
1077
                        else
 
1078
                                pos = list_entry(pos->node.prev, struct perf_evsel, node);
 
1079
                        goto browse_hists;
 
1080
                case 'q':
 
1081
                case CTRL('c'):
 
1082
                        goto out;
1007
1083
                default:
1008
 
                        return key;
 
1084
                        break;
1009
1085
                }
1010
1086
        }
1011
1087
 
 
1088
out:
 
1089
        ui_browser__hide(&menu->b);
1012
1090
        return key;
1013
1091
}
 
1092
 
 
1093
static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
 
1094
                                           const char *help)
 
1095
{
 
1096
        struct perf_evsel *pos;
 
1097
        struct perf_evsel_menu menu = {
 
1098
                .b = {
 
1099
                        .entries    = &evlist->entries,
 
1100
                        .refresh    = ui_browser__list_head_refresh,
 
1101
                        .seek       = ui_browser__list_head_seek,
 
1102
                        .write      = perf_evsel_menu__write,
 
1103
                        .nr_entries = evlist->nr_entries,
 
1104
                        .priv       = evlist,
 
1105
                },
 
1106
        };
 
1107
 
 
1108
        ui_helpline__push("Press ESC to exit");
 
1109
 
 
1110
        list_for_each_entry(pos, &evlist->entries, node) {
 
1111
                const char *ev_name = event_name(pos);
 
1112
                size_t line_len = strlen(ev_name) + 7;
 
1113
 
 
1114
                if (menu.b.width < line_len)
 
1115
                        menu.b.width = line_len;
 
1116
                /*
 
1117
                 * Cache the evsel name, tracepoints have a _high_ cost per
 
1118
                 * event_name() call.
 
1119
                 */
 
1120
                if (pos->name == NULL)
 
1121
                        pos->name = strdup(ev_name);
 
1122
        }
 
1123
 
 
1124
        return perf_evsel_menu__run(&menu, help);
 
1125
}
 
1126
 
 
1127
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help)
 
1128
{
 
1129
 
 
1130
        if (evlist->nr_entries == 1) {
 
1131
                struct perf_evsel *first = list_entry(evlist->entries.next,
 
1132
                                                      struct perf_evsel, node);
 
1133
                const char *ev_name = event_name(first);
 
1134
                return perf_evsel__hists_browse(first, help, ev_name, false);
 
1135
        }
 
1136
 
 
1137
        return __perf_evlist__tui_browse_hists(evlist, help);
 
1138
}