diff options
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/evsel.c | 88 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 5 |
2 files changed, 87 insertions, 6 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1506ba0453f1..00936ad29ff2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
| 11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
| 12 | #include "asm/bug.h" | 12 | #include "asm/bug.h" |
| 13 | #include "debugfs.h" | ||
| 13 | #include "event-parse.h" | 14 | #include "event-parse.h" |
| 14 | #include "evsel.h" | 15 | #include "evsel.h" |
| 15 | #include "evlist.h" | 16 | #include "evlist.h" |
| @@ -69,6 +70,72 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) | |||
| 69 | return evsel; | 70 | return evsel; |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 73 | static struct event_format *event_format__new(const char *sys, const char *name) | ||
| 74 | { | ||
| 75 | int fd, n; | ||
| 76 | char *filename; | ||
| 77 | void *bf = NULL, *nbf; | ||
| 78 | size_t size = 0, alloc_size = 0; | ||
| 79 | struct event_format *format = NULL; | ||
| 80 | |||
| 81 | if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) | ||
| 82 | goto out; | ||
| 83 | |||
| 84 | fd = open(filename, O_RDONLY); | ||
| 85 | if (fd < 0) | ||
| 86 | goto out_free_filename; | ||
| 87 | |||
| 88 | do { | ||
| 89 | if (size == alloc_size) { | ||
| 90 | alloc_size += BUFSIZ; | ||
| 91 | nbf = realloc(bf, alloc_size); | ||
| 92 | if (nbf == NULL) | ||
| 93 | goto out_free_bf; | ||
| 94 | bf = nbf; | ||
| 95 | } | ||
| 96 | |||
| 97 | n = read(fd, bf + size, BUFSIZ); | ||
| 98 | if (n < 0) | ||
| 99 | goto out_free_bf; | ||
| 100 | size += n; | ||
| 101 | } while (n > 0); | ||
| 102 | |||
| 103 | pevent_parse_format(&format, bf, size, sys); | ||
| 104 | |||
| 105 | out_free_bf: | ||
| 106 | free(bf); | ||
| 107 | close(fd); | ||
| 108 | out_free_filename: | ||
| 109 | free(filename); | ||
| 110 | out: | ||
| 111 | return format; | ||
| 112 | } | ||
| 113 | |||
| 114 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) | ||
| 115 | { | ||
| 116 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | ||
| 117 | |||
| 118 | if (evsel != NULL) { | ||
| 119 | struct perf_event_attr attr = { | ||
| 120 | .type = PERF_TYPE_TRACEPOINT, | ||
| 121 | }; | ||
| 122 | |||
| 123 | evsel->tp_format = event_format__new(sys, name); | ||
| 124 | if (evsel->tp_format == NULL) | ||
| 125 | goto out_free; | ||
| 126 | |||
| 127 | attr.config = evsel->tp_format->id; | ||
| 128 | perf_evsel__init(evsel, &attr, idx); | ||
| 129 | evsel->name = evsel->tp_format->name; | ||
| 130 | } | ||
| 131 | |||
| 132 | return evsel; | ||
| 133 | |||
| 134 | out_free: | ||
| 135 | free(evsel); | ||
| 136 | return NULL; | ||
| 137 | } | ||
| 138 | |||
| 72 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { | 139 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { |
| 73 | "cycles", | 140 | "cycles", |
| 74 | "instructions", | 141 | "instructions", |
| @@ -495,6 +562,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
| 495 | perf_evsel__exit(evsel); | 562 | perf_evsel__exit(evsel); |
| 496 | close_cgroup(evsel->cgrp); | 563 | close_cgroup(evsel->cgrp); |
| 497 | free(evsel->group_name); | 564 | free(evsel->group_name); |
| 565 | if (evsel->tp_format && evsel->name == evsel->tp_format->name) { | ||
| 566 | evsel->name = NULL; | ||
| 567 | pevent_free_format(evsel->tp_format); | ||
| 568 | } | ||
| 498 | free(evsel->name); | 569 | free(evsel->name); |
| 499 | free(evsel); | 570 | free(evsel); |
| 500 | } | 571 | } |
| @@ -1002,14 +1073,19 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
| 1002 | return 0; | 1073 | return 0; |
| 1003 | } | 1074 | } |
| 1004 | 1075 | ||
| 1076 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) | ||
| 1077 | { | ||
| 1078 | return pevent_find_field(evsel->tp_format, name); | ||
| 1079 | } | ||
| 1080 | |||
| 1005 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | 1081 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, |
| 1006 | const char *name) | 1082 | const char *name) |
| 1007 | { | 1083 | { |
| 1008 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1084 | struct format_field *field = perf_evsel__field(evsel, name); |
| 1009 | int offset; | 1085 | int offset; |
| 1010 | 1086 | ||
| 1011 | if (!field) | 1087 | if (!field) |
| 1012 | return NULL; | 1088 | return NULL; |
| 1013 | 1089 | ||
| 1014 | offset = field->offset; | 1090 | offset = field->offset; |
| 1015 | 1091 | ||
| @@ -1024,11 +1100,11 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 1024 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 1100 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
| 1025 | const char *name) | 1101 | const char *name) |
| 1026 | { | 1102 | { |
| 1027 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1103 | struct format_field *field = perf_evsel__field(evsel, name); |
| 1028 | u64 val; | 1104 | u64 val; |
| 1029 | 1105 | ||
| 1030 | if (!field) | 1106 | if (!field) |
| 1031 | return 0; | 1107 | return 0; |
| 1032 | 1108 | ||
| 1033 | val = pevent_read_number(evsel->tp_format->pevent, | 1109 | val = pevent_read_number(evsel->tp_format->pevent, |
| 1034 | sample->raw_data + field->offset, field->size); | 1110 | sample->raw_data + field->offset, field->size); |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 93876bad2e52..bb445d1cbc7b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -81,6 +81,7 @@ struct perf_evlist; | |||
| 81 | struct perf_record_opts; | 81 | struct perf_record_opts; |
| 82 | 82 | ||
| 83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); | 83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); |
| 84 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); | ||
| 84 | void perf_evsel__init(struct perf_evsel *evsel, | 85 | void perf_evsel__init(struct perf_evsel *evsel, |
| 85 | struct perf_event_attr *attr, int idx); | 86 | struct perf_event_attr *attr, int idx); |
| 86 | void perf_evsel__exit(struct perf_evsel *evsel); | 87 | void perf_evsel__exit(struct perf_evsel *evsel); |
| @@ -128,6 +129,10 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 128 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 129 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
| 129 | const char *name); | 130 | const char *name); |
| 130 | 131 | ||
| 132 | struct format_field; | ||
| 133 | |||
| 134 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); | ||
| 135 | |||
| 131 | #define perf_evsel__match(evsel, t, c) \ | 136 | #define perf_evsel__match(evsel, t, c) \ |
| 132 | (evsel->attr.type == PERF_TYPE_##t && \ | 137 | (evsel->attr.type == PERF_TYPE_##t && \ |
| 133 | evsel->attr.config == PERF_COUNT_##c) | 138 | evsel->attr.config == PERF_COUNT_##c) |
