]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - tools/perf/util/parse-events.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / tools / perf / util / parse-events.c
index 4af5bd59cfd14b475d0f2fa60e15f1b4b4e908de..135f69baf966d8a2a2525c6f9478958cf2932bf2 100644 (file)
@@ -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);
 }
@@ -279,7 +279,7 @@ const char *__event_name(int type, u64 config)
        static char buf[32];
 
        if (type == PERF_TYPE_RAW) {
-               sprintf(buf, "raw 0x%llx", config);
+               sprintf(buf, "raw 0x%" PRIx64, config);
                return buf;
        }
 
@@ -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;
@@ -490,12 +490,11 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
        return EVT_HANDLED_ALL;
 }
 
-
 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 +513,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,14 +528,14 @@ 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 + 1; /* 1 == the ':' */
                return parse_multiple_tracepoint_event(sys_name, evt_name,
                                                       flags);
-       } else
+       } else {
                return parse_single_tracepoint_event(sys_name, evt_name,
                                                     evt_length, attr, strp);
+       }
 }
 
 static enum event_result
@@ -774,45 +778,12 @@ modifier:
        return ret;
 }
 
-static int store_event_type(const char *orgname)
-{
-       char filename[PATH_MAX], *c;
-       FILE *file;
-       int id, n;
-
-       sprintf(filename, "%s/", debugfs_path);
-       strncat(filename, orgname, strlen(orgname));
-       strcat(filename, "/id");
-
-       c = strchr(filename, ':');
-       if (c)
-               *c = '/';
-
-       file = fopen(filename, "r");
-       if (!file)
-               return 0;
-       n = fscanf(file, "%i", &id);
-       fclose(file);
-       if (n < 1) {
-               pr_err("cannot store event ID\n");
-               return -EINVAL;
-       }
-       return perf_header__push_event(id, orgname);
-}
-
 int parse_events(const struct option *opt __used, const char *str, int unset __used)
 {
        struct perf_event_attr attr;
        enum event_result ret;
 
-       if (strchr(str, ':'))
-               if (store_event_type(str) < 0)
-                       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 +793,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,
+                                               nr_counters);
+                       if (evsel == NULL)
+                               return -1;
+                       list_add_tail(&evsel->node, &evsel_list);
+                       ++nr_counters;
                }
 
                if (*str == 0)
@@ -840,21 +816,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 (!list_empty(&evsel_list))
+               last = list_entry(evsel_list.prev, struct perf_evsel, node);
 
-       if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
+       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;
 }
@@ -905,6 +882,47 @@ static void print_tracepoint_events(void)
        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(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:
  */
@@ -963,3 +981,33 @@ void print_events(void)
 
        exit(129);
 }
+
+int perf_evsel_list__create_default(void)
+{
+       struct perf_evsel *evsel;
+       struct perf_event_attr attr;
+
+       memset(&attr, 0, sizeof(attr));
+       attr.type = PERF_TYPE_HARDWARE;
+       attr.config = PERF_COUNT_HW_CPU_CYCLES;
+
+       evsel = perf_evsel__new(&attr, 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;
+}