summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r--tools/perf/util/parse-events.c111
1 files changed, 91 insertions, 20 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4af5bd59cfd..649083f27e0 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
#include "../../../include/linux/hw_breakpoint.h"
#include "util.h"
#include "../perf.h"
+#include "evsel.h"
#include "parse-options.h"
#include "parse-events.h"
#include "exec_cmd.h"
@@ -12,8 +13,7 @@
int nr_counters;
-struct perf_event_attr attrs[MAX_COUNTERS];
-char *filters[MAX_COUNTERS];
+LIST_HEAD(evsel_list);
struct event_symbol {
u8 type;
@@ -266,10 +266,10 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
return name;
}
-const char *event_name(int counter)
+const char *event_name(struct perf_evsel *evsel)
{
- u64 config = attrs[counter].config;
- int type = attrs[counter].type;
+ u64 config = evsel->attr.config;
+ int type = evsel->attr.type;
return __event_name(type, config);
}
@@ -434,7 +434,7 @@ parse_single_tracepoint_event(char *sys_name,
id = atoll(id_buf);
attr->config = id;
attr->type = PERF_TYPE_TRACEPOINT;
- *strp = evt_name + evt_length;
+ *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
attr->sample_type |= PERF_SAMPLE_RAW;
attr->sample_type |= PERF_SAMPLE_TIME;
@@ -495,7 +495,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
struct perf_event_attr *attr)
{
const char *evt_name;
- char *flags;
+ char *flags = NULL, *comma_loc;
char sys_name[MAX_EVENT_LENGTH];
unsigned int sys_length, evt_length;
@@ -514,6 +514,11 @@ static enum event_result parse_tracepoint_event(const char **strp,
sys_name[sys_length] = '\0';
evt_name = evt_name + 1;
+ comma_loc = strchr(evt_name, ',');
+ if (comma_loc) {
+ /* take the event name up to the comma */
+ evt_name = strndup(evt_name, comma_loc - evt_name);
+ }
flags = strchr(evt_name, ':');
if (flags) {
/* split it out: */
@@ -524,9 +529,8 @@ static enum event_result parse_tracepoint_event(const char **strp,
evt_length = strlen(evt_name);
if (evt_length >= MAX_EVENT_LENGTH)
return EVT_FAILED;
-
if (strpbrk(evt_name, "*?")) {
- *strp = evt_name + evt_length;
+ *strp += strlen(sys_name) + evt_length;
return parse_multiple_tracepoint_event(sys_name, evt_name,
flags);
} else
@@ -810,9 +814,6 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
return -1;
for (;;) {
- if (nr_counters == MAX_COUNTERS)
- return -1;
-
memset(&attr, 0, sizeof(attr));
ret = parse_event_symbols(&str, &attr);
if (ret == EVT_FAILED)
@@ -822,8 +823,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
return -1;
if (ret != EVT_HANDLED_ALL) {
- attrs[nr_counters] = attr;
- nr_counters++;
+ struct perf_evsel *evsel;
+ evsel = perf_evsel__new(attr.type, attr.config,
+ nr_counters);
+ if (evsel == NULL)
+ return -1;
+ list_add_tail(&evsel->node, &evsel_list);
+ ++nr_counters;
}
if (*str == 0)
@@ -840,21 +846,22 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
int parse_filter(const struct option *opt __used, const char *str,
int unset __used)
{
- int i = nr_counters - 1;
- int len = strlen(str);
+ struct perf_evsel *last = NULL;
- if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
+ if (!list_empty(&evsel_list))
+ last = list_entry(evsel_list.prev, struct perf_evsel, node);
+
+ if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
fprintf(stderr,
"-F option should follow a -e tracepoint option\n");
return -1;
}
- filters[i] = malloc(len + 1);
- if (!filters[i]) {
+ last->filter = strdup(str);
+ if (last->filter == NULL) {
fprintf(stderr, "not enough memory to hold filter string\n");
return -1;
}
- strcpy(filters[i], str);
return 0;
}
@@ -906,6 +913,47 @@ static void print_tracepoint_events(void)
}
/*
+ * 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(debugfs_path))
+ return 0;
+
+ sys_dir = opendir(debugfs_path);
+ if (!sys_dir)
+ return 0;
+
+ for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+
+ snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_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;
+}
+
+/*
* Print the help text for the event symbols:
*/
void print_events(void)
@@ -963,3 +1011,26 @@ void print_events(void)
exit(129);
}
+
+int perf_evsel_list__create_default(void)
+{
+ struct perf_evsel *evsel = perf_evsel__new(PERF_TYPE_HARDWARE,
+ PERF_COUNT_HW_CPU_CYCLES, 0);
+ if (evsel == NULL)
+ return -ENOMEM;
+
+ list_add(&evsel->node, &evsel_list);
+ ++nr_counters;
+ return 0;
+}
+
+void perf_evsel_list__delete(void)
+{
+ struct perf_evsel *pos, *n;
+
+ list_for_each_entry_safe(pos, n, &evsel_list, node) {
+ list_del_init(&pos->node);
+ perf_evsel__delete(pos);
+ }
+ nr_counters = 0;
+}