diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2012-08-09 10:31:52 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-08-09 14:59:26 -0400 |
commit | a3277d2d5a0d5d9492993ab68af8a8dc96760dd1 (patch) | |
tree | e9c621444e7a31b801b5c57753409bab0a46484e /tools | |
parent | 98a4179c9aa1e99adf5103e6e0d05f563d902de1 (diff) |
perf tools: Support for events bash completion
Add basic bash completion for the -e option in record, top and stat
subcommands. Only hardware, software and tracepoint events are
supported.
Breakpoints, raw events and events grouping completion need more
thinking.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1344522713-27951-3-git-send-email-fweisbec@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/bash_completion | 6 | ||||
-rw-r--r-- | tools/perf/builtin-list.c | 14 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 70 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 7 |
4 files changed, 61 insertions, 36 deletions
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion index 9a31fa5ed2a9..1958fa539d0f 100644 --- a/tools/perf/bash_completion +++ b/tools/perf/bash_completion | |||
@@ -6,7 +6,7 @@ _perf() | |||
6 | local cur cmd | 6 | local cur cmd |
7 | 7 | ||
8 | COMPREPLY=() | 8 | COMPREPLY=() |
9 | _get_comp_words_by_ref cur | 9 | _get_comp_words_by_ref cur prev |
10 | 10 | ||
11 | cmd=${COMP_WORDS[0]} | 11 | cmd=${COMP_WORDS[0]} |
12 | 12 | ||
@@ -14,6 +14,10 @@ _perf() | |||
14 | if [ $COMP_CWORD -eq 1 ]; then | 14 | if [ $COMP_CWORD -eq 1 ]; then |
15 | cmds=$($cmd --list-cmds) | 15 | cmds=$($cmd --list-cmds) |
16 | COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) | 16 | COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) |
17 | # List possible events for -e option | ||
18 | elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then | ||
19 | cmds=$($cmd list --raw-dump) | ||
20 | COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) | ||
17 | # Fall down to list regular files | 21 | # Fall down to list regular files |
18 | else | 22 | else |
19 | _filedir | 23 | _filedir |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 6313b6eb3ebb..bdcff81b532a 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
@@ -19,15 +19,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __used) | |||
19 | setup_pager(); | 19 | setup_pager(); |
20 | 20 | ||
21 | if (argc == 1) | 21 | if (argc == 1) |
22 | print_events(NULL); | 22 | print_events(NULL, false); |
23 | else { | 23 | else { |
24 | int i; | 24 | int i; |
25 | 25 | ||
26 | for (i = 1; i < argc; ++i) { | 26 | for (i = 1; i < argc; ++i) { |
27 | if (i > 1) | 27 | if (i > 2) |
28 | putchar('\n'); | 28 | putchar('\n'); |
29 | if (strncmp(argv[i], "tracepoint", 10) == 0) | 29 | if (strncmp(argv[i], "tracepoint", 10) == 0) |
30 | print_tracepoint_events(NULL, NULL); | 30 | print_tracepoint_events(NULL, NULL, false); |
31 | else if (strcmp(argv[i], "hw") == 0 || | 31 | else if (strcmp(argv[i], "hw") == 0 || |
32 | strcmp(argv[i], "hardware") == 0) | 32 | strcmp(argv[i], "hardware") == 0) |
33 | print_events_type(PERF_TYPE_HARDWARE); | 33 | print_events_type(PERF_TYPE_HARDWARE); |
@@ -36,13 +36,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __used) | |||
36 | print_events_type(PERF_TYPE_SOFTWARE); | 36 | print_events_type(PERF_TYPE_SOFTWARE); |
37 | else if (strcmp(argv[i], "cache") == 0 || | 37 | else if (strcmp(argv[i], "cache") == 0 || |
38 | strcmp(argv[i], "hwcache") == 0) | 38 | strcmp(argv[i], "hwcache") == 0) |
39 | print_hwcache_events(NULL); | 39 | print_hwcache_events(NULL, false); |
40 | else if (strcmp(argv[i], "--raw-dump") == 0) | ||
41 | print_events(NULL, true); | ||
40 | else { | 42 | else { |
41 | char *sep = strchr(argv[i], ':'), *s; | 43 | char *sep = strchr(argv[i], ':'), *s; |
42 | int sep_idx; | 44 | int sep_idx; |
43 | 45 | ||
44 | if (sep == NULL) { | 46 | if (sep == NULL) { |
45 | print_events(argv[i]); | 47 | print_events(argv[i], false); |
46 | continue; | 48 | continue; |
47 | } | 49 | } |
48 | sep_idx = sep - argv[i]; | 50 | sep_idx = sep - argv[i]; |
@@ -51,7 +53,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __used) | |||
51 | return -1; | 53 | return -1; |
52 | 54 | ||
53 | s[sep_idx] = '\0'; | 55 | s[sep_idx] = '\0'; |
54 | print_tracepoint_events(s, s + sep_idx + 1); | 56 | print_tracepoint_events(s, s + sep_idx + 1, false); |
55 | free(s); | 57 | free(s); |
56 | } | 58 | } |
57 | } | 59 | } |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 8bdfa3e5c8c7..3ec4bfcd3f9c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -799,7 +799,8 @@ static const char * const event_type_descriptors[] = { | |||
799 | * Print the events from <debugfs_mount_point>/tracing/events | 799 | * Print the events from <debugfs_mount_point>/tracing/events |
800 | */ | 800 | */ |
801 | 801 | ||
802 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob) | 802 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, |
803 | bool name_only) | ||
803 | { | 804 | { |
804 | DIR *sys_dir, *evt_dir; | 805 | DIR *sys_dir, *evt_dir; |
805 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 806 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
@@ -829,6 +830,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob) | |||
829 | !strglobmatch(evt_dirent.d_name, event_glob)) | 830 | !strglobmatch(evt_dirent.d_name, event_glob)) |
830 | continue; | 831 | continue; |
831 | 832 | ||
833 | if (name_only) { | ||
834 | printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); | ||
835 | continue; | ||
836 | } | ||
837 | |||
832 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | 838 | snprintf(evt_path, MAXPATHLEN, "%s:%s", |
833 | sys_dirent.d_name, evt_dirent.d_name); | 839 | sys_dirent.d_name, evt_dirent.d_name); |
834 | printf(" %-50s [%s]\n", evt_path, | 840 | printf(" %-50s [%s]\n", evt_path, |
@@ -906,7 +912,7 @@ void print_events_type(u8 type) | |||
906 | __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); | 912 | __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); |
907 | } | 913 | } |
908 | 914 | ||
909 | int print_hwcache_events(const char *event_glob) | 915 | int print_hwcache_events(const char *event_glob, bool name_only) |
910 | { | 916 | { |
911 | unsigned int type, op, i, printed = 0; | 917 | unsigned int type, op, i, printed = 0; |
912 | char name[64]; | 918 | char name[64]; |
@@ -923,8 +929,11 @@ int print_hwcache_events(const char *event_glob) | |||
923 | if (event_glob != NULL && !strglobmatch(name, event_glob)) | 929 | if (event_glob != NULL && !strglobmatch(name, event_glob)) |
924 | continue; | 930 | continue; |
925 | 931 | ||
926 | printf(" %-50s [%s]\n", name, | 932 | if (name_only) |
927 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | 933 | printf("%s ", name); |
934 | else | ||
935 | printf(" %-50s [%s]\n", name, | ||
936 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | ||
928 | ++printed; | 937 | ++printed; |
929 | } | 938 | } |
930 | } | 939 | } |
@@ -934,7 +943,8 @@ int print_hwcache_events(const char *event_glob) | |||
934 | } | 943 | } |
935 | 944 | ||
936 | static void print_symbol_events(const char *event_glob, unsigned type, | 945 | static void print_symbol_events(const char *event_glob, unsigned type, |
937 | struct event_symbol *syms, unsigned max) | 946 | struct event_symbol *syms, unsigned max, |
947 | bool name_only) | ||
938 | { | 948 | { |
939 | unsigned i, printed = 0; | 949 | unsigned i, printed = 0; |
940 | char name[MAX_NAME_LEN]; | 950 | char name[MAX_NAME_LEN]; |
@@ -946,6 +956,11 @@ static void print_symbol_events(const char *event_glob, unsigned type, | |||
946 | (syms->alias && strglobmatch(syms->alias, event_glob)))) | 956 | (syms->alias && strglobmatch(syms->alias, event_glob)))) |
947 | continue; | 957 | continue; |
948 | 958 | ||
959 | if (name_only) { | ||
960 | printf("%s ", syms->symbol); | ||
961 | continue; | ||
962 | } | ||
963 | |||
949 | if (strlen(syms->alias)) | 964 | if (strlen(syms->alias)) |
950 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); | 965 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); |
951 | else | 966 | else |
@@ -963,39 +978,42 @@ static void print_symbol_events(const char *event_glob, unsigned type, | |||
963 | /* | 978 | /* |
964 | * Print the help text for the event symbols: | 979 | * Print the help text for the event symbols: |
965 | */ | 980 | */ |
966 | void print_events(const char *event_glob) | 981 | void print_events(const char *event_glob, bool name_only) |
967 | { | 982 | { |
968 | 983 | if (!name_only) { | |
969 | printf("\n"); | 984 | printf("\n"); |
970 | printf("List of pre-defined events (to be used in -e):\n"); | 985 | printf("List of pre-defined events (to be used in -e):\n"); |
986 | } | ||
971 | 987 | ||
972 | print_symbol_events(event_glob, PERF_TYPE_HARDWARE, | 988 | print_symbol_events(event_glob, PERF_TYPE_HARDWARE, |
973 | event_symbols_hw, PERF_COUNT_HW_MAX); | 989 | event_symbols_hw, PERF_COUNT_HW_MAX, name_only); |
974 | 990 | ||
975 | print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, | 991 | print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, |
976 | event_symbols_sw, PERF_COUNT_SW_MAX); | 992 | event_symbols_sw, PERF_COUNT_SW_MAX, name_only); |
977 | 993 | ||
978 | print_hwcache_events(event_glob); | 994 | print_hwcache_events(event_glob, name_only); |
979 | 995 | ||
980 | if (event_glob != NULL) | 996 | if (event_glob != NULL) |
981 | return; | 997 | return; |
982 | 998 | ||
983 | printf("\n"); | 999 | if (!name_only) { |
984 | printf(" %-50s [%s]\n", | 1000 | printf("\n"); |
985 | "rNNN", | 1001 | printf(" %-50s [%s]\n", |
986 | event_type_descriptors[PERF_TYPE_RAW]); | 1002 | "rNNN", |
987 | printf(" %-50s [%s]\n", | 1003 | event_type_descriptors[PERF_TYPE_RAW]); |
988 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", | 1004 | printf(" %-50s [%s]\n", |
989 | event_type_descriptors[PERF_TYPE_RAW]); | 1005 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", |
990 | printf(" (see 'perf list --help' on how to encode it)\n"); | 1006 | event_type_descriptors[PERF_TYPE_RAW]); |
991 | printf("\n"); | 1007 | printf(" (see 'perf list --help' on how to encode it)\n"); |
992 | 1008 | printf("\n"); | |
993 | printf(" %-50s [%s]\n", | 1009 | |
994 | "mem:<addr>[:access]", | 1010 | printf(" %-50s [%s]\n", |
1011 | "mem:<addr>[:access]", | ||
995 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); | 1012 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); |
996 | printf("\n"); | 1013 | printf("\n"); |
1014 | } | ||
997 | 1015 | ||
998 | print_tracepoint_events(NULL, NULL); | 1016 | print_tracepoint_events(NULL, NULL, name_only); |
999 | } | 1017 | } |
1000 | 1018 | ||
1001 | int parse_events__is_hardcoded_term(struct parse_events__term *term) | 1019 | int parse_events__is_hardcoded_term(struct parse_events__term *term) |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 163aad404619..00416d7fd012 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -96,10 +96,11 @@ void parse_events_update_lists(struct list_head *list_event, | |||
96 | void parse_events_error(void *data, void *scanner, char const *msg); | 96 | void parse_events_error(void *data, void *scanner, char const *msg); |
97 | int parse_events__test(void); | 97 | int parse_events__test(void); |
98 | 98 | ||
99 | void print_events(const char *event_glob); | 99 | void print_events(const char *event_glob, bool name_only); |
100 | void print_events_type(u8 type); | 100 | void print_events_type(u8 type); |
101 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob); | 101 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, |
102 | int print_hwcache_events(const char *event_glob); | 102 | bool name_only); |
103 | int print_hwcache_events(const char *event_glob, bool name_only); | ||
103 | extern int is_valid_tracepoint(const char *event_string); | 104 | extern int is_valid_tracepoint(const char *event_string); |
104 | 105 | ||
105 | extern int valid_debugfs_mount(const char *debugfs); | 106 | extern int valid_debugfs_mount(const char *debugfs); |