mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
98a4179c9a
commit
a3277d2d5a
|
@ -6,7 +6,7 @@ _perf()
|
||||||
local cur cmd
|
local cur cmd
|
||||||
|
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
_get_comp_words_by_ref cur
|
_get_comp_words_by_ref cur prev
|
||||||
|
|
||||||
cmd=${COMP_WORDS[0]}
|
cmd=${COMP_WORDS[0]}
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ _perf()
|
||||||
if [ $COMP_CWORD -eq 1 ]; then
|
if [ $COMP_CWORD -eq 1 ]; then
|
||||||
cmds=$($cmd --list-cmds)
|
cmds=$($cmd --list-cmds)
|
||||||
COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
|
COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
|
||||||
|
# List possible events for -e option
|
||||||
|
elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
|
||||||
|
cmds=$($cmd list --raw-dump)
|
||||||
|
COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
|
||||||
# Fall down to list regular files
|
# Fall down to list regular files
|
||||||
else
|
else
|
||||||
_filedir
|
_filedir
|
||||||
|
|
|
@ -19,15 +19,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __used)
|
||||||
setup_pager();
|
setup_pager();
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
print_events(NULL);
|
print_events(NULL, false);
|
||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i < argc; ++i) {
|
for (i = 1; i < argc; ++i) {
|
||||||
if (i > 1)
|
if (i > 2)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
if (strncmp(argv[i], "tracepoint", 10) == 0)
|
if (strncmp(argv[i], "tracepoint", 10) == 0)
|
||||||
print_tracepoint_events(NULL, NULL);
|
print_tracepoint_events(NULL, NULL, false);
|
||||||
else if (strcmp(argv[i], "hw") == 0 ||
|
else if (strcmp(argv[i], "hw") == 0 ||
|
||||||
strcmp(argv[i], "hardware") == 0)
|
strcmp(argv[i], "hardware") == 0)
|
||||||
print_events_type(PERF_TYPE_HARDWARE);
|
print_events_type(PERF_TYPE_HARDWARE);
|
||||||
|
@ -36,13 +36,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __used)
|
||||||
print_events_type(PERF_TYPE_SOFTWARE);
|
print_events_type(PERF_TYPE_SOFTWARE);
|
||||||
else if (strcmp(argv[i], "cache") == 0 ||
|
else if (strcmp(argv[i], "cache") == 0 ||
|
||||||
strcmp(argv[i], "hwcache") == 0)
|
strcmp(argv[i], "hwcache") == 0)
|
||||||
print_hwcache_events(NULL);
|
print_hwcache_events(NULL, false);
|
||||||
|
else if (strcmp(argv[i], "--raw-dump") == 0)
|
||||||
|
print_events(NULL, true);
|
||||||
else {
|
else {
|
||||||
char *sep = strchr(argv[i], ':'), *s;
|
char *sep = strchr(argv[i], ':'), *s;
|
||||||
int sep_idx;
|
int sep_idx;
|
||||||
|
|
||||||
if (sep == NULL) {
|
if (sep == NULL) {
|
||||||
print_events(argv[i]);
|
print_events(argv[i], false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sep_idx = sep - argv[i];
|
sep_idx = sep - argv[i];
|
||||||
|
@ -51,7 +53,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __used)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
s[sep_idx] = '\0';
|
s[sep_idx] = '\0';
|
||||||
print_tracepoint_events(s, s + sep_idx + 1);
|
print_tracepoint_events(s, s + sep_idx + 1, false);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -799,7 +799,8 @@ static const char * const event_type_descriptors[] = {
|
||||||
* Print the events from <debugfs_mount_point>/tracing/events
|
* Print the events from <debugfs_mount_point>/tracing/events
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
|
void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
||||||
|
bool name_only)
|
||||||
{
|
{
|
||||||
DIR *sys_dir, *evt_dir;
|
DIR *sys_dir, *evt_dir;
|
||||||
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
|
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)
|
||||||
!strglobmatch(evt_dirent.d_name, event_glob))
|
!strglobmatch(evt_dirent.d_name, event_glob))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (name_only) {
|
||||||
|
printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(evt_path, MAXPATHLEN, "%s:%s",
|
snprintf(evt_path, MAXPATHLEN, "%s:%s",
|
||||||
sys_dirent.d_name, evt_dirent.d_name);
|
sys_dirent.d_name, evt_dirent.d_name);
|
||||||
printf(" %-50s [%s]\n", evt_path,
|
printf(" %-50s [%s]\n", evt_path,
|
||||||
|
@ -906,7 +912,7 @@ void print_events_type(u8 type)
|
||||||
__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
|
__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_hwcache_events(const char *event_glob)
|
int print_hwcache_events(const char *event_glob, bool name_only)
|
||||||
{
|
{
|
||||||
unsigned int type, op, i, printed = 0;
|
unsigned int type, op, i, printed = 0;
|
||||||
char name[64];
|
char name[64];
|
||||||
|
@ -923,6 +929,9 @@ int print_hwcache_events(const char *event_glob)
|
||||||
if (event_glob != NULL && !strglobmatch(name, event_glob))
|
if (event_glob != NULL && !strglobmatch(name, event_glob))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (name_only)
|
||||||
|
printf("%s ", name);
|
||||||
|
else
|
||||||
printf(" %-50s [%s]\n", name,
|
printf(" %-50s [%s]\n", name,
|
||||||
event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
||||||
++printed;
|
++printed;
|
||||||
|
@ -934,7 +943,8 @@ int print_hwcache_events(const char *event_glob)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_symbol_events(const char *event_glob, unsigned type,
|
static void print_symbol_events(const char *event_glob, unsigned type,
|
||||||
struct event_symbol *syms, unsigned max)
|
struct event_symbol *syms, unsigned max,
|
||||||
|
bool name_only)
|
||||||
{
|
{
|
||||||
unsigned i, printed = 0;
|
unsigned i, printed = 0;
|
||||||
char name[MAX_NAME_LEN];
|
char name[MAX_NAME_LEN];
|
||||||
|
@ -946,6 +956,11 @@ static void print_symbol_events(const char *event_glob, unsigned type,
|
||||||
(syms->alias && strglobmatch(syms->alias, event_glob))))
|
(syms->alias && strglobmatch(syms->alias, event_glob))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (name_only) {
|
||||||
|
printf("%s ", syms->symbol);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(syms->alias))
|
if (strlen(syms->alias))
|
||||||
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
|
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
|
||||||
else
|
else
|
||||||
|
@ -963,23 +978,25 @@ static void print_symbol_events(const char *event_glob, unsigned type,
|
||||||
/*
|
/*
|
||||||
* Print the help text for the event symbols:
|
* Print the help text for the event symbols:
|
||||||
*/
|
*/
|
||||||
void print_events(const char *event_glob)
|
void print_events(const char *event_glob, bool name_only)
|
||||||
{
|
{
|
||||||
|
if (!name_only) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("List of pre-defined events (to be used in -e):\n");
|
printf("List of pre-defined events (to be used in -e):\n");
|
||||||
|
}
|
||||||
|
|
||||||
print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
|
print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
|
||||||
event_symbols_hw, PERF_COUNT_HW_MAX);
|
event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
|
||||||
|
|
||||||
print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
|
print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
|
||||||
event_symbols_sw, PERF_COUNT_SW_MAX);
|
event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
|
||||||
|
|
||||||
print_hwcache_events(event_glob);
|
print_hwcache_events(event_glob, name_only);
|
||||||
|
|
||||||
if (event_glob != NULL)
|
if (event_glob != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!name_only) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" %-50s [%s]\n",
|
printf(" %-50s [%s]\n",
|
||||||
"rNNN",
|
"rNNN",
|
||||||
|
@ -994,8 +1011,9 @@ void print_events(const char *event_glob)
|
||||||
"mem:<addr>[:access]",
|
"mem:<addr>[:access]",
|
||||||
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
|
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
print_tracepoint_events(NULL, NULL);
|
print_tracepoint_events(NULL, NULL, name_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_events__is_hardcoded_term(struct parse_events__term *term)
|
int parse_events__is_hardcoded_term(struct parse_events__term *term)
|
||||||
|
|
|
@ -96,10 +96,11 @@ void parse_events_update_lists(struct list_head *list_event,
|
||||||
void parse_events_error(void *data, void *scanner, char const *msg);
|
void parse_events_error(void *data, void *scanner, char const *msg);
|
||||||
int parse_events__test(void);
|
int parse_events__test(void);
|
||||||
|
|
||||||
void print_events(const char *event_glob);
|
void print_events(const char *event_glob, bool name_only);
|
||||||
void print_events_type(u8 type);
|
void print_events_type(u8 type);
|
||||||
void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
|
void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
||||||
int print_hwcache_events(const char *event_glob);
|
bool name_only);
|
||||||
|
int print_hwcache_events(const char *event_glob, bool name_only);
|
||||||
extern int is_valid_tracepoint(const char *event_string);
|
extern int is_valid_tracepoint(const char *event_string);
|
||||||
|
|
||||||
extern int valid_debugfs_mount(const char *debugfs);
|
extern int valid_debugfs_mount(const char *debugfs);
|
||||||
|
|
Loading…
Reference in New Issue