Newer
Older
if (debugfs_valid_mountpoint(tracing_events_path))
return;
sys_dir = opendir(tracing_events_path);
if (!sys_dir)
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", tracing_events_path,
sys_dirent.d_name);
evt_dir = opendir(dir_path);
if (!evt_dir)
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
if (event_glob != NULL &&
!strglobmatch(evt_dirent.d_name, event_glob))
continue;
if (name_only) {
printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
continue;
}
snprintf(evt_path, MAXPATHLEN, "%s:%s",
sys_dirent.d_name, evt_dirent.d_name);
event_type_descriptors[PERF_TYPE_TRACEPOINT]);
}
closedir(evt_dir);
}
closedir(sys_dir);
}
/*
* Check whether event is in <debugfs_mount_point>/tracing/events
*/
int is_valid_tracepoint(const char *event_string)
{
DIR *sys_dir, *evt_dir;
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
char evt_path[MAXPATHLEN];
char dir_path[MAXPATHLEN];
if (debugfs_valid_mountpoint(tracing_events_path))
return 0;
sys_dir = opendir(tracing_events_path);
if (!sys_dir)
return 0;
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
sys_dirent.d_name);
evt_dir = opendir(dir_path);
if (!evt_dir)
continue;
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
snprintf(evt_path, MAXPATHLEN, "%s:%s",
sys_dirent.d_name, evt_dirent.d_name);
if (!strcmp(evt_path, event_string)) {
closedir(evt_dir);
closedir(sys_dir);
return 1;
}
}
closedir(evt_dir);
}
closedir(sys_dir);
return 0;
}
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
static bool is_event_supported(u8 type, unsigned config)
{
bool ret = true;
struct perf_evsel *evsel;
struct perf_event_attr attr = {
.type = type,
.config = config,
.disabled = 1,
.exclude_kernel = 1,
};
struct {
struct thread_map map;
int threads[1];
} tmap = {
.map.nr = 1,
.threads = { 0 },
};
evsel = perf_evsel__new(&attr, 0);
if (evsel) {
ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
perf_evsel__delete(evsel);
}
return ret;
}
static void __print_events_type(u8 type, struct event_symbol *syms,
unsigned max)
{
char name[64];
for (i = 0; i < max ; i++, syms++) {
if (!is_event_supported(type, i))
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(" %-50s [%s]\n", name, event_type_descriptors[type]);
void print_events_type(u8 type)
{
if (type == PERF_TYPE_SOFTWARE)
__print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
else
__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
}
int print_hwcache_events(const char *event_glob, bool name_only)
{
unsigned int type, op, i, printed = 0;

Arnaldo Carvalho de Melo
committed
char name[64];
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 */

Arnaldo Carvalho de Melo
committed
if (!perf_evsel__is_cache_op_valid(type, op))
continue;
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {

Arnaldo Carvalho de Melo
committed
__perf_evsel__hw_cache_type_op_res_name(type, op, i,
name, sizeof(name));
if (event_glob != NULL && !strglobmatch(name, event_glob))
if (!is_event_supported(PERF_TYPE_HW_CACHE,
type | (op << 8) | (i << 16)))
continue;
if (name_only)
printf("%s ", name);
else
printf(" %-50s [%s]\n", name,
event_type_descriptors[PERF_TYPE_HW_CACHE]);
++printed;
}
}
}
if (printed)
printf("\n");
return printed;
}
static void print_symbol_events(const char *event_glob, unsigned type,
struct event_symbol *syms, unsigned max,
bool name_only)
unsigned i, printed = 0;
for (i = 0; i < max; i++, syms++) {
if (event_glob != NULL &&
!(strglobmatch(syms->symbol, event_glob) ||
(syms->alias && strglobmatch(syms->alias, event_glob))))
continue;
if (!is_event_supported(type, i))
continue;
if (name_only) {
printf("%s ", syms->symbol);
continue;
}
if (strlen(syms->alias))
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
else
strncpy(name, syms->symbol, MAX_NAME_LEN);
printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
printed++;
}
/*
* Print the help text for the event symbols:
*/
void print_events(const char *event_glob, bool name_only)
if (!name_only) {
printf("\n");
printf("List of pre-defined events (to be used in -e):\n");
}
print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
print_hwcache_events(event_glob, name_only);
print_pmu_events(event_glob, name_only);
if (event_glob != NULL)
return;
if (!name_only) {
printf(" %-50s [%s]\n",
"rNNN",
event_type_descriptors[PERF_TYPE_RAW]);
printf(" %-50s [%s]\n",
"cpu/t1=v1[,t2=v2,t3 ...]/modifier",
event_type_descriptors[PERF_TYPE_RAW]);
printf(" (see 'man perf-list' on how to encode it)\n");
printf("\n");
printf(" %-50s [%s]\n",
"mem:<addr>[:access]",
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
printf("\n");
}
print_tracepoint_events(NULL, NULL, name_only);
int parse_events__is_hardcoded_term(struct parse_events_term *term)
return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
static int new_term(struct parse_events_term **_term, int type_val,
int type_term, char *config,
char *str, u64 num)
struct parse_events_term *term;
term = zalloc(sizeof(*term));
if (!term)
return -ENOMEM;
INIT_LIST_HEAD(&term->list);
term->type_val = type_val;
term->type_term = type_term;
term->config = config;
switch (type_val) {
case PARSE_EVENTS__TERM_TYPE_NUM:
term->val.num = num;
break;
case PARSE_EVENTS__TERM_TYPE_STR:
term->val.str = str;
break;
default:
return -EINVAL;
}
*_term = term;
return 0;
}
int parse_events_term__num(struct parse_events_term **term,
int type_term, char *config, u64 num)
{
return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
config, NULL, num);
}
int parse_events_term__str(struct parse_events_term **term,
int type_term, char *config, char *str)
{
return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
config, str, 0);
}
int parse_events_term__sym_hw(struct parse_events_term **term,
char *config, unsigned idx)
{
struct event_symbol *sym;
BUG_ON(idx >= PERF_COUNT_HW_MAX);
sym = &event_symbols_hw[idx];
if (config)
return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
PARSE_EVENTS__TERM_TYPE_USER, config,
(char *) sym->symbol, 0);
else
return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
PARSE_EVENTS__TERM_TYPE_USER,
(char *) "event", (char *) sym->symbol, 0);
}
int parse_events_term__clone(struct parse_events_term **new,
struct parse_events_term *term)
{
return new_term(new, term->type_val, term->type_term, term->config,
term->val.str, term->val.num);
}
void parse_events__free_terms(struct list_head *terms)
{
struct parse_events_term *term, *h;