aboutsummaryrefslogtreecommitdiffstats
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 4af5bd59cfd1..649083f27e08 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
1#include "../../../include/linux/hw_breakpoint.h" 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "evsel.h"
4#include "parse-options.h" 5#include "parse-options.h"
5#include "parse-events.h" 6#include "parse-events.h"
6#include "exec_cmd.h" 7#include "exec_cmd.h"
@@ -12,8 +13,7 @@
12 13
13int nr_counters; 14int nr_counters;
14 15
15struct perf_event_attr attrs[MAX_COUNTERS]; 16LIST_HEAD(evsel_list);
16char *filters[MAX_COUNTERS];
17 17
18struct event_symbol { 18struct event_symbol {
19 u8 type; 19 u8 type;
@@ -266,10 +266,10 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
266 return name; 266 return name;
267} 267}
268 268
269const char *event_name(int counter) 269const char *event_name(struct perf_evsel *evsel)
270{ 270{
271 u64 config = attrs[counter].config; 271 u64 config = evsel->attr.config;
272 int type = attrs[counter].type; 272 int type = evsel->attr.type;
273 273
274 return __event_name(type, config); 274 return __event_name(type, config);
275} 275}
@@ -434,7 +434,7 @@ parse_single_tracepoint_event(char *sys_name,
434 id = atoll(id_buf); 434 id = atoll(id_buf);
435 attr->config = id; 435 attr->config = id;
436 attr->type = PERF_TYPE_TRACEPOINT; 436 attr->type = PERF_TYPE_TRACEPOINT;
437 *strp = evt_name + evt_length; 437 *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
438 438
439 attr->sample_type |= PERF_SAMPLE_RAW; 439 attr->sample_type |= PERF_SAMPLE_RAW;
440 attr->sample_type |= PERF_SAMPLE_TIME; 440 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -495,7 +495,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
495 struct perf_event_attr *attr) 495 struct perf_event_attr *attr)
496{ 496{
497 const char *evt_name; 497 const char *evt_name;
498 char *flags; 498 char *flags = NULL, *comma_loc;
499 char sys_name[MAX_EVENT_LENGTH]; 499 char sys_name[MAX_EVENT_LENGTH];
500 unsigned int sys_length, evt_length; 500 unsigned int sys_length, evt_length;
501 501
@@ -514,6 +514,11 @@ static enum event_result parse_tracepoint_event(const char **strp,
514 sys_name[sys_length] = '\0'; 514 sys_name[sys_length] = '\0';
515 evt_name = evt_name + 1; 515 evt_name = evt_name + 1;
516 516
517 comma_loc = strchr(evt_name, ',');
518 if (comma_loc) {
519 /* take the event name up to the comma */
520 evt_name = strndup(evt_name, comma_loc - evt_name);
521 }
517 flags = strchr(evt_name, ':'); 522 flags = strchr(evt_name, ':');
518 if (flags) { 523 if (flags) {
519 /* split it out: */ 524 /* split it out: */
@@ -524,9 +529,8 @@ static enum event_result parse_tracepoint_event(const char **strp,
524 evt_length = strlen(evt_name); 529 evt_length = strlen(evt_name);
525 if (evt_length >= MAX_EVENT_LENGTH) 530 if (evt_length >= MAX_EVENT_LENGTH)
526 return EVT_FAILED; 531 return EVT_FAILED;
527
528 if (strpbrk(evt_name, "*?")) { 532 if (strpbrk(evt_name, "*?")) {
529 *strp = evt_name + evt_length; 533 *strp += strlen(sys_name) + evt_length;
530 return parse_multiple_tracepoint_event(sys_name, evt_name, 534 return parse_multiple_tracepoint_event(sys_name, evt_name,
531 flags); 535 flags);
532 } else 536 } else
@@ -810,9 +814,6 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
810 return -1; 814 return -1;
811 815
812 for (;;) { 816 for (;;) {
813 if (nr_counters == MAX_COUNTERS)
814 return -1;
815
816 memset(&attr, 0, sizeof(attr)); 817 memset(&attr, 0, sizeof(attr));
817 ret = parse_event_symbols(&str, &attr); 818 ret = parse_event_symbols(&str, &attr);
818 if (ret == EVT_FAILED) 819 if (ret == EVT_FAILED)
@@ -822,8 +823,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
822 return -1; 823 return -1;
823 824
824 if (ret != EVT_HANDLED_ALL) { 825 if (ret != EVT_HANDLED_ALL) {
825 attrs[nr_counters] = attr; 826 struct perf_evsel *evsel;
826 nr_counters++; 827 evsel = perf_evsel__new(attr.type, attr.config,
828 nr_counters);
829 if (evsel == NULL)
830 return -1;
831 list_add_tail(&evsel->node, &evsel_list);
832 ++nr_counters;
827 } 833 }
828 834
829 if (*str == 0) 835 if (*str == 0)
@@ -840,21 +846,22 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
840int parse_filter(const struct option *opt __used, const char *str, 846int parse_filter(const struct option *opt __used, const char *str,
841 int unset __used) 847 int unset __used)
842{ 848{
843 int i = nr_counters - 1; 849 struct perf_evsel *last = NULL;
844 int len = strlen(str);
845 850
846 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 851 if (!list_empty(&evsel_list))
852 last = list_entry(evsel_list.prev, struct perf_evsel, node);
853
854 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
847 fprintf(stderr, 855 fprintf(stderr,
848 "-F option should follow a -e tracepoint option\n"); 856 "-F option should follow a -e tracepoint option\n");
849 return -1; 857 return -1;
850 } 858 }
851 859
852 filters[i] = malloc(len + 1); 860 last->filter = strdup(str);
853 if (!filters[i]) { 861 if (last->filter == NULL) {
854 fprintf(stderr, "not enough memory to hold filter string\n"); 862 fprintf(stderr, "not enough memory to hold filter string\n");
855 return -1; 863 return -1;
856 } 864 }
857 strcpy(filters[i], str);
858 865
859 return 0; 866 return 0;
860} 867}
@@ -906,6 +913,47 @@ static void print_tracepoint_events(void)
906} 913}
907 914
908/* 915/*
916 * Check whether event is in <debugfs_mount_point>/tracing/events
917 */
918
919int is_valid_tracepoint(const char *event_string)
920{
921 DIR *sys_dir, *evt_dir;
922 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
923 char evt_path[MAXPATHLEN];
924 char dir_path[MAXPATHLEN];
925
926 if (debugfs_valid_mountpoint(debugfs_path))
927 return 0;
928
929 sys_dir = opendir(debugfs_path);
930 if (!sys_dir)
931 return 0;
932
933 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
934
935 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
936 sys_dirent.d_name);
937 evt_dir = opendir(dir_path);
938 if (!evt_dir)
939 continue;
940
941 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
942 snprintf(evt_path, MAXPATHLEN, "%s:%s",
943 sys_dirent.d_name, evt_dirent.d_name);
944 if (!strcmp(evt_path, event_string)) {
945 closedir(evt_dir);
946 closedir(sys_dir);
947 return 1;
948 }
949 }
950 closedir(evt_dir);
951 }
952 closedir(sys_dir);
953 return 0;
954}
955
956/*
909 * Print the help text for the event symbols: 957 * Print the help text for the event symbols:
910 */ 958 */
911void print_events(void) 959void print_events(void)
@@ -963,3 +1011,26 @@ void print_events(void)
963 1011
964 exit(129); 1012 exit(129);
965} 1013}
1014
1015int perf_evsel_list__create_default(void)
1016{
1017 struct perf_evsel *evsel = perf_evsel__new(PERF_TYPE_HARDWARE,
1018 PERF_COUNT_HW_CPU_CYCLES, 0);
1019 if (evsel == NULL)
1020 return -ENOMEM;
1021
1022 list_add(&evsel->node, &evsel_list);
1023 ++nr_counters;
1024 return 0;
1025}
1026
1027void perf_evsel_list__delete(void)
1028{
1029 struct perf_evsel *pos, *n;
1030
1031 list_for_each_entry_safe(pos, n, &evsel_list, node) {
1032 list_del_init(&pos->node);
1033 perf_evsel__delete(pos);
1034 }
1035 nr_counters = 0;
1036}