Commit e4cc9f4a authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
parents e9345aab 668b8788
...@@ -8,7 +8,7 @@ perf-list - List all symbolic event types ...@@ -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. ...@@ -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 @@ ...@@ -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 @@ ...@@ -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;
} }
...@@ -538,11 +538,6 @@ static int __cmd_record(int argc, const char **argv) ...@@ -538,11 +538,6 @@ static int __cmd_record(int argc, const char **argv)
if (have_tracepoints(&evsel_list->entries)) if (have_tracepoints(&evsel_list->entries))
perf_header__set_feat(&session->header, HEADER_TRACE_INFO); perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
/*
* perf_session__delete(session) will be called at atexit_header()
*/
atexit(atexit_header);
if (forks) { if (forks) {
child_pid = fork(); child_pid = fork();
if (child_pid < 0) { if (child_pid < 0) {
...@@ -601,6 +596,11 @@ static int __cmd_record(int argc, const char **argv) ...@@ -601,6 +596,11 @@ static int __cmd_record(int argc, const char **argv)
perf_session__set_sample_type(session, sample_type); perf_session__set_sample_type(session, sample_type);
/*
* perf_session__delete(session) will be called at atexit_header()
*/
atexit(atexit_header);
if (pipe_output) { if (pipe_output) {
err = perf_header__write_pipe(output); err = perf_header__write_pipe(output);
if (err < 0) if (err < 0)
......
...@@ -350,6 +350,12 @@ static int __cmd_report(void) ...@@ -350,6 +350,12 @@ static int __cmd_report(void)
perf_session__fprintf_dsos(session, stdout); perf_session__fprintf_dsos(session, stdout);
next = rb_first(&session->hists_tree); next = rb_first(&session->hists_tree);
if (next == NULL) {
ui__warning("The %s file has no samples!\n", input_name);
goto out_delete;
}
while (next) { while (next) {
struct hists *hists; struct hists *hists;
......
...@@ -86,6 +86,7 @@ void perf_evsel__delete(struct perf_evsel *evsel) ...@@ -86,6 +86,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)
{ {
perf_evsel__exit(evsel); perf_evsel__exit(evsel);
close_cgroup(evsel->cgrp); close_cgroup(evsel->cgrp);
free(evsel->name);
free(evsel); free(evsel);
} }
......
...@@ -37,6 +37,12 @@ struct perf_sample_id { ...@@ -37,6 +37,12 @@ struct perf_sample_id {
struct perf_evsel *evsel; struct perf_evsel *evsel;
}; };
/** struct perf_evsel - event selector
*
* @name - Can be set to retain the original event name passed by the user,
* so that when showing results in tools such as 'perf stat', we
* show the name used, not some alias.
*/
struct perf_evsel { struct perf_evsel {
struct list_head node; struct list_head node;
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -45,6 +51,7 @@ struct perf_evsel { ...@@ -45,6 +51,7 @@ struct perf_evsel {
struct xyarray *id; struct xyarray *id;
struct perf_counts *counts; struct perf_counts *counts;
int idx; int idx;
char *name;
void *priv; void *priv;
struct cgroup_sel *cgrp; struct cgroup_sel *cgrp;
}; };
......
...@@ -591,6 +591,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, ...@@ -591,6 +591,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
{ {
struct sort_entry *se; struct sort_entry *se;
u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
u64 nr_events;
const char *sep = symbol_conf.field_sep; const char *sep = symbol_conf.field_sep;
int ret; int ret;
...@@ -599,6 +600,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, ...@@ -599,6 +600,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
if (pair_hists) { if (pair_hists) {
period = self->pair ? self->pair->period : 0; period = self->pair ? self->pair->period : 0;
nr_events = self->pair ? self->pair->nr_events : 0;
total = pair_hists->stats.total_period; total = pair_hists->stats.total_period;
period_sys = self->pair ? self->pair->period_sys : 0; period_sys = self->pair ? self->pair->period_sys : 0;
period_us = self->pair ? self->pair->period_us : 0; period_us = self->pair ? self->pair->period_us : 0;
...@@ -606,6 +608,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, ...@@ -606,6 +608,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
period_guest_us = self->pair ? self->pair->period_guest_us : 0; period_guest_us = self->pair ? self->pair->period_guest_us : 0;
} else { } else {
period = self->period; period = self->period;
nr_events = self->nr_events;
total = session_total; total = session_total;
period_sys = self->period_sys; period_sys = self->period_sys;
period_us = self->period_us; period_us = self->period_us;
...@@ -646,9 +649,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, ...@@ -646,9 +649,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
if (symbol_conf.show_nr_samples) { if (symbol_conf.show_nr_samples) {
if (sep) if (sep)
ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
else else
ret += snprintf(s + ret, size - ret, "%11" PRIu64, period); ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
} }
if (pair_hists) { if (pair_hists) {
......
...@@ -268,6 +268,9 @@ const char *event_name(struct perf_evsel *evsel) ...@@ -268,6 +268,9 @@ const char *event_name(struct perf_evsel *evsel)
u64 config = evsel->attr.config; u64 config = evsel->attr.config;
int type = evsel->attr.type; int type = evsel->attr.type;
if (evsel->name)
return evsel->name;
return __event_name(type, config); return __event_name(type, config);
} }
...@@ -782,8 +785,10 @@ int parse_events(const struct option *opt, const char *str, int unset __used) ...@@ -782,8 +785,10 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
struct perf_event_attr attr; struct perf_event_attr attr;
enum event_result ret; enum event_result ret;
const char *ostr;
for (;;) { for (;;) {
ostr = str;
memset(&attr, 0, sizeof(attr)); memset(&attr, 0, sizeof(attr));
ret = parse_event_symbols(opt, &str, &attr); ret = parse_event_symbols(opt, &str, &attr);
if (ret == EVT_FAILED) if (ret == EVT_FAILED)
...@@ -798,6 +803,11 @@ int parse_events(const struct option *opt, const char *str, int unset __used) ...@@ -798,6 +803,11 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
if (evsel == NULL) if (evsel == NULL)
return -1; return -1;
perf_evlist__add(evlist, evsel); perf_evlist__add(evlist, evsel);
evsel->name = calloc(str - ostr + 1, 1);
if (!evsel->name)
return -1;
strncpy(evsel->name, ostr, str - ostr);
} }
if (*str == 0) if (*str == 0)
...@@ -848,7 +858,7 @@ static const char * const event_type_descriptors[] = { ...@@ -848,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;
...@@ -863,6 +873,9 @@ static void print_tracepoint_events(void) ...@@ -863,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);
...@@ -871,6 +884,10 @@ static void print_tracepoint_events(void) ...@@ -871,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,
...@@ -922,13 +939,61 @@ int is_valid_tracepoint(const char *event_string) ...@@ -922,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");
...@@ -937,8 +1002,16 @@ void print_events(void) ...@@ -937,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);
...@@ -948,22 +1021,17 @@ void print_events(void) ...@@ -948,22 +1021,17 @@ void print_events(void)
event_type_descriptors[type]); event_type_descriptors[type]);
prev_type = type; prev_type = type;
++printed;
} }
printf("\n"); if (ntypes_printed) {
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { printed = 0;
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { printf("\n");
/* skip invalid cache type */
if (!is_cache_op_valid(type, op))
continue;
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
printf(" %-42s [%s]\n",
event_cache_name(type, op, i),
event_type_descriptors[PERF_TYPE_HW_CACHE]);
}
}
} }
print_hwcache_events(event_glob);
if (event_glob != NULL)
return;
printf("\n"); printf("\n");
printf(" %-42s [%s]\n", printf(" %-42s [%s]\n",
...@@ -976,7 +1044,7 @@ void print_events(void) ...@@ -976,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); ...@@ -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[];
......
...@@ -5,7 +5,7 @@ from distutils.core import setup, Extension ...@@ -5,7 +5,7 @@ from distutils.core import setup, Extension
perf = Extension('perf', perf = Extension('perf',
sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
'util/util.c', 'util/xyarray.c'], 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
include_dirs = ['util/include'], include_dirs = ['util/include'],
extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings']) extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings'])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment