forked from Minki/linux
perf list: Allow filtering list of events
The man page has the details, here are some examples: [root@emilia ~]# perf list *fault* *:*wait* List of pre-defined events (to be used in -e): page-faults OR faults [Software event] minor-faults [Software event] major-faults [Software event] alignment-faults [Software event] emulation-faults [Software event] radeon:radeon_fence_wait_begin [Tracepoint event] radeon:radeon_fence_wait_end [Tracepoint event] writeback:wbc_writeback_wait [Tracepoint event] writeback:wbc_balance_dirty_wait [Tracepoint event] writeback:writeback_congestion_wait [Tracepoint event] writeback:writeback_wait_iff_congested [Tracepoint event] sched:sched_wait_task [Tracepoint event] sched:sched_process_wait [Tracepoint event] sched:sched_stat_wait [Tracepoint event] sched:sched_stat_iowait [Tracepoint event] syscalls:sys_enter_epoll_wait [Tracepoint event] syscalls:sys_exit_epoll_wait [Tracepoint event] syscalls:sys_enter_epoll_pwait [Tracepoint event] syscalls:sys_exit_epoll_pwait [Tracepoint event] syscalls:sys_enter_rt_sigtimedwait [Tracepoint event] syscalls:sys_exit_rt_sigtimedwait [Tracepoint event] syscalls:sys_enter_waitid [Tracepoint event] syscalls:sys_exit_waitid [Tracepoint event] syscalls:sys_enter_wait4 [Tracepoint event] syscalls:sys_exit_wait4 [Tracepoint event] syscalls:sys_enter_waitpid [Tracepoint event] syscalls:sys_exit_waitpid [Tracepoint event] [root@emilia ~]# Suggested-by: Ingo Molnar <mingo@elte.hu> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
74cfc17dc1
commit
668b8788f4
@ -8,7 +8,7 @@ perf-list - List all symbolic event types
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'perf list'
|
'perf list' [hw|sw|cache|tracepoint|event_glob]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -63,7 +63,26 @@ details. Some of them are referenced in the SEE ALSO section below.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
None
|
|
||||||
|
Without options all known events will be listed.
|
||||||
|
|
||||||
|
To limit the list use:
|
||||||
|
|
||||||
|
. 'hw' or 'hardware' to list hardware events such as cache-misses, etc.
|
||||||
|
|
||||||
|
. 'sw' or 'software' to list software events such as context switches, etc.
|
||||||
|
|
||||||
|
. 'cache' or 'hwcache' to list hardware cache events such as L1-dcache-loads, etc.
|
||||||
|
|
||||||
|
. 'tracepoint' to list all tracepoint events, alternatively use
|
||||||
|
'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
|
||||||
|
block, etc.
|
||||||
|
|
||||||
|
. If none of the above is matched, it will apply the supplied glob to all
|
||||||
|
events, printing the ones that match.
|
||||||
|
|
||||||
|
One or more types can be used at the same time, listing the events for the
|
||||||
|
types specified.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
|
* Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
|
||||||
* Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
|
* Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
|
||||||
|
* Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||||
*/
|
*/
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
|
||||||
@ -13,9 +14,47 @@
|
|||||||
#include "util/parse-events.h"
|
#include "util/parse-events.h"
|
||||||
#include "util/cache.h"
|
#include "util/cache.h"
|
||||||
|
|
||||||
int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
|
int cmd_list(int argc, const char **argv, const char *prefix __used)
|
||||||
{
|
{
|
||||||
setup_pager();
|
setup_pager();
|
||||||
print_events();
|
|
||||||
|
if (argc == 1)
|
||||||
|
print_events(NULL);
|
||||||
|
else {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
|
if (i > 1)
|
||||||
|
putchar('\n');
|
||||||
|
if (strncmp(argv[i], "tracepoint", 10) == 0)
|
||||||
|
print_tracepoint_events(NULL, NULL);
|
||||||
|
else if (strcmp(argv[i], "hw") == 0 ||
|
||||||
|
strcmp(argv[i], "hardware") == 0)
|
||||||
|
print_events_type(PERF_TYPE_HARDWARE);
|
||||||
|
else if (strcmp(argv[i], "sw") == 0 ||
|
||||||
|
strcmp(argv[i], "software") == 0)
|
||||||
|
print_events_type(PERF_TYPE_SOFTWARE);
|
||||||
|
else if (strcmp(argv[i], "cache") == 0 ||
|
||||||
|
strcmp(argv[i], "hwcache") == 0)
|
||||||
|
print_hwcache_events(NULL);
|
||||||
|
else {
|
||||||
|
char *sep = strchr(argv[i], ':'), *s;
|
||||||
|
int sep_idx;
|
||||||
|
|
||||||
|
if (sep == NULL) {
|
||||||
|
print_events(argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sep_idx = sep - argv[i];
|
||||||
|
s = strdup(argv[i]);
|
||||||
|
if (s == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
s[sep_idx] = '\0';
|
||||||
|
print_tracepoint_events(s, s + sep_idx + 1);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -858,7 +858,7 @@ 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void print_tracepoint_events(void)
|
void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
|
||||||
{
|
{
|
||||||
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;
|
||||||
@ -873,6 +873,9 @@ static void print_tracepoint_events(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
|
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
|
||||||
|
if (subsys_glob != NULL &&
|
||||||
|
!strglobmatch(sys_dirent.d_name, subsys_glob))
|
||||||
|
continue;
|
||||||
|
|
||||||
snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
|
snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
|
||||||
sys_dirent.d_name);
|
sys_dirent.d_name);
|
||||||
@ -881,6 +884,10 @@ static void print_tracepoint_events(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
|
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
|
||||||
|
if (event_glob != NULL &&
|
||||||
|
!strglobmatch(evt_dirent.d_name, event_glob))
|
||||||
|
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(" %-42s [%s]\n", evt_path,
|
printf(" %-42s [%s]\n", evt_path,
|
||||||
@ -932,13 +939,61 @@ int is_valid_tracepoint(const char *event_string)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_events_type(u8 type)
|
||||||
|
{
|
||||||
|
struct event_symbol *syms = event_symbols;
|
||||||
|
unsigned int i;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
|
||||||
|
if (type != syms->type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strlen(syms->alias))
|
||||||
|
snprintf(name, sizeof(name), "%s OR %s",
|
||||||
|
syms->symbol, syms->alias);
|
||||||
|
else
|
||||||
|
snprintf(name, sizeof(name), "%s", syms->symbol);
|
||||||
|
|
||||||
|
printf(" %-42s [%s]\n", name,
|
||||||
|
event_type_descriptors[type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_hwcache_events(const char *event_glob)
|
||||||
|
{
|
||||||
|
unsigned int type, op, i, printed = 0;
|
||||||
|
|
||||||
|
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
|
||||||
|
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
|
||||||
|
/* skip invalid cache type */
|
||||||
|
if (!is_cache_op_valid(type, op))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
|
||||||
|
char *name = event_cache_name(type, op, i);
|
||||||
|
|
||||||
|
if (event_glob != NULL &&
|
||||||
|
!strglobmatch(name, event_glob))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf(" %-42s [%s]\n", name,
|
||||||
|
event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
||||||
|
++printed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return printed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print the help text for the event symbols:
|
* Print the help text for the event symbols:
|
||||||
*/
|
*/
|
||||||
void print_events(void)
|
void print_events(const char *event_glob)
|
||||||
{
|
{
|
||||||
struct event_symbol *syms = event_symbols;
|
struct event_symbol *syms = event_symbols;
|
||||||
unsigned int i, type, op, prev_type = -1;
|
unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
|
||||||
char name[40];
|
char name[40];
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -947,8 +1002,16 @@ void print_events(void)
|
|||||||
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
|
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
|
||||||
type = syms->type;
|
type = syms->type;
|
||||||
|
|
||||||
if (type != prev_type)
|
if (type != prev_type && printed) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
printed = 0;
|
||||||
|
ntypes_printed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event_glob != NULL &&
|
||||||
|
!(strglobmatch(syms->symbol, event_glob) ||
|
||||||
|
(syms->alias && strglobmatch(syms->alias, event_glob))))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (strlen(syms->alias))
|
if (strlen(syms->alias))
|
||||||
sprintf(name, "%s OR %s", syms->symbol, syms->alias);
|
sprintf(name, "%s OR %s", syms->symbol, syms->alias);
|
||||||
@ -958,22 +1021,17 @@ void print_events(void)
|
|||||||
event_type_descriptors[type]);
|
event_type_descriptors[type]);
|
||||||
|
|
||||||
prev_type = type;
|
prev_type = type;
|
||||||
|
++printed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ntypes_printed) {
|
||||||
|
printed = 0;
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
|
}
|
||||||
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
|
print_hwcache_events(event_glob);
|
||||||
/* skip invalid cache type */
|
|
||||||
if (!is_cache_op_valid(type, op))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
|
if (event_glob != NULL)
|
||||||
printf(" %-42s [%s]\n",
|
return;
|
||||||
event_cache_name(type, op, i),
|
|
||||||
event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" %-42s [%s]\n",
|
printf(" %-42s [%s]\n",
|
||||||
@ -986,7 +1044,7 @@ void print_events(void)
|
|||||||
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
|
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
print_tracepoint_events();
|
print_tracepoint_events(NULL, NULL);
|
||||||
|
|
||||||
exit(129);
|
exit(129);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,10 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
|
|||||||
|
|
||||||
#define EVENTS_HELP_MAX (128*1024)
|
#define EVENTS_HELP_MAX (128*1024)
|
||||||
|
|
||||||
extern void print_events(void);
|
void print_events(const char *event_glob);
|
||||||
|
void print_events_type(u8 type);
|
||||||
|
void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
|
||||||
|
int print_hwcache_events(const char *event_glob);
|
||||||
extern int is_valid_tracepoint(const char *event_string);
|
extern int is_valid_tracepoint(const char *event_string);
|
||||||
|
|
||||||
extern char debugfs_path[];
|
extern char debugfs_path[];
|
||||||
|
Loading…
Reference in New Issue
Block a user