Commit a3f698fe3082ff80a7f3b27c9b64b4b748c81f9d

Authored by Arnaldo Carvalho de Melo
1 parent cb0b29e086

perf evsel: Adopt parse_sample method from perf_event

Since we need evsel->{attr.{sample_{id_all,type}},sample_size},
reducing the number of parameters tools have to pass.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wdtmgak0ihgsmw1brb54a8h4@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 5 changed files with 11 additions and 15 deletions Inline Diff

tools/perf/util/event.h
1 #ifndef __PERF_RECORD_H 1 #ifndef __PERF_RECORD_H
2 #define __PERF_RECORD_H 2 #define __PERF_RECORD_H
3 3
4 #include <limits.h> 4 #include <limits.h>
5 #include <stdio.h> 5 #include <stdio.h>
6 6
7 #include "../perf.h" 7 #include "../perf.h"
8 #include "map.h" 8 #include "map.h"
9 9
10 /* 10 /*
11 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * 11 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
12 */ 12 */
13 struct ip_event { 13 struct ip_event {
14 struct perf_event_header header; 14 struct perf_event_header header;
15 u64 ip; 15 u64 ip;
16 u32 pid, tid; 16 u32 pid, tid;
17 unsigned char __more_data[]; 17 unsigned char __more_data[];
18 }; 18 };
19 19
20 struct mmap_event { 20 struct mmap_event {
21 struct perf_event_header header; 21 struct perf_event_header header;
22 u32 pid, tid; 22 u32 pid, tid;
23 u64 start; 23 u64 start;
24 u64 len; 24 u64 len;
25 u64 pgoff; 25 u64 pgoff;
26 char filename[PATH_MAX]; 26 char filename[PATH_MAX];
27 }; 27 };
28 28
29 struct comm_event { 29 struct comm_event {
30 struct perf_event_header header; 30 struct perf_event_header header;
31 u32 pid, tid; 31 u32 pid, tid;
32 char comm[16]; 32 char comm[16];
33 }; 33 };
34 34
35 struct fork_event { 35 struct fork_event {
36 struct perf_event_header header; 36 struct perf_event_header header;
37 u32 pid, ppid; 37 u32 pid, ppid;
38 u32 tid, ptid; 38 u32 tid, ptid;
39 u64 time; 39 u64 time;
40 }; 40 };
41 41
42 struct lost_event { 42 struct lost_event {
43 struct perf_event_header header; 43 struct perf_event_header header;
44 u64 id; 44 u64 id;
45 u64 lost; 45 u64 lost;
46 }; 46 };
47 47
48 /* 48 /*
49 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID 49 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
50 */ 50 */
51 struct read_event { 51 struct read_event {
52 struct perf_event_header header; 52 struct perf_event_header header;
53 u32 pid, tid; 53 u32 pid, tid;
54 u64 value; 54 u64 value;
55 u64 time_enabled; 55 u64 time_enabled;
56 u64 time_running; 56 u64 time_running;
57 u64 id; 57 u64 id;
58 }; 58 };
59 59
60 60
61 #define PERF_SAMPLE_MASK \ 61 #define PERF_SAMPLE_MASK \
62 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ 62 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
63 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ 63 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
64 PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ 64 PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
65 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) 65 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
66 66
67 struct sample_event { 67 struct sample_event {
68 struct perf_event_header header; 68 struct perf_event_header header;
69 u64 array[]; 69 u64 array[];
70 }; 70 };
71 71
72 struct perf_sample { 72 struct perf_sample {
73 u64 ip; 73 u64 ip;
74 u32 pid, tid; 74 u32 pid, tid;
75 u64 time; 75 u64 time;
76 u64 addr; 76 u64 addr;
77 u64 id; 77 u64 id;
78 u64 stream_id; 78 u64 stream_id;
79 u64 period; 79 u64 period;
80 u32 cpu; 80 u32 cpu;
81 u32 raw_size; 81 u32 raw_size;
82 void *raw_data; 82 void *raw_data;
83 struct ip_callchain *callchain; 83 struct ip_callchain *callchain;
84 struct branch_stack *branch_stack; 84 struct branch_stack *branch_stack;
85 }; 85 };
86 86
87 #define BUILD_ID_SIZE 20 87 #define BUILD_ID_SIZE 20
88 88
89 struct build_id_event { 89 struct build_id_event {
90 struct perf_event_header header; 90 struct perf_event_header header;
91 pid_t pid; 91 pid_t pid;
92 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; 92 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
93 char filename[]; 93 char filename[];
94 }; 94 };
95 95
96 enum perf_user_event_type { /* above any possible kernel type */ 96 enum perf_user_event_type { /* above any possible kernel type */
97 PERF_RECORD_USER_TYPE_START = 64, 97 PERF_RECORD_USER_TYPE_START = 64,
98 PERF_RECORD_HEADER_ATTR = 64, 98 PERF_RECORD_HEADER_ATTR = 64,
99 PERF_RECORD_HEADER_EVENT_TYPE = 65, 99 PERF_RECORD_HEADER_EVENT_TYPE = 65,
100 PERF_RECORD_HEADER_TRACING_DATA = 66, 100 PERF_RECORD_HEADER_TRACING_DATA = 66,
101 PERF_RECORD_HEADER_BUILD_ID = 67, 101 PERF_RECORD_HEADER_BUILD_ID = 67,
102 PERF_RECORD_FINISHED_ROUND = 68, 102 PERF_RECORD_FINISHED_ROUND = 68,
103 PERF_RECORD_HEADER_MAX 103 PERF_RECORD_HEADER_MAX
104 }; 104 };
105 105
106 struct attr_event { 106 struct attr_event {
107 struct perf_event_header header; 107 struct perf_event_header header;
108 struct perf_event_attr attr; 108 struct perf_event_attr attr;
109 u64 id[]; 109 u64 id[];
110 }; 110 };
111 111
112 #define MAX_EVENT_NAME 64 112 #define MAX_EVENT_NAME 64
113 113
114 struct perf_trace_event_type { 114 struct perf_trace_event_type {
115 u64 event_id; 115 u64 event_id;
116 char name[MAX_EVENT_NAME]; 116 char name[MAX_EVENT_NAME];
117 }; 117 };
118 118
119 struct event_type_event { 119 struct event_type_event {
120 struct perf_event_header header; 120 struct perf_event_header header;
121 struct perf_trace_event_type event_type; 121 struct perf_trace_event_type event_type;
122 }; 122 };
123 123
124 struct tracing_data_event { 124 struct tracing_data_event {
125 struct perf_event_header header; 125 struct perf_event_header header;
126 u32 size; 126 u32 size;
127 }; 127 };
128 128
129 union perf_event { 129 union perf_event {
130 struct perf_event_header header; 130 struct perf_event_header header;
131 struct ip_event ip; 131 struct ip_event ip;
132 struct mmap_event mmap; 132 struct mmap_event mmap;
133 struct comm_event comm; 133 struct comm_event comm;
134 struct fork_event fork; 134 struct fork_event fork;
135 struct lost_event lost; 135 struct lost_event lost;
136 struct read_event read; 136 struct read_event read;
137 struct sample_event sample; 137 struct sample_event sample;
138 struct attr_event attr; 138 struct attr_event attr;
139 struct event_type_event event_type; 139 struct event_type_event event_type;
140 struct tracing_data_event tracing_data; 140 struct tracing_data_event tracing_data;
141 struct build_id_event build_id; 141 struct build_id_event build_id;
142 }; 142 };
143 143
144 void perf_event__print_totals(void); 144 void perf_event__print_totals(void);
145 145
146 struct perf_tool; 146 struct perf_tool;
147 struct thread_map; 147 struct thread_map;
148 148
149 typedef int (*perf_event__handler_t)(struct perf_tool *tool, 149 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
150 union perf_event *event, 150 union perf_event *event,
151 struct perf_sample *sample, 151 struct perf_sample *sample,
152 struct machine *machine); 152 struct machine *machine);
153 153
154 int perf_event__synthesize_thread_map(struct perf_tool *tool, 154 int perf_event__synthesize_thread_map(struct perf_tool *tool,
155 struct thread_map *threads, 155 struct thread_map *threads,
156 perf_event__handler_t process, 156 perf_event__handler_t process,
157 struct machine *machine); 157 struct machine *machine);
158 int perf_event__synthesize_threads(struct perf_tool *tool, 158 int perf_event__synthesize_threads(struct perf_tool *tool,
159 perf_event__handler_t process, 159 perf_event__handler_t process,
160 struct machine *machine); 160 struct machine *machine);
161 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 161 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
162 perf_event__handler_t process, 162 perf_event__handler_t process,
163 struct machine *machine, 163 struct machine *machine,
164 const char *symbol_name); 164 const char *symbol_name);
165 165
166 int perf_event__synthesize_modules(struct perf_tool *tool, 166 int perf_event__synthesize_modules(struct perf_tool *tool,
167 perf_event__handler_t process, 167 perf_event__handler_t process,
168 struct machine *machine); 168 struct machine *machine);
169 169
170 int perf_event__process_comm(struct perf_tool *tool, 170 int perf_event__process_comm(struct perf_tool *tool,
171 union perf_event *event, 171 union perf_event *event,
172 struct perf_sample *sample, 172 struct perf_sample *sample,
173 struct machine *machine); 173 struct machine *machine);
174 int perf_event__process_lost(struct perf_tool *tool, 174 int perf_event__process_lost(struct perf_tool *tool,
175 union perf_event *event, 175 union perf_event *event,
176 struct perf_sample *sample, 176 struct perf_sample *sample,
177 struct machine *machine); 177 struct machine *machine);
178 int perf_event__process_mmap(struct perf_tool *tool, 178 int perf_event__process_mmap(struct perf_tool *tool,
179 union perf_event *event, 179 union perf_event *event,
180 struct perf_sample *sample, 180 struct perf_sample *sample,
181 struct machine *machine); 181 struct machine *machine);
182 int perf_event__process_task(struct perf_tool *tool, 182 int perf_event__process_task(struct perf_tool *tool,
183 union perf_event *event, 183 union perf_event *event,
184 struct perf_sample *sample, 184 struct perf_sample *sample,
185 struct machine *machine); 185 struct machine *machine);
186 int perf_event__process(struct perf_tool *tool, 186 int perf_event__process(struct perf_tool *tool,
187 union perf_event *event, 187 union perf_event *event,
188 struct perf_sample *sample, 188 struct perf_sample *sample,
189 struct machine *machine); 189 struct machine *machine);
190 190
191 struct addr_location; 191 struct addr_location;
192 int perf_event__preprocess_sample(const union perf_event *self, 192 int perf_event__preprocess_sample(const union perf_event *self,
193 struct machine *machine, 193 struct machine *machine,
194 struct addr_location *al, 194 struct addr_location *al,
195 struct perf_sample *sample, 195 struct perf_sample *sample,
196 symbol_filter_t filter); 196 symbol_filter_t filter);
197 197
198 const char *perf_event__name(unsigned int id); 198 const char *perf_event__name(unsigned int id);
199 199
200 int perf_event__parse_sample(const union perf_event *event, u64 type,
201 int sample_size, bool sample_id_all,
202 struct perf_sample *sample, bool swapped);
203 int perf_event__synthesize_sample(union perf_event *event, u64 type, 200 int perf_event__synthesize_sample(union perf_event *event, u64 type,
204 const struct perf_sample *sample, 201 const struct perf_sample *sample,
205 bool swapped); 202 bool swapped);
206 203
207 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); 204 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
208 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); 205 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
209 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); 206 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
210 size_t perf_event__fprintf(union perf_event *event, FILE *fp); 207 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
211 208
212 #endif /* __PERF_RECORD_H */ 209 #endif /* __PERF_RECORD_H */
213 210
tools/perf/util/evlist.c
1 /* 1 /*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 * 3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further 4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes. 5 * copyright notes.
6 * 6 *
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 #include "util.h" 9 #include "util.h"
10 #include "debugfs.h" 10 #include "debugfs.h"
11 #include <poll.h> 11 #include <poll.h>
12 #include "cpumap.h" 12 #include "cpumap.h"
13 #include "thread_map.h" 13 #include "thread_map.h"
14 #include "target.h" 14 #include "target.h"
15 #include "evlist.h" 15 #include "evlist.h"
16 #include "evsel.h" 16 #include "evsel.h"
17 #include <unistd.h> 17 #include <unistd.h>
18 18
19 #include "parse-events.h" 19 #include "parse-events.h"
20 20
21 #include <sys/mman.h> 21 #include <sys/mman.h>
22 22
23 #include <linux/bitops.h> 23 #include <linux/bitops.h>
24 #include <linux/hash.h> 24 #include <linux/hash.h>
25 25
26 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 26 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
27 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 27 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
28 28
29 void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 29 void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
30 struct thread_map *threads) 30 struct thread_map *threads)
31 { 31 {
32 int i; 32 int i;
33 33
34 for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) 34 for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
35 INIT_HLIST_HEAD(&evlist->heads[i]); 35 INIT_HLIST_HEAD(&evlist->heads[i]);
36 INIT_LIST_HEAD(&evlist->entries); 36 INIT_LIST_HEAD(&evlist->entries);
37 perf_evlist__set_maps(evlist, cpus, threads); 37 perf_evlist__set_maps(evlist, cpus, threads);
38 evlist->workload.pid = -1; 38 evlist->workload.pid = -1;
39 } 39 }
40 40
41 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 41 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
42 struct thread_map *threads) 42 struct thread_map *threads)
43 { 43 {
44 struct perf_evlist *evlist = zalloc(sizeof(*evlist)); 44 struct perf_evlist *evlist = zalloc(sizeof(*evlist));
45 45
46 if (evlist != NULL) 46 if (evlist != NULL)
47 perf_evlist__init(evlist, cpus, threads); 47 perf_evlist__init(evlist, cpus, threads);
48 48
49 return evlist; 49 return evlist;
50 } 50 }
51 51
52 void perf_evlist__config_attrs(struct perf_evlist *evlist, 52 void perf_evlist__config_attrs(struct perf_evlist *evlist,
53 struct perf_record_opts *opts) 53 struct perf_record_opts *opts)
54 { 54 {
55 struct perf_evsel *evsel, *first; 55 struct perf_evsel *evsel, *first;
56 56
57 if (evlist->cpus->map[0] < 0) 57 if (evlist->cpus->map[0] < 0)
58 opts->no_inherit = true; 58 opts->no_inherit = true;
59 59
60 first = list_entry(evlist->entries.next, struct perf_evsel, node); 60 first = list_entry(evlist->entries.next, struct perf_evsel, node);
61 61
62 list_for_each_entry(evsel, &evlist->entries, node) { 62 list_for_each_entry(evsel, &evlist->entries, node) {
63 perf_evsel__config(evsel, opts, first); 63 perf_evsel__config(evsel, opts, first);
64 64
65 if (evlist->nr_entries > 1) 65 if (evlist->nr_entries > 1)
66 evsel->attr.sample_type |= PERF_SAMPLE_ID; 66 evsel->attr.sample_type |= PERF_SAMPLE_ID;
67 } 67 }
68 } 68 }
69 69
70 static void perf_evlist__purge(struct perf_evlist *evlist) 70 static void perf_evlist__purge(struct perf_evlist *evlist)
71 { 71 {
72 struct perf_evsel *pos, *n; 72 struct perf_evsel *pos, *n;
73 73
74 list_for_each_entry_safe(pos, n, &evlist->entries, node) { 74 list_for_each_entry_safe(pos, n, &evlist->entries, node) {
75 list_del_init(&pos->node); 75 list_del_init(&pos->node);
76 perf_evsel__delete(pos); 76 perf_evsel__delete(pos);
77 } 77 }
78 78
79 evlist->nr_entries = 0; 79 evlist->nr_entries = 0;
80 } 80 }
81 81
82 void perf_evlist__exit(struct perf_evlist *evlist) 82 void perf_evlist__exit(struct perf_evlist *evlist)
83 { 83 {
84 free(evlist->mmap); 84 free(evlist->mmap);
85 free(evlist->pollfd); 85 free(evlist->pollfd);
86 evlist->mmap = NULL; 86 evlist->mmap = NULL;
87 evlist->pollfd = NULL; 87 evlist->pollfd = NULL;
88 } 88 }
89 89
90 void perf_evlist__delete(struct perf_evlist *evlist) 90 void perf_evlist__delete(struct perf_evlist *evlist)
91 { 91 {
92 perf_evlist__purge(evlist); 92 perf_evlist__purge(evlist);
93 perf_evlist__exit(evlist); 93 perf_evlist__exit(evlist);
94 free(evlist); 94 free(evlist);
95 } 95 }
96 96
97 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 97 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
98 { 98 {
99 list_add_tail(&entry->node, &evlist->entries); 99 list_add_tail(&entry->node, &evlist->entries);
100 ++evlist->nr_entries; 100 ++evlist->nr_entries;
101 } 101 }
102 102
103 void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 103 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
104 struct list_head *list, 104 struct list_head *list,
105 int nr_entries) 105 int nr_entries)
106 { 106 {
107 list_splice_tail(list, &evlist->entries); 107 list_splice_tail(list, &evlist->entries);
108 evlist->nr_entries += nr_entries; 108 evlist->nr_entries += nr_entries;
109 } 109 }
110 110
111 int perf_evlist__add_default(struct perf_evlist *evlist) 111 int perf_evlist__add_default(struct perf_evlist *evlist)
112 { 112 {
113 struct perf_event_attr attr = { 113 struct perf_event_attr attr = {
114 .type = PERF_TYPE_HARDWARE, 114 .type = PERF_TYPE_HARDWARE,
115 .config = PERF_COUNT_HW_CPU_CYCLES, 115 .config = PERF_COUNT_HW_CPU_CYCLES,
116 }; 116 };
117 struct perf_evsel *evsel; 117 struct perf_evsel *evsel;
118 118
119 event_attr_init(&attr); 119 event_attr_init(&attr);
120 120
121 evsel = perf_evsel__new(&attr, 0); 121 evsel = perf_evsel__new(&attr, 0);
122 if (evsel == NULL) 122 if (evsel == NULL)
123 goto error; 123 goto error;
124 124
125 /* use strdup() because free(evsel) assumes name is allocated */ 125 /* use strdup() because free(evsel) assumes name is allocated */
126 evsel->name = strdup("cycles"); 126 evsel->name = strdup("cycles");
127 if (!evsel->name) 127 if (!evsel->name)
128 goto error_free; 128 goto error_free;
129 129
130 perf_evlist__add(evlist, evsel); 130 perf_evlist__add(evlist, evsel);
131 return 0; 131 return 0;
132 error_free: 132 error_free:
133 perf_evsel__delete(evsel); 133 perf_evsel__delete(evsel);
134 error: 134 error:
135 return -ENOMEM; 135 return -ENOMEM;
136 } 136 }
137 137
138 int perf_evlist__add_attrs(struct perf_evlist *evlist, 138 int perf_evlist__add_attrs(struct perf_evlist *evlist,
139 struct perf_event_attr *attrs, size_t nr_attrs) 139 struct perf_event_attr *attrs, size_t nr_attrs)
140 { 140 {
141 struct perf_evsel *evsel, *n; 141 struct perf_evsel *evsel, *n;
142 LIST_HEAD(head); 142 LIST_HEAD(head);
143 size_t i; 143 size_t i;
144 144
145 for (i = 0; i < nr_attrs; i++) { 145 for (i = 0; i < nr_attrs; i++) {
146 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i); 146 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
147 if (evsel == NULL) 147 if (evsel == NULL)
148 goto out_delete_partial_list; 148 goto out_delete_partial_list;
149 list_add_tail(&evsel->node, &head); 149 list_add_tail(&evsel->node, &head);
150 } 150 }
151 151
152 perf_evlist__splice_list_tail(evlist, &head, nr_attrs); 152 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
153 153
154 return 0; 154 return 0;
155 155
156 out_delete_partial_list: 156 out_delete_partial_list:
157 list_for_each_entry_safe(evsel, n, &head, node) 157 list_for_each_entry_safe(evsel, n, &head, node)
158 perf_evsel__delete(evsel); 158 perf_evsel__delete(evsel);
159 return -1; 159 return -1;
160 } 160 }
161 161
162 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 162 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
163 struct perf_event_attr *attrs, size_t nr_attrs) 163 struct perf_event_attr *attrs, size_t nr_attrs)
164 { 164 {
165 size_t i; 165 size_t i;
166 166
167 for (i = 0; i < nr_attrs; i++) 167 for (i = 0; i < nr_attrs; i++)
168 event_attr_init(attrs + i); 168 event_attr_init(attrs + i);
169 169
170 return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 170 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
171 } 171 }
172 172
173 static int trace_event__id(const char *evname) 173 static int trace_event__id(const char *evname)
174 { 174 {
175 char *filename, *colon; 175 char *filename, *colon;
176 int err = -1, fd; 176 int err = -1, fd;
177 177
178 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0) 178 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
179 return -1; 179 return -1;
180 180
181 colon = strrchr(filename, ':'); 181 colon = strrchr(filename, ':');
182 if (colon != NULL) 182 if (colon != NULL)
183 *colon = '/'; 183 *colon = '/';
184 184
185 fd = open(filename, O_RDONLY); 185 fd = open(filename, O_RDONLY);
186 if (fd >= 0) { 186 if (fd >= 0) {
187 char id[16]; 187 char id[16];
188 if (read(fd, id, sizeof(id)) > 0) 188 if (read(fd, id, sizeof(id)) > 0)
189 err = atoi(id); 189 err = atoi(id);
190 close(fd); 190 close(fd);
191 } 191 }
192 192
193 free(filename); 193 free(filename);
194 return err; 194 return err;
195 } 195 }
196 196
197 int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 197 int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
198 const char *tracepoints[], 198 const char *tracepoints[],
199 size_t nr_tracepoints) 199 size_t nr_tracepoints)
200 { 200 {
201 int err; 201 int err;
202 size_t i; 202 size_t i;
203 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs)); 203 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
204 204
205 if (attrs == NULL) 205 if (attrs == NULL)
206 return -1; 206 return -1;
207 207
208 for (i = 0; i < nr_tracepoints; i++) { 208 for (i = 0; i < nr_tracepoints; i++) {
209 err = trace_event__id(tracepoints[i]); 209 err = trace_event__id(tracepoints[i]);
210 210
211 if (err < 0) 211 if (err < 0)
212 goto out_free_attrs; 212 goto out_free_attrs;
213 213
214 attrs[i].type = PERF_TYPE_TRACEPOINT; 214 attrs[i].type = PERF_TYPE_TRACEPOINT;
215 attrs[i].config = err; 215 attrs[i].config = err;
216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD); 217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
218 attrs[i].sample_period = 1; 218 attrs[i].sample_period = 1;
219 } 219 }
220 220
221 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints); 221 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
222 out_free_attrs: 222 out_free_attrs:
223 free(attrs); 223 free(attrs);
224 return err; 224 return err;
225 } 225 }
226 226
227 struct perf_evsel * 227 struct perf_evsel *
228 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 228 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
229 { 229 {
230 struct perf_evsel *evsel; 230 struct perf_evsel *evsel;
231 231
232 list_for_each_entry(evsel, &evlist->entries, node) { 232 list_for_each_entry(evsel, &evlist->entries, node) {
233 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 233 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
234 (int)evsel->attr.config == id) 234 (int)evsel->attr.config == id)
235 return evsel; 235 return evsel;
236 } 236 }
237 237
238 return NULL; 238 return NULL;
239 } 239 }
240 240
241 int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 241 int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
242 const struct perf_evsel_str_handler *assocs, 242 const struct perf_evsel_str_handler *assocs,
243 size_t nr_assocs) 243 size_t nr_assocs)
244 { 244 {
245 struct perf_evsel *evsel; 245 struct perf_evsel *evsel;
246 int err; 246 int err;
247 size_t i; 247 size_t i;
248 248
249 for (i = 0; i < nr_assocs; i++) { 249 for (i = 0; i < nr_assocs; i++) {
250 err = trace_event__id(assocs[i].name); 250 err = trace_event__id(assocs[i].name);
251 if (err < 0) 251 if (err < 0)
252 goto out; 252 goto out;
253 253
254 evsel = perf_evlist__find_tracepoint_by_id(evlist, err); 254 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
255 if (evsel == NULL) 255 if (evsel == NULL)
256 continue; 256 continue;
257 257
258 err = -EEXIST; 258 err = -EEXIST;
259 if (evsel->handler.func != NULL) 259 if (evsel->handler.func != NULL)
260 goto out; 260 goto out;
261 evsel->handler.func = assocs[i].handler; 261 evsel->handler.func = assocs[i].handler;
262 } 262 }
263 263
264 err = 0; 264 err = 0;
265 out: 265 out:
266 return err; 266 return err;
267 } 267 }
268 268
269 void perf_evlist__disable(struct perf_evlist *evlist) 269 void perf_evlist__disable(struct perf_evlist *evlist)
270 { 270 {
271 int cpu, thread; 271 int cpu, thread;
272 struct perf_evsel *pos; 272 struct perf_evsel *pos;
273 273
274 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 274 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
275 list_for_each_entry(pos, &evlist->entries, node) { 275 list_for_each_entry(pos, &evlist->entries, node) {
276 for (thread = 0; thread < evlist->threads->nr; thread++) 276 for (thread = 0; thread < evlist->threads->nr; thread++)
277 ioctl(FD(pos, cpu, thread), 277 ioctl(FD(pos, cpu, thread),
278 PERF_EVENT_IOC_DISABLE, 0); 278 PERF_EVENT_IOC_DISABLE, 0);
279 } 279 }
280 } 280 }
281 } 281 }
282 282
283 void perf_evlist__enable(struct perf_evlist *evlist) 283 void perf_evlist__enable(struct perf_evlist *evlist)
284 { 284 {
285 int cpu, thread; 285 int cpu, thread;
286 struct perf_evsel *pos; 286 struct perf_evsel *pos;
287 287
288 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 288 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
289 list_for_each_entry(pos, &evlist->entries, node) { 289 list_for_each_entry(pos, &evlist->entries, node) {
290 for (thread = 0; thread < evlist->threads->nr; thread++) 290 for (thread = 0; thread < evlist->threads->nr; thread++)
291 ioctl(FD(pos, cpu, thread), 291 ioctl(FD(pos, cpu, thread),
292 PERF_EVENT_IOC_ENABLE, 0); 292 PERF_EVENT_IOC_ENABLE, 0);
293 } 293 }
294 } 294 }
295 } 295 }
296 296
297 static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 297 static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
298 { 298 {
299 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 299 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
300 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 300 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
301 return evlist->pollfd != NULL ? 0 : -ENOMEM; 301 return evlist->pollfd != NULL ? 0 : -ENOMEM;
302 } 302 }
303 303
304 void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 304 void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
305 { 305 {
306 fcntl(fd, F_SETFL, O_NONBLOCK); 306 fcntl(fd, F_SETFL, O_NONBLOCK);
307 evlist->pollfd[evlist->nr_fds].fd = fd; 307 evlist->pollfd[evlist->nr_fds].fd = fd;
308 evlist->pollfd[evlist->nr_fds].events = POLLIN; 308 evlist->pollfd[evlist->nr_fds].events = POLLIN;
309 evlist->nr_fds++; 309 evlist->nr_fds++;
310 } 310 }
311 311
312 static void perf_evlist__id_hash(struct perf_evlist *evlist, 312 static void perf_evlist__id_hash(struct perf_evlist *evlist,
313 struct perf_evsel *evsel, 313 struct perf_evsel *evsel,
314 int cpu, int thread, u64 id) 314 int cpu, int thread, u64 id)
315 { 315 {
316 int hash; 316 int hash;
317 struct perf_sample_id *sid = SID(evsel, cpu, thread); 317 struct perf_sample_id *sid = SID(evsel, cpu, thread);
318 318
319 sid->id = id; 319 sid->id = id;
320 sid->evsel = evsel; 320 sid->evsel = evsel;
321 hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); 321 hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
322 hlist_add_head(&sid->node, &evlist->heads[hash]); 322 hlist_add_head(&sid->node, &evlist->heads[hash]);
323 } 323 }
324 324
325 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 325 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
326 int cpu, int thread, u64 id) 326 int cpu, int thread, u64 id)
327 { 327 {
328 perf_evlist__id_hash(evlist, evsel, cpu, thread, id); 328 perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
329 evsel->id[evsel->ids++] = id; 329 evsel->id[evsel->ids++] = id;
330 } 330 }
331 331
332 static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 332 static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
333 struct perf_evsel *evsel, 333 struct perf_evsel *evsel,
334 int cpu, int thread, int fd) 334 int cpu, int thread, int fd)
335 { 335 {
336 u64 read_data[4] = { 0, }; 336 u64 read_data[4] = { 0, };
337 int id_idx = 1; /* The first entry is the counter value */ 337 int id_idx = 1; /* The first entry is the counter value */
338 338
339 if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 339 if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
340 read(fd, &read_data, sizeof(read_data)) == -1) 340 read(fd, &read_data, sizeof(read_data)) == -1)
341 return -1; 341 return -1;
342 342
343 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 343 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
344 ++id_idx; 344 ++id_idx;
345 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 345 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
346 ++id_idx; 346 ++id_idx;
347 347
348 perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]); 348 perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]);
349 return 0; 349 return 0;
350 } 350 }
351 351
352 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 352 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
353 { 353 {
354 struct hlist_head *head; 354 struct hlist_head *head;
355 struct hlist_node *pos; 355 struct hlist_node *pos;
356 struct perf_sample_id *sid; 356 struct perf_sample_id *sid;
357 int hash; 357 int hash;
358 358
359 if (evlist->nr_entries == 1) 359 if (evlist->nr_entries == 1)
360 return list_entry(evlist->entries.next, struct perf_evsel, node); 360 return list_entry(evlist->entries.next, struct perf_evsel, node);
361 361
362 hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 362 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
363 head = &evlist->heads[hash]; 363 head = &evlist->heads[hash];
364 364
365 hlist_for_each_entry(sid, pos, head, node) 365 hlist_for_each_entry(sid, pos, head, node)
366 if (sid->id == id) 366 if (sid->id == id)
367 return sid->evsel; 367 return sid->evsel;
368 368
369 if (!perf_evlist__sample_id_all(evlist)) 369 if (!perf_evlist__sample_id_all(evlist))
370 return list_entry(evlist->entries.next, struct perf_evsel, node); 370 return list_entry(evlist->entries.next, struct perf_evsel, node);
371 371
372 return NULL; 372 return NULL;
373 } 373 }
374 374
375 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 375 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
376 { 376 {
377 /* XXX Move this to perf.c, making it generally available */ 377 /* XXX Move this to perf.c, making it generally available */
378 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 378 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
379 struct perf_mmap *md = &evlist->mmap[idx]; 379 struct perf_mmap *md = &evlist->mmap[idx];
380 unsigned int head = perf_mmap__read_head(md); 380 unsigned int head = perf_mmap__read_head(md);
381 unsigned int old = md->prev; 381 unsigned int old = md->prev;
382 unsigned char *data = md->base + page_size; 382 unsigned char *data = md->base + page_size;
383 union perf_event *event = NULL; 383 union perf_event *event = NULL;
384 384
385 if (evlist->overwrite) { 385 if (evlist->overwrite) {
386 /* 386 /*
387 * If we're further behind than half the buffer, there's a chance 387 * If we're further behind than half the buffer, there's a chance
388 * the writer will bite our tail and mess up the samples under us. 388 * the writer will bite our tail and mess up the samples under us.
389 * 389 *
390 * If we somehow ended up ahead of the head, we got messed up. 390 * If we somehow ended up ahead of the head, we got messed up.
391 * 391 *
392 * In either case, truncate and restart at head. 392 * In either case, truncate and restart at head.
393 */ 393 */
394 int diff = head - old; 394 int diff = head - old;
395 if (diff > md->mask / 2 || diff < 0) { 395 if (diff > md->mask / 2 || diff < 0) {
396 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 396 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
397 397
398 /* 398 /*
399 * head points to a known good entry, start there. 399 * head points to a known good entry, start there.
400 */ 400 */
401 old = head; 401 old = head;
402 } 402 }
403 } 403 }
404 404
405 if (old != head) { 405 if (old != head) {
406 size_t size; 406 size_t size;
407 407
408 event = (union perf_event *)&data[old & md->mask]; 408 event = (union perf_event *)&data[old & md->mask];
409 size = event->header.size; 409 size = event->header.size;
410 410
411 /* 411 /*
412 * Event straddles the mmap boundary -- header should always 412 * Event straddles the mmap boundary -- header should always
413 * be inside due to u64 alignment of output. 413 * be inside due to u64 alignment of output.
414 */ 414 */
415 if ((old & md->mask) + size != ((old + size) & md->mask)) { 415 if ((old & md->mask) + size != ((old + size) & md->mask)) {
416 unsigned int offset = old; 416 unsigned int offset = old;
417 unsigned int len = min(sizeof(*event), size), cpy; 417 unsigned int len = min(sizeof(*event), size), cpy;
418 void *dst = &evlist->event_copy; 418 void *dst = &evlist->event_copy;
419 419
420 do { 420 do {
421 cpy = min(md->mask + 1 - (offset & md->mask), len); 421 cpy = min(md->mask + 1 - (offset & md->mask), len);
422 memcpy(dst, &data[offset & md->mask], cpy); 422 memcpy(dst, &data[offset & md->mask], cpy);
423 offset += cpy; 423 offset += cpy;
424 dst += cpy; 424 dst += cpy;
425 len -= cpy; 425 len -= cpy;
426 } while (len); 426 } while (len);
427 427
428 event = &evlist->event_copy; 428 event = &evlist->event_copy;
429 } 429 }
430 430
431 old += size; 431 old += size;
432 } 432 }
433 433
434 md->prev = old; 434 md->prev = old;
435 435
436 if (!evlist->overwrite) 436 if (!evlist->overwrite)
437 perf_mmap__write_tail(md, old); 437 perf_mmap__write_tail(md, old);
438 438
439 return event; 439 return event;
440 } 440 }
441 441
442 void perf_evlist__munmap(struct perf_evlist *evlist) 442 void perf_evlist__munmap(struct perf_evlist *evlist)
443 { 443 {
444 int i; 444 int i;
445 445
446 for (i = 0; i < evlist->nr_mmaps; i++) { 446 for (i = 0; i < evlist->nr_mmaps; i++) {
447 if (evlist->mmap[i].base != NULL) { 447 if (evlist->mmap[i].base != NULL) {
448 munmap(evlist->mmap[i].base, evlist->mmap_len); 448 munmap(evlist->mmap[i].base, evlist->mmap_len);
449 evlist->mmap[i].base = NULL; 449 evlist->mmap[i].base = NULL;
450 } 450 }
451 } 451 }
452 452
453 free(evlist->mmap); 453 free(evlist->mmap);
454 evlist->mmap = NULL; 454 evlist->mmap = NULL;
455 } 455 }
456 456
457 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 457 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
458 { 458 {
459 evlist->nr_mmaps = evlist->cpus->nr; 459 evlist->nr_mmaps = evlist->cpus->nr;
460 if (evlist->cpus->map[0] == -1) 460 if (evlist->cpus->map[0] == -1)
461 evlist->nr_mmaps = evlist->threads->nr; 461 evlist->nr_mmaps = evlist->threads->nr;
462 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 462 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
463 return evlist->mmap != NULL ? 0 : -ENOMEM; 463 return evlist->mmap != NULL ? 0 : -ENOMEM;
464 } 464 }
465 465
466 static int __perf_evlist__mmap(struct perf_evlist *evlist, 466 static int __perf_evlist__mmap(struct perf_evlist *evlist,
467 int idx, int prot, int mask, int fd) 467 int idx, int prot, int mask, int fd)
468 { 468 {
469 evlist->mmap[idx].prev = 0; 469 evlist->mmap[idx].prev = 0;
470 evlist->mmap[idx].mask = mask; 470 evlist->mmap[idx].mask = mask;
471 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 471 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
472 MAP_SHARED, fd, 0); 472 MAP_SHARED, fd, 0);
473 if (evlist->mmap[idx].base == MAP_FAILED) { 473 if (evlist->mmap[idx].base == MAP_FAILED) {
474 evlist->mmap[idx].base = NULL; 474 evlist->mmap[idx].base = NULL;
475 return -1; 475 return -1;
476 } 476 }
477 477
478 perf_evlist__add_pollfd(evlist, fd); 478 perf_evlist__add_pollfd(evlist, fd);
479 return 0; 479 return 0;
480 } 480 }
481 481
482 static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) 482 static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask)
483 { 483 {
484 struct perf_evsel *evsel; 484 struct perf_evsel *evsel;
485 int cpu, thread; 485 int cpu, thread;
486 486
487 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 487 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
488 int output = -1; 488 int output = -1;
489 489
490 for (thread = 0; thread < evlist->threads->nr; thread++) { 490 for (thread = 0; thread < evlist->threads->nr; thread++) {
491 list_for_each_entry(evsel, &evlist->entries, node) { 491 list_for_each_entry(evsel, &evlist->entries, node) {
492 int fd = FD(evsel, cpu, thread); 492 int fd = FD(evsel, cpu, thread);
493 493
494 if (output == -1) { 494 if (output == -1) {
495 output = fd; 495 output = fd;
496 if (__perf_evlist__mmap(evlist, cpu, 496 if (__perf_evlist__mmap(evlist, cpu,
497 prot, mask, output) < 0) 497 prot, mask, output) < 0)
498 goto out_unmap; 498 goto out_unmap;
499 } else { 499 } else {
500 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) 500 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
501 goto out_unmap; 501 goto out_unmap;
502 } 502 }
503 503
504 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 504 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
505 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 505 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
506 goto out_unmap; 506 goto out_unmap;
507 } 507 }
508 } 508 }
509 } 509 }
510 510
511 return 0; 511 return 0;
512 512
513 out_unmap: 513 out_unmap:
514 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 514 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
515 if (evlist->mmap[cpu].base != NULL) { 515 if (evlist->mmap[cpu].base != NULL) {
516 munmap(evlist->mmap[cpu].base, evlist->mmap_len); 516 munmap(evlist->mmap[cpu].base, evlist->mmap_len);
517 evlist->mmap[cpu].base = NULL; 517 evlist->mmap[cpu].base = NULL;
518 } 518 }
519 } 519 }
520 return -1; 520 return -1;
521 } 521 }
522 522
523 static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) 523 static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask)
524 { 524 {
525 struct perf_evsel *evsel; 525 struct perf_evsel *evsel;
526 int thread; 526 int thread;
527 527
528 for (thread = 0; thread < evlist->threads->nr; thread++) { 528 for (thread = 0; thread < evlist->threads->nr; thread++) {
529 int output = -1; 529 int output = -1;
530 530
531 list_for_each_entry(evsel, &evlist->entries, node) { 531 list_for_each_entry(evsel, &evlist->entries, node) {
532 int fd = FD(evsel, 0, thread); 532 int fd = FD(evsel, 0, thread);
533 533
534 if (output == -1) { 534 if (output == -1) {
535 output = fd; 535 output = fd;
536 if (__perf_evlist__mmap(evlist, thread, 536 if (__perf_evlist__mmap(evlist, thread,
537 prot, mask, output) < 0) 537 prot, mask, output) < 0)
538 goto out_unmap; 538 goto out_unmap;
539 } else { 539 } else {
540 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) 540 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
541 goto out_unmap; 541 goto out_unmap;
542 } 542 }
543 543
544 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 544 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
545 perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0) 545 perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
546 goto out_unmap; 546 goto out_unmap;
547 } 547 }
548 } 548 }
549 549
550 return 0; 550 return 0;
551 551
552 out_unmap: 552 out_unmap:
553 for (thread = 0; thread < evlist->threads->nr; thread++) { 553 for (thread = 0; thread < evlist->threads->nr; thread++) {
554 if (evlist->mmap[thread].base != NULL) { 554 if (evlist->mmap[thread].base != NULL) {
555 munmap(evlist->mmap[thread].base, evlist->mmap_len); 555 munmap(evlist->mmap[thread].base, evlist->mmap_len);
556 evlist->mmap[thread].base = NULL; 556 evlist->mmap[thread].base = NULL;
557 } 557 }
558 } 558 }
559 return -1; 559 return -1;
560 } 560 }
561 561
562 /** perf_evlist__mmap - Create per cpu maps to receive events 562 /** perf_evlist__mmap - Create per cpu maps to receive events
563 * 563 *
564 * @evlist - list of events 564 * @evlist - list of events
565 * @pages - map length in pages 565 * @pages - map length in pages
566 * @overwrite - overwrite older events? 566 * @overwrite - overwrite older events?
567 * 567 *
568 * If overwrite is false the user needs to signal event consuption using: 568 * If overwrite is false the user needs to signal event consuption using:
569 * 569 *
570 * struct perf_mmap *m = &evlist->mmap[cpu]; 570 * struct perf_mmap *m = &evlist->mmap[cpu];
571 * unsigned int head = perf_mmap__read_head(m); 571 * unsigned int head = perf_mmap__read_head(m);
572 * 572 *
573 * perf_mmap__write_tail(m, head) 573 * perf_mmap__write_tail(m, head)
574 * 574 *
575 * Using perf_evlist__read_on_cpu does this automatically. 575 * Using perf_evlist__read_on_cpu does this automatically.
576 */ 576 */
577 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 577 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
578 bool overwrite) 578 bool overwrite)
579 { 579 {
580 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 580 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
581 struct perf_evsel *evsel; 581 struct perf_evsel *evsel;
582 const struct cpu_map *cpus = evlist->cpus; 582 const struct cpu_map *cpus = evlist->cpus;
583 const struct thread_map *threads = evlist->threads; 583 const struct thread_map *threads = evlist->threads;
584 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 584 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
585 585
586 /* 512 kiB: default amount of unprivileged mlocked memory */ 586 /* 512 kiB: default amount of unprivileged mlocked memory */
587 if (pages == UINT_MAX) 587 if (pages == UINT_MAX)
588 pages = (512 * 1024) / page_size; 588 pages = (512 * 1024) / page_size;
589 else if (!is_power_of_2(pages)) 589 else if (!is_power_of_2(pages))
590 return -EINVAL; 590 return -EINVAL;
591 591
592 mask = pages * page_size - 1; 592 mask = pages * page_size - 1;
593 593
594 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 594 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
595 return -ENOMEM; 595 return -ENOMEM;
596 596
597 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 597 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
598 return -ENOMEM; 598 return -ENOMEM;
599 599
600 evlist->overwrite = overwrite; 600 evlist->overwrite = overwrite;
601 evlist->mmap_len = (pages + 1) * page_size; 601 evlist->mmap_len = (pages + 1) * page_size;
602 602
603 list_for_each_entry(evsel, &evlist->entries, node) { 603 list_for_each_entry(evsel, &evlist->entries, node) {
604 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 604 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
605 evsel->sample_id == NULL && 605 evsel->sample_id == NULL &&
606 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) 606 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)
607 return -ENOMEM; 607 return -ENOMEM;
608 } 608 }
609 609
610 if (evlist->cpus->map[0] == -1) 610 if (evlist->cpus->map[0] == -1)
611 return perf_evlist__mmap_per_thread(evlist, prot, mask); 611 return perf_evlist__mmap_per_thread(evlist, prot, mask);
612 612
613 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 613 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
614 } 614 }
615 615
616 int perf_evlist__create_maps(struct perf_evlist *evlist, 616 int perf_evlist__create_maps(struct perf_evlist *evlist,
617 struct perf_target *target) 617 struct perf_target *target)
618 { 618 {
619 evlist->threads = thread_map__new_str(target->pid, target->tid, 619 evlist->threads = thread_map__new_str(target->pid, target->tid,
620 target->uid); 620 target->uid);
621 621
622 if (evlist->threads == NULL) 622 if (evlist->threads == NULL)
623 return -1; 623 return -1;
624 624
625 if (perf_target__has_task(target)) 625 if (perf_target__has_task(target))
626 evlist->cpus = cpu_map__dummy_new(); 626 evlist->cpus = cpu_map__dummy_new();
627 else if (!perf_target__has_cpu(target) && !target->uses_mmap) 627 else if (!perf_target__has_cpu(target) && !target->uses_mmap)
628 evlist->cpus = cpu_map__dummy_new(); 628 evlist->cpus = cpu_map__dummy_new();
629 else 629 else
630 evlist->cpus = cpu_map__new(target->cpu_list); 630 evlist->cpus = cpu_map__new(target->cpu_list);
631 631
632 if (evlist->cpus == NULL) 632 if (evlist->cpus == NULL)
633 goto out_delete_threads; 633 goto out_delete_threads;
634 634
635 return 0; 635 return 0;
636 636
637 out_delete_threads: 637 out_delete_threads:
638 thread_map__delete(evlist->threads); 638 thread_map__delete(evlist->threads);
639 return -1; 639 return -1;
640 } 640 }
641 641
642 void perf_evlist__delete_maps(struct perf_evlist *evlist) 642 void perf_evlist__delete_maps(struct perf_evlist *evlist)
643 { 643 {
644 cpu_map__delete(evlist->cpus); 644 cpu_map__delete(evlist->cpus);
645 thread_map__delete(evlist->threads); 645 thread_map__delete(evlist->threads);
646 evlist->cpus = NULL; 646 evlist->cpus = NULL;
647 evlist->threads = NULL; 647 evlist->threads = NULL;
648 } 648 }
649 649
650 int perf_evlist__set_filters(struct perf_evlist *evlist) 650 int perf_evlist__set_filters(struct perf_evlist *evlist)
651 { 651 {
652 const struct thread_map *threads = evlist->threads; 652 const struct thread_map *threads = evlist->threads;
653 const struct cpu_map *cpus = evlist->cpus; 653 const struct cpu_map *cpus = evlist->cpus;
654 struct perf_evsel *evsel; 654 struct perf_evsel *evsel;
655 char *filter; 655 char *filter;
656 int thread; 656 int thread;
657 int cpu; 657 int cpu;
658 int err; 658 int err;
659 int fd; 659 int fd;
660 660
661 list_for_each_entry(evsel, &evlist->entries, node) { 661 list_for_each_entry(evsel, &evlist->entries, node) {
662 filter = evsel->filter; 662 filter = evsel->filter;
663 if (!filter) 663 if (!filter)
664 continue; 664 continue;
665 for (cpu = 0; cpu < cpus->nr; cpu++) { 665 for (cpu = 0; cpu < cpus->nr; cpu++) {
666 for (thread = 0; thread < threads->nr; thread++) { 666 for (thread = 0; thread < threads->nr; thread++) {
667 fd = FD(evsel, cpu, thread); 667 fd = FD(evsel, cpu, thread);
668 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); 668 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
669 if (err) 669 if (err)
670 return err; 670 return err;
671 } 671 }
672 } 672 }
673 } 673 }
674 674
675 return 0; 675 return 0;
676 } 676 }
677 677
678 bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) 678 bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
679 { 679 {
680 struct perf_evsel *pos, *first; 680 struct perf_evsel *pos, *first;
681 681
682 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); 682 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
683 683
684 list_for_each_entry_continue(pos, &evlist->entries, node) { 684 list_for_each_entry_continue(pos, &evlist->entries, node) {
685 if (first->attr.sample_type != pos->attr.sample_type) 685 if (first->attr.sample_type != pos->attr.sample_type)
686 return false; 686 return false;
687 } 687 }
688 688
689 return true; 689 return true;
690 } 690 }
691 691
692 u64 perf_evlist__sample_type(const struct perf_evlist *evlist) 692 u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
693 { 693 {
694 struct perf_evsel *first; 694 struct perf_evsel *first;
695 695
696 first = list_entry(evlist->entries.next, struct perf_evsel, node); 696 first = list_entry(evlist->entries.next, struct perf_evsel, node);
697 return first->attr.sample_type; 697 return first->attr.sample_type;
698 } 698 }
699 699
700 u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist) 700 u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
701 { 701 {
702 struct perf_evsel *first; 702 struct perf_evsel *first;
703 struct perf_sample *data; 703 struct perf_sample *data;
704 u64 sample_type; 704 u64 sample_type;
705 u16 size = 0; 705 u16 size = 0;
706 706
707 first = list_entry(evlist->entries.next, struct perf_evsel, node); 707 first = list_entry(evlist->entries.next, struct perf_evsel, node);
708 708
709 if (!first->attr.sample_id_all) 709 if (!first->attr.sample_id_all)
710 goto out; 710 goto out;
711 711
712 sample_type = first->attr.sample_type; 712 sample_type = first->attr.sample_type;
713 713
714 if (sample_type & PERF_SAMPLE_TID) 714 if (sample_type & PERF_SAMPLE_TID)
715 size += sizeof(data->tid) * 2; 715 size += sizeof(data->tid) * 2;
716 716
717 if (sample_type & PERF_SAMPLE_TIME) 717 if (sample_type & PERF_SAMPLE_TIME)
718 size += sizeof(data->time); 718 size += sizeof(data->time);
719 719
720 if (sample_type & PERF_SAMPLE_ID) 720 if (sample_type & PERF_SAMPLE_ID)
721 size += sizeof(data->id); 721 size += sizeof(data->id);
722 722
723 if (sample_type & PERF_SAMPLE_STREAM_ID) 723 if (sample_type & PERF_SAMPLE_STREAM_ID)
724 size += sizeof(data->stream_id); 724 size += sizeof(data->stream_id);
725 725
726 if (sample_type & PERF_SAMPLE_CPU) 726 if (sample_type & PERF_SAMPLE_CPU)
727 size += sizeof(data->cpu) * 2; 727 size += sizeof(data->cpu) * 2;
728 out: 728 out:
729 return size; 729 return size;
730 } 730 }
731 731
732 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 732 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
733 { 733 {
734 struct perf_evsel *pos, *first; 734 struct perf_evsel *pos, *first;
735 735
736 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); 736 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
737 737
738 list_for_each_entry_continue(pos, &evlist->entries, node) { 738 list_for_each_entry_continue(pos, &evlist->entries, node) {
739 if (first->attr.sample_id_all != pos->attr.sample_id_all) 739 if (first->attr.sample_id_all != pos->attr.sample_id_all)
740 return false; 740 return false;
741 } 741 }
742 742
743 return true; 743 return true;
744 } 744 }
745 745
746 bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) 746 bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
747 { 747 {
748 struct perf_evsel *first; 748 struct perf_evsel *first;
749 749
750 first = list_entry(evlist->entries.next, struct perf_evsel, node); 750 first = list_entry(evlist->entries.next, struct perf_evsel, node);
751 return first->attr.sample_id_all; 751 return first->attr.sample_id_all;
752 } 752 }
753 753
754 void perf_evlist__set_selected(struct perf_evlist *evlist, 754 void perf_evlist__set_selected(struct perf_evlist *evlist,
755 struct perf_evsel *evsel) 755 struct perf_evsel *evsel)
756 { 756 {
757 evlist->selected = evsel; 757 evlist->selected = evsel;
758 } 758 }
759 759
760 int perf_evlist__open(struct perf_evlist *evlist, bool group) 760 int perf_evlist__open(struct perf_evlist *evlist, bool group)
761 { 761 {
762 struct perf_evsel *evsel, *first; 762 struct perf_evsel *evsel, *first;
763 int err, ncpus, nthreads; 763 int err, ncpus, nthreads;
764 764
765 first = list_entry(evlist->entries.next, struct perf_evsel, node); 765 first = list_entry(evlist->entries.next, struct perf_evsel, node);
766 766
767 list_for_each_entry(evsel, &evlist->entries, node) { 767 list_for_each_entry(evsel, &evlist->entries, node) {
768 struct xyarray *group_fd = NULL; 768 struct xyarray *group_fd = NULL;
769 769
770 if (group && evsel != first) 770 if (group && evsel != first)
771 group_fd = first->fd; 771 group_fd = first->fd;
772 772
773 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads, 773 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
774 group, group_fd); 774 group, group_fd);
775 if (err < 0) 775 if (err < 0)
776 goto out_err; 776 goto out_err;
777 } 777 }
778 778
779 return 0; 779 return 0;
780 out_err: 780 out_err:
781 ncpus = evlist->cpus ? evlist->cpus->nr : 1; 781 ncpus = evlist->cpus ? evlist->cpus->nr : 1;
782 nthreads = evlist->threads ? evlist->threads->nr : 1; 782 nthreads = evlist->threads ? evlist->threads->nr : 1;
783 783
784 list_for_each_entry_reverse(evsel, &evlist->entries, node) 784 list_for_each_entry_reverse(evsel, &evlist->entries, node)
785 perf_evsel__close(evsel, ncpus, nthreads); 785 perf_evsel__close(evsel, ncpus, nthreads);
786 786
787 errno = -err; 787 errno = -err;
788 return err; 788 return err;
789 } 789 }
790 790
791 int perf_evlist__prepare_workload(struct perf_evlist *evlist, 791 int perf_evlist__prepare_workload(struct perf_evlist *evlist,
792 struct perf_record_opts *opts, 792 struct perf_record_opts *opts,
793 const char *argv[]) 793 const char *argv[])
794 { 794 {
795 int child_ready_pipe[2], go_pipe[2]; 795 int child_ready_pipe[2], go_pipe[2];
796 char bf; 796 char bf;
797 797
798 if (pipe(child_ready_pipe) < 0) { 798 if (pipe(child_ready_pipe) < 0) {
799 perror("failed to create 'ready' pipe"); 799 perror("failed to create 'ready' pipe");
800 return -1; 800 return -1;
801 } 801 }
802 802
803 if (pipe(go_pipe) < 0) { 803 if (pipe(go_pipe) < 0) {
804 perror("failed to create 'go' pipe"); 804 perror("failed to create 'go' pipe");
805 goto out_close_ready_pipe; 805 goto out_close_ready_pipe;
806 } 806 }
807 807
808 evlist->workload.pid = fork(); 808 evlist->workload.pid = fork();
809 if (evlist->workload.pid < 0) { 809 if (evlist->workload.pid < 0) {
810 perror("failed to fork"); 810 perror("failed to fork");
811 goto out_close_pipes; 811 goto out_close_pipes;
812 } 812 }
813 813
814 if (!evlist->workload.pid) { 814 if (!evlist->workload.pid) {
815 if (opts->pipe_output) 815 if (opts->pipe_output)
816 dup2(2, 1); 816 dup2(2, 1);
817 817
818 close(child_ready_pipe[0]); 818 close(child_ready_pipe[0]);
819 close(go_pipe[1]); 819 close(go_pipe[1]);
820 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 820 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
821 821
822 /* 822 /*
823 * Do a dummy execvp to get the PLT entry resolved, 823 * Do a dummy execvp to get the PLT entry resolved,
824 * so we avoid the resolver overhead on the real 824 * so we avoid the resolver overhead on the real
825 * execvp call. 825 * execvp call.
826 */ 826 */
827 execvp("", (char **)argv); 827 execvp("", (char **)argv);
828 828
829 /* 829 /*
830 * Tell the parent we're ready to go 830 * Tell the parent we're ready to go
831 */ 831 */
832 close(child_ready_pipe[1]); 832 close(child_ready_pipe[1]);
833 833
834 /* 834 /*
835 * Wait until the parent tells us to go. 835 * Wait until the parent tells us to go.
836 */ 836 */
837 if (read(go_pipe[0], &bf, 1) == -1) 837 if (read(go_pipe[0], &bf, 1) == -1)
838 perror("unable to read pipe"); 838 perror("unable to read pipe");
839 839
840 execvp(argv[0], (char **)argv); 840 execvp(argv[0], (char **)argv);
841 841
842 perror(argv[0]); 842 perror(argv[0]);
843 kill(getppid(), SIGUSR1); 843 kill(getppid(), SIGUSR1);
844 exit(-1); 844 exit(-1);
845 } 845 }
846 846
847 if (perf_target__none(&opts->target)) 847 if (perf_target__none(&opts->target))
848 evlist->threads->map[0] = evlist->workload.pid; 848 evlist->threads->map[0] = evlist->workload.pid;
849 849
850 close(child_ready_pipe[1]); 850 close(child_ready_pipe[1]);
851 close(go_pipe[0]); 851 close(go_pipe[0]);
852 /* 852 /*
853 * wait for child to settle 853 * wait for child to settle
854 */ 854 */
855 if (read(child_ready_pipe[0], &bf, 1) == -1) { 855 if (read(child_ready_pipe[0], &bf, 1) == -1) {
856 perror("unable to read pipe"); 856 perror("unable to read pipe");
857 goto out_close_pipes; 857 goto out_close_pipes;
858 } 858 }
859 859
860 evlist->workload.cork_fd = go_pipe[1]; 860 evlist->workload.cork_fd = go_pipe[1];
861 close(child_ready_pipe[0]); 861 close(child_ready_pipe[0]);
862 return 0; 862 return 0;
863 863
864 out_close_pipes: 864 out_close_pipes:
865 close(go_pipe[0]); 865 close(go_pipe[0]);
866 close(go_pipe[1]); 866 close(go_pipe[1]);
867 out_close_ready_pipe: 867 out_close_ready_pipe:
868 close(child_ready_pipe[0]); 868 close(child_ready_pipe[0]);
869 close(child_ready_pipe[1]); 869 close(child_ready_pipe[1]);
870 return -1; 870 return -1;
871 } 871 }
872 872
873 int perf_evlist__start_workload(struct perf_evlist *evlist) 873 int perf_evlist__start_workload(struct perf_evlist *evlist)
874 { 874 {
875 if (evlist->workload.cork_fd > 0) { 875 if (evlist->workload.cork_fd > 0) {
876 /* 876 /*
877 * Remove the cork, let it rip! 877 * Remove the cork, let it rip!
878 */ 878 */
879 return close(evlist->workload.cork_fd); 879 return close(evlist->workload.cork_fd);
880 } 880 }
881 881
882 return 0; 882 return 0;
883 } 883 }
884 884
885 int perf_evlist__parse_sample(struct perf_evlist *evlist, 885 int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
886 const union perf_event *event,
887 struct perf_sample *sample, bool swapped) 886 struct perf_sample *sample, bool swapped)
888 { 887 {
889 struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); 888 struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
890 return perf_event__parse_sample(event, e->attr.sample_type, e->sample_size, 889 return perf_evsel__parse_sample(e, event, sample, swapped);
891 e->attr.sample_id_all, sample, swapped);
892 } 890 }
893 891
tools/perf/util/evlist.h
1 #ifndef __PERF_EVLIST_H 1 #ifndef __PERF_EVLIST_H
2 #define __PERF_EVLIST_H 1 2 #define __PERF_EVLIST_H 1
3 3
4 #include <linux/list.h> 4 #include <linux/list.h>
5 #include <stdio.h> 5 #include <stdio.h>
6 #include "../perf.h" 6 #include "../perf.h"
7 #include "event.h" 7 #include "event.h"
8 #include "util.h" 8 #include "util.h"
9 #include <unistd.h> 9 #include <unistd.h>
10 10
11 struct pollfd; 11 struct pollfd;
12 struct thread_map; 12 struct thread_map;
13 struct cpu_map; 13 struct cpu_map;
14 struct perf_record_opts; 14 struct perf_record_opts;
15 15
16 #define PERF_EVLIST__HLIST_BITS 8 16 #define PERF_EVLIST__HLIST_BITS 8
17 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 17 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
18 18
19 struct perf_evlist { 19 struct perf_evlist {
20 struct list_head entries; 20 struct list_head entries;
21 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 21 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
22 int nr_entries; 22 int nr_entries;
23 int nr_fds; 23 int nr_fds;
24 int nr_mmaps; 24 int nr_mmaps;
25 int mmap_len; 25 int mmap_len;
26 struct { 26 struct {
27 int cork_fd; 27 int cork_fd;
28 pid_t pid; 28 pid_t pid;
29 } workload; 29 } workload;
30 bool overwrite; 30 bool overwrite;
31 union perf_event event_copy; 31 union perf_event event_copy;
32 struct perf_mmap *mmap; 32 struct perf_mmap *mmap;
33 struct pollfd *pollfd; 33 struct pollfd *pollfd;
34 struct thread_map *threads; 34 struct thread_map *threads;
35 struct cpu_map *cpus; 35 struct cpu_map *cpus;
36 struct perf_evsel *selected; 36 struct perf_evsel *selected;
37 }; 37 };
38 38
39 struct perf_evsel_str_handler { 39 struct perf_evsel_str_handler {
40 const char *name; 40 const char *name;
41 void *handler; 41 void *handler;
42 }; 42 };
43 43
44 struct perf_evsel; 44 struct perf_evsel;
45 45
46 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 46 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
47 struct thread_map *threads); 47 struct thread_map *threads);
48 void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 48 void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
49 struct thread_map *threads); 49 struct thread_map *threads);
50 void perf_evlist__exit(struct perf_evlist *evlist); 50 void perf_evlist__exit(struct perf_evlist *evlist);
51 void perf_evlist__delete(struct perf_evlist *evlist); 51 void perf_evlist__delete(struct perf_evlist *evlist);
52 52
53 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 53 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
54 int perf_evlist__add_default(struct perf_evlist *evlist); 54 int perf_evlist__add_default(struct perf_evlist *evlist);
55 int perf_evlist__add_attrs(struct perf_evlist *evlist, 55 int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs); 56 struct perf_event_attr *attrs, size_t nr_attrs);
57 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 57 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
58 struct perf_event_attr *attrs, size_t nr_attrs); 58 struct perf_event_attr *attrs, size_t nr_attrs);
59 int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 59 int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
60 const char *tracepoints[], size_t nr_tracepoints); 60 const char *tracepoints[], size_t nr_tracepoints);
61 int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 61 int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
62 const struct perf_evsel_str_handler *assocs, 62 const struct perf_evsel_str_handler *assocs,
63 size_t nr_assocs); 63 size_t nr_assocs);
64 64
65 #define perf_evlist__add_attrs_array(evlist, array) \ 65 #define perf_evlist__add_attrs_array(evlist, array) \
66 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array)) 66 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
67 #define perf_evlist__add_default_attrs(evlist, array) \ 67 #define perf_evlist__add_default_attrs(evlist, array) \
68 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 68 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
69 69
70 #define perf_evlist__add_tracepoints_array(evlist, array) \ 70 #define perf_evlist__add_tracepoints_array(evlist, array) \
71 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) 71 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
72 72
73 #define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 73 #define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
75 75
76 struct perf_evsel * 76 struct perf_evsel *
77 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 77 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
78 78
79 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 79 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
80 int cpu, int thread, u64 id); 80 int cpu, int thread, u64 id);
81 81
82 void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 82 void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
83 83
84 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 84 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
85 85
86 union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 86 union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
87 87
88 int perf_evlist__open(struct perf_evlist *evlist, bool group); 88 int perf_evlist__open(struct perf_evlist *evlist, bool group);
89 89
90 void perf_evlist__config_attrs(struct perf_evlist *evlist, 90 void perf_evlist__config_attrs(struct perf_evlist *evlist,
91 struct perf_record_opts *opts); 91 struct perf_record_opts *opts);
92 92
93 int perf_evlist__prepare_workload(struct perf_evlist *evlist, 93 int perf_evlist__prepare_workload(struct perf_evlist *evlist,
94 struct perf_record_opts *opts, 94 struct perf_record_opts *opts,
95 const char *argv[]); 95 const char *argv[]);
96 int perf_evlist__start_workload(struct perf_evlist *evlist); 96 int perf_evlist__start_workload(struct perf_evlist *evlist);
97 97
98 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 98 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
99 bool overwrite); 99 bool overwrite);
100 void perf_evlist__munmap(struct perf_evlist *evlist); 100 void perf_evlist__munmap(struct perf_evlist *evlist);
101 101
102 void perf_evlist__disable(struct perf_evlist *evlist); 102 void perf_evlist__disable(struct perf_evlist *evlist);
103 void perf_evlist__enable(struct perf_evlist *evlist); 103 void perf_evlist__enable(struct perf_evlist *evlist);
104 104
105 void perf_evlist__set_selected(struct perf_evlist *evlist, 105 void perf_evlist__set_selected(struct perf_evlist *evlist,
106 struct perf_evsel *evsel); 106 struct perf_evsel *evsel);
107 107
108 static inline void perf_evlist__set_maps(struct perf_evlist *evlist, 108 static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
109 struct cpu_map *cpus, 109 struct cpu_map *cpus,
110 struct thread_map *threads) 110 struct thread_map *threads)
111 { 111 {
112 evlist->cpus = cpus; 112 evlist->cpus = cpus;
113 evlist->threads = threads; 113 evlist->threads = threads;
114 } 114 }
115 115
116 int perf_evlist__create_maps(struct perf_evlist *evlist, 116 int perf_evlist__create_maps(struct perf_evlist *evlist,
117 struct perf_target *target); 117 struct perf_target *target);
118 void perf_evlist__delete_maps(struct perf_evlist *evlist); 118 void perf_evlist__delete_maps(struct perf_evlist *evlist);
119 int perf_evlist__set_filters(struct perf_evlist *evlist); 119 int perf_evlist__set_filters(struct perf_evlist *evlist);
120 120
121 u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 121 u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
122 bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 122 bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
123 u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); 123 u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
124 124
125 int perf_evlist__parse_sample(struct perf_evlist *evlist, 125 int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
126 const union perf_event *event,
127 struct perf_sample *sample, bool swapped); 126 struct perf_sample *sample, bool swapped);
128 127
129 bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 128 bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
130 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 129 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
131 130
132 void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 131 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
133 struct list_head *list, 132 struct list_head *list,
134 int nr_entries); 133 int nr_entries);
135 134
136 #endif /* __PERF_EVLIST_H */ 135 #endif /* __PERF_EVLIST_H */
137 136
tools/perf/util/evsel.c
1 /* 1 /*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 * 3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further 4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes. 5 * copyright notes.
6 * 6 *
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 9
10 #include <byteswap.h> 10 #include <byteswap.h>
11 #include "asm/bug.h" 11 #include "asm/bug.h"
12 #include "evsel.h" 12 #include "evsel.h"
13 #include "evlist.h" 13 #include "evlist.h"
14 #include "util.h" 14 #include "util.h"
15 #include "cpumap.h" 15 #include "cpumap.h"
16 #include "thread_map.h" 16 #include "thread_map.h"
17 #include "target.h" 17 #include "target.h"
18 #include "../../../include/linux/hw_breakpoint.h" 18 #include "../../../include/linux/hw_breakpoint.h"
19 19
20 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 20 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
21 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 21 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
22 22
23 static int __perf_evsel__sample_size(u64 sample_type) 23 static int __perf_evsel__sample_size(u64 sample_type)
24 { 24 {
25 u64 mask = sample_type & PERF_SAMPLE_MASK; 25 u64 mask = sample_type & PERF_SAMPLE_MASK;
26 int size = 0; 26 int size = 0;
27 int i; 27 int i;
28 28
29 for (i = 0; i < 64; i++) { 29 for (i = 0; i < 64; i++) {
30 if (mask & (1ULL << i)) 30 if (mask & (1ULL << i))
31 size++; 31 size++;
32 } 32 }
33 33
34 size *= sizeof(u64); 34 size *= sizeof(u64);
35 35
36 return size; 36 return size;
37 } 37 }
38 38
39 void hists__init(struct hists *hists) 39 void hists__init(struct hists *hists)
40 { 40 {
41 memset(hists, 0, sizeof(*hists)); 41 memset(hists, 0, sizeof(*hists));
42 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 42 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
43 hists->entries_in = &hists->entries_in_array[0]; 43 hists->entries_in = &hists->entries_in_array[0];
44 hists->entries_collapsed = RB_ROOT; 44 hists->entries_collapsed = RB_ROOT;
45 hists->entries = RB_ROOT; 45 hists->entries = RB_ROOT;
46 pthread_mutex_init(&hists->lock, NULL); 46 pthread_mutex_init(&hists->lock, NULL);
47 } 47 }
48 48
49 void perf_evsel__init(struct perf_evsel *evsel, 49 void perf_evsel__init(struct perf_evsel *evsel,
50 struct perf_event_attr *attr, int idx) 50 struct perf_event_attr *attr, int idx)
51 { 51 {
52 evsel->idx = idx; 52 evsel->idx = idx;
53 evsel->attr = *attr; 53 evsel->attr = *attr;
54 INIT_LIST_HEAD(&evsel->node); 54 INIT_LIST_HEAD(&evsel->node);
55 hists__init(&evsel->hists); 55 hists__init(&evsel->hists);
56 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 56 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
57 } 57 }
58 58
59 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 59 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
60 { 60 {
61 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 61 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
62 62
63 if (evsel != NULL) 63 if (evsel != NULL)
64 perf_evsel__init(evsel, attr, idx); 64 perf_evsel__init(evsel, attr, idx);
65 65
66 return evsel; 66 return evsel;
67 } 67 }
68 68
69 static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { 69 static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
70 "cycles", 70 "cycles",
71 "instructions", 71 "instructions",
72 "cache-references", 72 "cache-references",
73 "cache-misses", 73 "cache-misses",
74 "branches", 74 "branches",
75 "branch-misses", 75 "branch-misses",
76 "bus-cycles", 76 "bus-cycles",
77 "stalled-cycles-frontend", 77 "stalled-cycles-frontend",
78 "stalled-cycles-backend", 78 "stalled-cycles-backend",
79 "ref-cycles", 79 "ref-cycles",
80 }; 80 };
81 81
82 static const char *__perf_evsel__hw_name(u64 config) 82 static const char *__perf_evsel__hw_name(u64 config)
83 { 83 {
84 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 84 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
85 return perf_evsel__hw_names[config]; 85 return perf_evsel__hw_names[config];
86 86
87 return "unknown-hardware"; 87 return "unknown-hardware";
88 } 88 }
89 89
90 static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size) 90 static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
91 { 91 {
92 int colon = 0, r = 0; 92 int colon = 0, r = 0;
93 struct perf_event_attr *attr = &evsel->attr; 93 struct perf_event_attr *attr = &evsel->attr;
94 bool exclude_guest_default = false; 94 bool exclude_guest_default = false;
95 95
96 #define MOD_PRINT(context, mod) do { \ 96 #define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 97 if (!attr->exclude_##context) { \
98 if (!colon) colon = ++r; \ 98 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 99 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 100 } } while(0)
101 101
102 if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) { 102 if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
103 MOD_PRINT(kernel, 'k'); 103 MOD_PRINT(kernel, 'k');
104 MOD_PRINT(user, 'u'); 104 MOD_PRINT(user, 'u');
105 MOD_PRINT(hv, 'h'); 105 MOD_PRINT(hv, 'h');
106 exclude_guest_default = true; 106 exclude_guest_default = true;
107 } 107 }
108 108
109 if (attr->precise_ip) { 109 if (attr->precise_ip) {
110 if (!colon) 110 if (!colon)
111 colon = ++r; 111 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 113 exclude_guest_default = true;
114 } 114 }
115 115
116 if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) { 116 if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
117 MOD_PRINT(host, 'H'); 117 MOD_PRINT(host, 'H');
118 MOD_PRINT(guest, 'G'); 118 MOD_PRINT(guest, 'G');
119 } 119 }
120 #undef MOD_PRINT 120 #undef MOD_PRINT
121 if (colon) 121 if (colon)
122 bf[colon - 1] = ':'; 122 bf[colon - 1] = ':';
123 return r; 123 return r;
124 } 124 }
125 125
126 static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 126 static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
127 { 127 {
128 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config)); 128 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
129 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 129 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
130 } 130 }
131 131
132 static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { 132 static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
133 "cpu-clock", 133 "cpu-clock",
134 "task-clock", 134 "task-clock",
135 "page-faults", 135 "page-faults",
136 "context-switches", 136 "context-switches",
137 "CPU-migrations", 137 "CPU-migrations",
138 "minor-faults", 138 "minor-faults",
139 "major-faults", 139 "major-faults",
140 "alignment-faults", 140 "alignment-faults",
141 "emulation-faults", 141 "emulation-faults",
142 }; 142 };
143 143
144 static const char *__perf_evsel__sw_name(u64 config) 144 static const char *__perf_evsel__sw_name(u64 config)
145 { 145 {
146 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config]) 146 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
147 return perf_evsel__sw_names[config]; 147 return perf_evsel__sw_names[config];
148 return "unknown-software"; 148 return "unknown-software";
149 } 149 }
150 150
151 static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) 151 static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
152 { 152 {
153 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config)); 153 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
154 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 154 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
155 } 155 }
156 156
157 static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) 157 static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
158 { 158 {
159 int r; 159 int r;
160 160
161 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr); 161 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
162 162
163 if (type & HW_BREAKPOINT_R) 163 if (type & HW_BREAKPOINT_R)
164 r += scnprintf(bf + r, size - r, "r"); 164 r += scnprintf(bf + r, size - r, "r");
165 165
166 if (type & HW_BREAKPOINT_W) 166 if (type & HW_BREAKPOINT_W)
167 r += scnprintf(bf + r, size - r, "w"); 167 r += scnprintf(bf + r, size - r, "w");
168 168
169 if (type & HW_BREAKPOINT_X) 169 if (type & HW_BREAKPOINT_X)
170 r += scnprintf(bf + r, size - r, "x"); 170 r += scnprintf(bf + r, size - r, "x");
171 171
172 return r; 172 return r;
173 } 173 }
174 174
175 static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) 175 static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
176 { 176 {
177 struct perf_event_attr *attr = &evsel->attr; 177 struct perf_event_attr *attr = &evsel->attr;
178 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); 178 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
179 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 179 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
180 } 180 }
181 181
182 const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] 182 const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
183 [PERF_EVSEL__MAX_ALIASES] = { 183 [PERF_EVSEL__MAX_ALIASES] = {
184 { "L1-dcache", "l1-d", "l1d", "L1-data", }, 184 { "L1-dcache", "l1-d", "l1d", "L1-data", },
185 { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 185 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
186 { "LLC", "L2", }, 186 { "LLC", "L2", },
187 { "dTLB", "d-tlb", "Data-TLB", }, 187 { "dTLB", "d-tlb", "Data-TLB", },
188 { "iTLB", "i-tlb", "Instruction-TLB", }, 188 { "iTLB", "i-tlb", "Instruction-TLB", },
189 { "branch", "branches", "bpu", "btb", "bpc", }, 189 { "branch", "branches", "bpu", "btb", "bpc", },
190 { "node", }, 190 { "node", },
191 }; 191 };
192 192
193 const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] 193 const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
194 [PERF_EVSEL__MAX_ALIASES] = { 194 [PERF_EVSEL__MAX_ALIASES] = {
195 { "load", "loads", "read", }, 195 { "load", "loads", "read", },
196 { "store", "stores", "write", }, 196 { "store", "stores", "write", },
197 { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 197 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
198 }; 198 };
199 199
200 const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] 200 const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
201 [PERF_EVSEL__MAX_ALIASES] = { 201 [PERF_EVSEL__MAX_ALIASES] = {
202 { "refs", "Reference", "ops", "access", }, 202 { "refs", "Reference", "ops", "access", },
203 { "misses", "miss", }, 203 { "misses", "miss", },
204 }; 204 };
205 205
206 #define C(x) PERF_COUNT_HW_CACHE_##x 206 #define C(x) PERF_COUNT_HW_CACHE_##x
207 #define CACHE_READ (1 << C(OP_READ)) 207 #define CACHE_READ (1 << C(OP_READ))
208 #define CACHE_WRITE (1 << C(OP_WRITE)) 208 #define CACHE_WRITE (1 << C(OP_WRITE))
209 #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 209 #define CACHE_PREFETCH (1 << C(OP_PREFETCH))
210 #define COP(x) (1 << x) 210 #define COP(x) (1 << x)
211 211
212 /* 212 /*
213 * cache operartion stat 213 * cache operartion stat
214 * L1I : Read and prefetch only 214 * L1I : Read and prefetch only
215 * ITLB and BPU : Read-only 215 * ITLB and BPU : Read-only
216 */ 216 */
217 static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = { 217 static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
218 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 218 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
219 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 219 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
220 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 220 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 221 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
222 [C(ITLB)] = (CACHE_READ), 222 [C(ITLB)] = (CACHE_READ),
223 [C(BPU)] = (CACHE_READ), 223 [C(BPU)] = (CACHE_READ),
224 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 224 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
225 }; 225 };
226 226
227 bool perf_evsel__is_cache_op_valid(u8 type, u8 op) 227 bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
228 { 228 {
229 if (perf_evsel__hw_cache_stat[type] & COP(op)) 229 if (perf_evsel__hw_cache_stat[type] & COP(op))
230 return true; /* valid */ 230 return true; /* valid */
231 else 231 else
232 return false; /* invalid */ 232 return false; /* invalid */
233 } 233 }
234 234
235 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, 235 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
236 char *bf, size_t size) 236 char *bf, size_t size)
237 { 237 {
238 if (result) { 238 if (result) {
239 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0], 239 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
240 perf_evsel__hw_cache_op[op][0], 240 perf_evsel__hw_cache_op[op][0],
241 perf_evsel__hw_cache_result[result][0]); 241 perf_evsel__hw_cache_result[result][0]);
242 } 242 }
243 243
244 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0], 244 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
245 perf_evsel__hw_cache_op[op][1]); 245 perf_evsel__hw_cache_op[op][1]);
246 } 246 }
247 247
248 static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) 248 static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
249 { 249 {
250 u8 op, result, type = (config >> 0) & 0xff; 250 u8 op, result, type = (config >> 0) & 0xff;
251 const char *err = "unknown-ext-hardware-cache-type"; 251 const char *err = "unknown-ext-hardware-cache-type";
252 252
253 if (type > PERF_COUNT_HW_CACHE_MAX) 253 if (type > PERF_COUNT_HW_CACHE_MAX)
254 goto out_err; 254 goto out_err;
255 255
256 op = (config >> 8) & 0xff; 256 op = (config >> 8) & 0xff;
257 err = "unknown-ext-hardware-cache-op"; 257 err = "unknown-ext-hardware-cache-op";
258 if (op > PERF_COUNT_HW_CACHE_OP_MAX) 258 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
259 goto out_err; 259 goto out_err;
260 260
261 result = (config >> 16) & 0xff; 261 result = (config >> 16) & 0xff;
262 err = "unknown-ext-hardware-cache-result"; 262 err = "unknown-ext-hardware-cache-result";
263 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX) 263 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
264 goto out_err; 264 goto out_err;
265 265
266 err = "invalid-cache"; 266 err = "invalid-cache";
267 if (!perf_evsel__is_cache_op_valid(type, op)) 267 if (!perf_evsel__is_cache_op_valid(type, op))
268 goto out_err; 268 goto out_err;
269 269
270 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size); 270 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
271 out_err: 271 out_err:
272 return scnprintf(bf, size, "%s", err); 272 return scnprintf(bf, size, "%s", err);
273 } 273 }
274 274
275 static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size) 275 static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
276 { 276 {
277 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); 277 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
278 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); 278 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
279 } 279 }
280 280
281 static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size) 281 static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
282 { 282 {
283 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 283 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
284 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); 284 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
285 } 285 }
286 286
287 const char *perf_evsel__name(struct perf_evsel *evsel) 287 const char *perf_evsel__name(struct perf_evsel *evsel)
288 { 288 {
289 char bf[128]; 289 char bf[128];
290 290
291 if (evsel->name) 291 if (evsel->name)
292 return evsel->name; 292 return evsel->name;
293 293
294 switch (evsel->attr.type) { 294 switch (evsel->attr.type) {
295 case PERF_TYPE_RAW: 295 case PERF_TYPE_RAW:
296 perf_evsel__raw_name(evsel, bf, sizeof(bf)); 296 perf_evsel__raw_name(evsel, bf, sizeof(bf));
297 break; 297 break;
298 298
299 case PERF_TYPE_HARDWARE: 299 case PERF_TYPE_HARDWARE:
300 perf_evsel__hw_name(evsel, bf, sizeof(bf)); 300 perf_evsel__hw_name(evsel, bf, sizeof(bf));
301 break; 301 break;
302 302
303 case PERF_TYPE_HW_CACHE: 303 case PERF_TYPE_HW_CACHE:
304 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf)); 304 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
305 break; 305 break;
306 306
307 case PERF_TYPE_SOFTWARE: 307 case PERF_TYPE_SOFTWARE:
308 perf_evsel__sw_name(evsel, bf, sizeof(bf)); 308 perf_evsel__sw_name(evsel, bf, sizeof(bf));
309 break; 309 break;
310 310
311 case PERF_TYPE_TRACEPOINT: 311 case PERF_TYPE_TRACEPOINT:
312 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); 312 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
313 break; 313 break;
314 314
315 case PERF_TYPE_BREAKPOINT: 315 case PERF_TYPE_BREAKPOINT:
316 perf_evsel__bp_name(evsel, bf, sizeof(bf)); 316 perf_evsel__bp_name(evsel, bf, sizeof(bf));
317 break; 317 break;
318 318
319 default: 319 default:
320 scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); 320 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
321 break; 321 break;
322 } 322 }
323 323
324 evsel->name = strdup(bf); 324 evsel->name = strdup(bf);
325 325
326 return evsel->name ?: "unknown"; 326 return evsel->name ?: "unknown";
327 } 327 }
328 328
329 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 329 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
330 struct perf_evsel *first) 330 struct perf_evsel *first)
331 { 331 {
332 struct perf_event_attr *attr = &evsel->attr; 332 struct perf_event_attr *attr = &evsel->attr;
333 int track = !evsel->idx; /* only the first counter needs these */ 333 int track = !evsel->idx; /* only the first counter needs these */
334 334
335 attr->disabled = 1; 335 attr->disabled = 1;
336 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 336 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
337 attr->inherit = !opts->no_inherit; 337 attr->inherit = !opts->no_inherit;
338 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 338 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
339 PERF_FORMAT_TOTAL_TIME_RUNNING | 339 PERF_FORMAT_TOTAL_TIME_RUNNING |
340 PERF_FORMAT_ID; 340 PERF_FORMAT_ID;
341 341
342 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 342 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
343 343
344 /* 344 /*
345 * We default some events to a 1 default interval. But keep 345 * We default some events to a 1 default interval. But keep
346 * it a weak assumption overridable by the user. 346 * it a weak assumption overridable by the user.
347 */ 347 */
348 if (!attr->sample_period || (opts->user_freq != UINT_MAX && 348 if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
349 opts->user_interval != ULLONG_MAX)) { 349 opts->user_interval != ULLONG_MAX)) {
350 if (opts->freq) { 350 if (opts->freq) {
351 attr->sample_type |= PERF_SAMPLE_PERIOD; 351 attr->sample_type |= PERF_SAMPLE_PERIOD;
352 attr->freq = 1; 352 attr->freq = 1;
353 attr->sample_freq = opts->freq; 353 attr->sample_freq = opts->freq;
354 } else { 354 } else {
355 attr->sample_period = opts->default_interval; 355 attr->sample_period = opts->default_interval;
356 } 356 }
357 } 357 }
358 358
359 if (opts->no_samples) 359 if (opts->no_samples)
360 attr->sample_freq = 0; 360 attr->sample_freq = 0;
361 361
362 if (opts->inherit_stat) 362 if (opts->inherit_stat)
363 attr->inherit_stat = 1; 363 attr->inherit_stat = 1;
364 364
365 if (opts->sample_address) { 365 if (opts->sample_address) {
366 attr->sample_type |= PERF_SAMPLE_ADDR; 366 attr->sample_type |= PERF_SAMPLE_ADDR;
367 attr->mmap_data = track; 367 attr->mmap_data = track;
368 } 368 }
369 369
370 if (opts->call_graph) 370 if (opts->call_graph)
371 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 371 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
372 372
373 if (perf_target__has_cpu(&opts->target)) 373 if (perf_target__has_cpu(&opts->target))
374 attr->sample_type |= PERF_SAMPLE_CPU; 374 attr->sample_type |= PERF_SAMPLE_CPU;
375 375
376 if (opts->period) 376 if (opts->period)
377 attr->sample_type |= PERF_SAMPLE_PERIOD; 377 attr->sample_type |= PERF_SAMPLE_PERIOD;
378 378
379 if (!opts->sample_id_all_missing && 379 if (!opts->sample_id_all_missing &&
380 (opts->sample_time || !opts->no_inherit || 380 (opts->sample_time || !opts->no_inherit ||
381 perf_target__has_cpu(&opts->target))) 381 perf_target__has_cpu(&opts->target)))
382 attr->sample_type |= PERF_SAMPLE_TIME; 382 attr->sample_type |= PERF_SAMPLE_TIME;
383 383
384 if (opts->raw_samples) { 384 if (opts->raw_samples) {
385 attr->sample_type |= PERF_SAMPLE_TIME; 385 attr->sample_type |= PERF_SAMPLE_TIME;
386 attr->sample_type |= PERF_SAMPLE_RAW; 386 attr->sample_type |= PERF_SAMPLE_RAW;
387 attr->sample_type |= PERF_SAMPLE_CPU; 387 attr->sample_type |= PERF_SAMPLE_CPU;
388 } 388 }
389 389
390 if (opts->no_delay) { 390 if (opts->no_delay) {
391 attr->watermark = 0; 391 attr->watermark = 0;
392 attr->wakeup_events = 1; 392 attr->wakeup_events = 1;
393 } 393 }
394 if (opts->branch_stack) { 394 if (opts->branch_stack) {
395 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; 395 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK;
396 attr->branch_sample_type = opts->branch_stack; 396 attr->branch_sample_type = opts->branch_stack;
397 } 397 }
398 398
399 attr->mmap = track; 399 attr->mmap = track;
400 attr->comm = track; 400 attr->comm = track;
401 401
402 if (perf_target__none(&opts->target) && 402 if (perf_target__none(&opts->target) &&
403 (!opts->group || evsel == first)) { 403 (!opts->group || evsel == first)) {
404 attr->enable_on_exec = 1; 404 attr->enable_on_exec = 1;
405 } 405 }
406 } 406 }
407 407
408 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 408 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
409 { 409 {
410 int cpu, thread; 410 int cpu, thread;
411 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 411 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
412 412
413 if (evsel->fd) { 413 if (evsel->fd) {
414 for (cpu = 0; cpu < ncpus; cpu++) { 414 for (cpu = 0; cpu < ncpus; cpu++) {
415 for (thread = 0; thread < nthreads; thread++) { 415 for (thread = 0; thread < nthreads; thread++) {
416 FD(evsel, cpu, thread) = -1; 416 FD(evsel, cpu, thread) = -1;
417 } 417 }
418 } 418 }
419 } 419 }
420 420
421 return evsel->fd != NULL ? 0 : -ENOMEM; 421 return evsel->fd != NULL ? 0 : -ENOMEM;
422 } 422 }
423 423
424 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 424 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
425 { 425 {
426 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 426 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
427 if (evsel->sample_id == NULL) 427 if (evsel->sample_id == NULL)
428 return -ENOMEM; 428 return -ENOMEM;
429 429
430 evsel->id = zalloc(ncpus * nthreads * sizeof(u64)); 430 evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
431 if (evsel->id == NULL) { 431 if (evsel->id == NULL) {
432 xyarray__delete(evsel->sample_id); 432 xyarray__delete(evsel->sample_id);
433 evsel->sample_id = NULL; 433 evsel->sample_id = NULL;
434 return -ENOMEM; 434 return -ENOMEM;
435 } 435 }
436 436
437 return 0; 437 return 0;
438 } 438 }
439 439
440 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) 440 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
441 { 441 {
442 evsel->counts = zalloc((sizeof(*evsel->counts) + 442 evsel->counts = zalloc((sizeof(*evsel->counts) +
443 (ncpus * sizeof(struct perf_counts_values)))); 443 (ncpus * sizeof(struct perf_counts_values))));
444 return evsel->counts != NULL ? 0 : -ENOMEM; 444 return evsel->counts != NULL ? 0 : -ENOMEM;
445 } 445 }
446 446
447 void perf_evsel__free_fd(struct perf_evsel *evsel) 447 void perf_evsel__free_fd(struct perf_evsel *evsel)
448 { 448 {
449 xyarray__delete(evsel->fd); 449 xyarray__delete(evsel->fd);
450 evsel->fd = NULL; 450 evsel->fd = NULL;
451 } 451 }
452 452
453 void perf_evsel__free_id(struct perf_evsel *evsel) 453 void perf_evsel__free_id(struct perf_evsel *evsel)
454 { 454 {
455 xyarray__delete(evsel->sample_id); 455 xyarray__delete(evsel->sample_id);
456 evsel->sample_id = NULL; 456 evsel->sample_id = NULL;
457 free(evsel->id); 457 free(evsel->id);
458 evsel->id = NULL; 458 evsel->id = NULL;
459 } 459 }
460 460
461 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 461 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
462 { 462 {
463 int cpu, thread; 463 int cpu, thread;
464 464
465 for (cpu = 0; cpu < ncpus; cpu++) 465 for (cpu = 0; cpu < ncpus; cpu++)
466 for (thread = 0; thread < nthreads; ++thread) { 466 for (thread = 0; thread < nthreads; ++thread) {
467 close(FD(evsel, cpu, thread)); 467 close(FD(evsel, cpu, thread));
468 FD(evsel, cpu, thread) = -1; 468 FD(evsel, cpu, thread) = -1;
469 } 469 }
470 } 470 }
471 471
472 void perf_evsel__exit(struct perf_evsel *evsel) 472 void perf_evsel__exit(struct perf_evsel *evsel)
473 { 473 {
474 assert(list_empty(&evsel->node)); 474 assert(list_empty(&evsel->node));
475 xyarray__delete(evsel->fd); 475 xyarray__delete(evsel->fd);
476 xyarray__delete(evsel->sample_id); 476 xyarray__delete(evsel->sample_id);
477 free(evsel->id); 477 free(evsel->id);
478 } 478 }
479 479
480 void perf_evsel__delete(struct perf_evsel *evsel) 480 void perf_evsel__delete(struct perf_evsel *evsel)
481 { 481 {
482 perf_evsel__exit(evsel); 482 perf_evsel__exit(evsel);
483 close_cgroup(evsel->cgrp); 483 close_cgroup(evsel->cgrp);
484 free(evsel->name); 484 free(evsel->name);
485 free(evsel); 485 free(evsel);
486 } 486 }
487 487
488 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 488 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
489 int cpu, int thread, bool scale) 489 int cpu, int thread, bool scale)
490 { 490 {
491 struct perf_counts_values count; 491 struct perf_counts_values count;
492 size_t nv = scale ? 3 : 1; 492 size_t nv = scale ? 3 : 1;
493 493
494 if (FD(evsel, cpu, thread) < 0) 494 if (FD(evsel, cpu, thread) < 0)
495 return -EINVAL; 495 return -EINVAL;
496 496
497 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) 497 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
498 return -ENOMEM; 498 return -ENOMEM;
499 499
500 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) 500 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
501 return -errno; 501 return -errno;
502 502
503 if (scale) { 503 if (scale) {
504 if (count.run == 0) 504 if (count.run == 0)
505 count.val = 0; 505 count.val = 0;
506 else if (count.run < count.ena) 506 else if (count.run < count.ena)
507 count.val = (u64)((double)count.val * count.ena / count.run + 0.5); 507 count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
508 } else 508 } else
509 count.ena = count.run = 0; 509 count.ena = count.run = 0;
510 510
511 evsel->counts->cpu[cpu] = count; 511 evsel->counts->cpu[cpu] = count;
512 return 0; 512 return 0;
513 } 513 }
514 514
515 int __perf_evsel__read(struct perf_evsel *evsel, 515 int __perf_evsel__read(struct perf_evsel *evsel,
516 int ncpus, int nthreads, bool scale) 516 int ncpus, int nthreads, bool scale)
517 { 517 {
518 size_t nv = scale ? 3 : 1; 518 size_t nv = scale ? 3 : 1;
519 int cpu, thread; 519 int cpu, thread;
520 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 520 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
521 521
522 aggr->val = aggr->ena = aggr->run = 0; 522 aggr->val = aggr->ena = aggr->run = 0;
523 523
524 for (cpu = 0; cpu < ncpus; cpu++) { 524 for (cpu = 0; cpu < ncpus; cpu++) {
525 for (thread = 0; thread < nthreads; thread++) { 525 for (thread = 0; thread < nthreads; thread++) {
526 if (FD(evsel, cpu, thread) < 0) 526 if (FD(evsel, cpu, thread) < 0)
527 continue; 527 continue;
528 528
529 if (readn(FD(evsel, cpu, thread), 529 if (readn(FD(evsel, cpu, thread),
530 &count, nv * sizeof(u64)) < 0) 530 &count, nv * sizeof(u64)) < 0)
531 return -errno; 531 return -errno;
532 532
533 aggr->val += count.val; 533 aggr->val += count.val;
534 if (scale) { 534 if (scale) {
535 aggr->ena += count.ena; 535 aggr->ena += count.ena;
536 aggr->run += count.run; 536 aggr->run += count.run;
537 } 537 }
538 } 538 }
539 } 539 }
540 540
541 evsel->counts->scaled = 0; 541 evsel->counts->scaled = 0;
542 if (scale) { 542 if (scale) {
543 if (aggr->run == 0) { 543 if (aggr->run == 0) {
544 evsel->counts->scaled = -1; 544 evsel->counts->scaled = -1;
545 aggr->val = 0; 545 aggr->val = 0;
546 return 0; 546 return 0;
547 } 547 }
548 548
549 if (aggr->run < aggr->ena) { 549 if (aggr->run < aggr->ena) {
550 evsel->counts->scaled = 1; 550 evsel->counts->scaled = 1;
551 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); 551 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
552 } 552 }
553 } else 553 } else
554 aggr->ena = aggr->run = 0; 554 aggr->ena = aggr->run = 0;
555 555
556 return 0; 556 return 0;
557 } 557 }
558 558
559 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 559 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
560 struct thread_map *threads, bool group, 560 struct thread_map *threads, bool group,
561 struct xyarray *group_fds) 561 struct xyarray *group_fds)
562 { 562 {
563 int cpu, thread; 563 int cpu, thread;
564 unsigned long flags = 0; 564 unsigned long flags = 0;
565 int pid = -1, err; 565 int pid = -1, err;
566 566
567 if (evsel->fd == NULL && 567 if (evsel->fd == NULL &&
568 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 568 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
569 return -ENOMEM; 569 return -ENOMEM;
570 570
571 if (evsel->cgrp) { 571 if (evsel->cgrp) {
572 flags = PERF_FLAG_PID_CGROUP; 572 flags = PERF_FLAG_PID_CGROUP;
573 pid = evsel->cgrp->fd; 573 pid = evsel->cgrp->fd;
574 } 574 }
575 575
576 for (cpu = 0; cpu < cpus->nr; cpu++) { 576 for (cpu = 0; cpu < cpus->nr; cpu++) {
577 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1; 577 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
578 578
579 for (thread = 0; thread < threads->nr; thread++) { 579 for (thread = 0; thread < threads->nr; thread++) {
580 580
581 if (!evsel->cgrp) 581 if (!evsel->cgrp)
582 pid = threads->map[thread]; 582 pid = threads->map[thread];
583 583
584 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 584 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
585 pid, 585 pid,
586 cpus->map[cpu], 586 cpus->map[cpu],
587 group_fd, flags); 587 group_fd, flags);
588 if (FD(evsel, cpu, thread) < 0) { 588 if (FD(evsel, cpu, thread) < 0) {
589 err = -errno; 589 err = -errno;
590 goto out_close; 590 goto out_close;
591 } 591 }
592 592
593 if (group && group_fd == -1) 593 if (group && group_fd == -1)
594 group_fd = FD(evsel, cpu, thread); 594 group_fd = FD(evsel, cpu, thread);
595 } 595 }
596 } 596 }
597 597
598 return 0; 598 return 0;
599 599
600 out_close: 600 out_close:
601 do { 601 do {
602 while (--thread >= 0) { 602 while (--thread >= 0) {
603 close(FD(evsel, cpu, thread)); 603 close(FD(evsel, cpu, thread));
604 FD(evsel, cpu, thread) = -1; 604 FD(evsel, cpu, thread) = -1;
605 } 605 }
606 thread = threads->nr; 606 thread = threads->nr;
607 } while (--cpu >= 0); 607 } while (--cpu >= 0);
608 return err; 608 return err;
609 } 609 }
610 610
611 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads) 611 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
612 { 612 {
613 if (evsel->fd == NULL) 613 if (evsel->fd == NULL)
614 return; 614 return;
615 615
616 perf_evsel__close_fd(evsel, ncpus, nthreads); 616 perf_evsel__close_fd(evsel, ncpus, nthreads);
617 perf_evsel__free_fd(evsel); 617 perf_evsel__free_fd(evsel);
618 evsel->fd = NULL; 618 evsel->fd = NULL;
619 } 619 }
620 620
621 static struct { 621 static struct {
622 struct cpu_map map; 622 struct cpu_map map;
623 int cpus[1]; 623 int cpus[1];
624 } empty_cpu_map = { 624 } empty_cpu_map = {
625 .map.nr = 1, 625 .map.nr = 1,
626 .cpus = { -1, }, 626 .cpus = { -1, },
627 }; 627 };
628 628
629 static struct { 629 static struct {
630 struct thread_map map; 630 struct thread_map map;
631 int threads[1]; 631 int threads[1];
632 } empty_thread_map = { 632 } empty_thread_map = {
633 .map.nr = 1, 633 .map.nr = 1,
634 .threads = { -1, }, 634 .threads = { -1, },
635 }; 635 };
636 636
637 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 637 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
638 struct thread_map *threads, bool group, 638 struct thread_map *threads, bool group,
639 struct xyarray *group_fd) 639 struct xyarray *group_fd)
640 { 640 {
641 if (cpus == NULL) { 641 if (cpus == NULL) {
642 /* Work around old compiler warnings about strict aliasing */ 642 /* Work around old compiler warnings about strict aliasing */
643 cpus = &empty_cpu_map.map; 643 cpus = &empty_cpu_map.map;
644 } 644 }
645 645
646 if (threads == NULL) 646 if (threads == NULL)
647 threads = &empty_thread_map.map; 647 threads = &empty_thread_map.map;
648 648
649 return __perf_evsel__open(evsel, cpus, threads, group, group_fd); 649 return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
650 } 650 }
651 651
652 int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 652 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
653 struct cpu_map *cpus, bool group, 653 struct cpu_map *cpus, bool group,
654 struct xyarray *group_fd) 654 struct xyarray *group_fd)
655 { 655 {
656 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, 656 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
657 group_fd); 657 group_fd);
658 } 658 }
659 659
660 int perf_evsel__open_per_thread(struct perf_evsel *evsel, 660 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
661 struct thread_map *threads, bool group, 661 struct thread_map *threads, bool group,
662 struct xyarray *group_fd) 662 struct xyarray *group_fd)
663 { 663 {
664 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, 664 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
665 group_fd); 665 group_fd);
666 } 666 }
667 667
668 static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 668 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
669 struct perf_sample *sample, 669 struct perf_sample *sample,
670 bool swapped) 670 bool swapped)
671 { 671 {
672 const u64 *array = event->sample.array; 672 const u64 *array = event->sample.array;
673 union u64_swap u; 673 union u64_swap u;
674 674
675 array += ((event->header.size - 675 array += ((event->header.size -
676 sizeof(event->header)) / sizeof(u64)) - 1; 676 sizeof(event->header)) / sizeof(u64)) - 1;
677 677
678 if (type & PERF_SAMPLE_CPU) { 678 if (type & PERF_SAMPLE_CPU) {
679 u.val64 = *array; 679 u.val64 = *array;
680 if (swapped) { 680 if (swapped) {
681 /* undo swap of u64, then swap on individual u32s */ 681 /* undo swap of u64, then swap on individual u32s */
682 u.val64 = bswap_64(u.val64); 682 u.val64 = bswap_64(u.val64);
683 u.val32[0] = bswap_32(u.val32[0]); 683 u.val32[0] = bswap_32(u.val32[0]);
684 } 684 }
685 685
686 sample->cpu = u.val32[0]; 686 sample->cpu = u.val32[0];
687 array--; 687 array--;
688 } 688 }
689 689
690 if (type & PERF_SAMPLE_STREAM_ID) { 690 if (type & PERF_SAMPLE_STREAM_ID) {
691 sample->stream_id = *array; 691 sample->stream_id = *array;
692 array--; 692 array--;
693 } 693 }
694 694
695 if (type & PERF_SAMPLE_ID) { 695 if (type & PERF_SAMPLE_ID) {
696 sample->id = *array; 696 sample->id = *array;
697 array--; 697 array--;
698 } 698 }
699 699
700 if (type & PERF_SAMPLE_TIME) { 700 if (type & PERF_SAMPLE_TIME) {
701 sample->time = *array; 701 sample->time = *array;
702 array--; 702 array--;
703 } 703 }
704 704
705 if (type & PERF_SAMPLE_TID) { 705 if (type & PERF_SAMPLE_TID) {
706 u.val64 = *array; 706 u.val64 = *array;
707 if (swapped) { 707 if (swapped) {
708 /* undo swap of u64, then swap on individual u32s */ 708 /* undo swap of u64, then swap on individual u32s */
709 u.val64 = bswap_64(u.val64); 709 u.val64 = bswap_64(u.val64);
710 u.val32[0] = bswap_32(u.val32[0]); 710 u.val32[0] = bswap_32(u.val32[0]);
711 u.val32[1] = bswap_32(u.val32[1]); 711 u.val32[1] = bswap_32(u.val32[1]);
712 } 712 }
713 713
714 sample->pid = u.val32[0]; 714 sample->pid = u.val32[0];
715 sample->tid = u.val32[1]; 715 sample->tid = u.val32[1];
716 } 716 }
717 717
718 return 0; 718 return 0;
719 } 719 }
720 720
721 static bool sample_overlap(const union perf_event *event, 721 static bool sample_overlap(const union perf_event *event,
722 const void *offset, u64 size) 722 const void *offset, u64 size)
723 { 723 {
724 const void *base = event; 724 const void *base = event;
725 725
726 if (offset + size > base + event->header.size) 726 if (offset + size > base + event->header.size)
727 return true; 727 return true;
728 728
729 return false; 729 return false;
730 } 730 }
731 731
732 int perf_event__parse_sample(const union perf_event *event, u64 type, 732 int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
733 int sample_size, bool sample_id_all,
734 struct perf_sample *data, bool swapped) 733 struct perf_sample *data, bool swapped)
735 { 734 {
735 u64 type = evsel->attr.sample_type;
736 const u64 *array; 736 const u64 *array;
737 737
738 /* 738 /*
739 * used for cross-endian analysis. See git commit 65014ab3 739 * used for cross-endian analysis. See git commit 65014ab3
740 * for why this goofiness is needed. 740 * for why this goofiness is needed.
741 */ 741 */
742 union u64_swap u; 742 union u64_swap u;
743 743
744 memset(data, 0, sizeof(*data)); 744 memset(data, 0, sizeof(*data));
745 data->cpu = data->pid = data->tid = -1; 745 data->cpu = data->pid = data->tid = -1;
746 data->stream_id = data->id = data->time = -1ULL; 746 data->stream_id = data->id = data->time = -1ULL;
747 data->period = 1; 747 data->period = 1;
748 748
749 if (event->header.type != PERF_RECORD_SAMPLE) { 749 if (event->header.type != PERF_RECORD_SAMPLE) {
750 if (!sample_id_all) 750 if (!evsel->attr.sample_id_all)
751 return 0; 751 return 0;
752 return perf_event__parse_id_sample(event, type, data, swapped); 752 return perf_event__parse_id_sample(event, type, data, swapped);
753 } 753 }
754 754
755 array = event->sample.array; 755 array = event->sample.array;
756 756
757 if (sample_size + sizeof(event->header) > event->header.size) 757 if (evsel->sample_size + sizeof(event->header) > event->header.size)
758 return -EFAULT; 758 return -EFAULT;
759 759
760 if (type & PERF_SAMPLE_IP) { 760 if (type & PERF_SAMPLE_IP) {
761 data->ip = event->ip.ip; 761 data->ip = event->ip.ip;
762 array++; 762 array++;
763 } 763 }
764 764
765 if (type & PERF_SAMPLE_TID) { 765 if (type & PERF_SAMPLE_TID) {
766 u.val64 = *array; 766 u.val64 = *array;
767 if (swapped) { 767 if (swapped) {
768 /* undo swap of u64, then swap on individual u32s */ 768 /* undo swap of u64, then swap on individual u32s */
769 u.val64 = bswap_64(u.val64); 769 u.val64 = bswap_64(u.val64);
770 u.val32[0] = bswap_32(u.val32[0]); 770 u.val32[0] = bswap_32(u.val32[0]);
771 u.val32[1] = bswap_32(u.val32[1]); 771 u.val32[1] = bswap_32(u.val32[1]);
772 } 772 }
773 773
774 data->pid = u.val32[0]; 774 data->pid = u.val32[0];
775 data->tid = u.val32[1]; 775 data->tid = u.val32[1];
776 array++; 776 array++;
777 } 777 }
778 778
779 if (type & PERF_SAMPLE_TIME) { 779 if (type & PERF_SAMPLE_TIME) {
780 data->time = *array; 780 data->time = *array;
781 array++; 781 array++;
782 } 782 }
783 783
784 data->addr = 0; 784 data->addr = 0;
785 if (type & PERF_SAMPLE_ADDR) { 785 if (type & PERF_SAMPLE_ADDR) {
786 data->addr = *array; 786 data->addr = *array;
787 array++; 787 array++;
788 } 788 }
789 789
790 data->id = -1ULL; 790 data->id = -1ULL;
791 if (type & PERF_SAMPLE_ID) { 791 if (type & PERF_SAMPLE_ID) {
792 data->id = *array; 792 data->id = *array;
793 array++; 793 array++;
794 } 794 }
795 795
796 if (type & PERF_SAMPLE_STREAM_ID) { 796 if (type & PERF_SAMPLE_STREAM_ID) {
797 data->stream_id = *array; 797 data->stream_id = *array;
798 array++; 798 array++;
799 } 799 }
800 800
801 if (type & PERF_SAMPLE_CPU) { 801 if (type & PERF_SAMPLE_CPU) {
802 802
803 u.val64 = *array; 803 u.val64 = *array;
804 if (swapped) { 804 if (swapped) {
805 /* undo swap of u64, then swap on individual u32s */ 805 /* undo swap of u64, then swap on individual u32s */
806 u.val64 = bswap_64(u.val64); 806 u.val64 = bswap_64(u.val64);
807 u.val32[0] = bswap_32(u.val32[0]); 807 u.val32[0] = bswap_32(u.val32[0]);
808 } 808 }
809 809
810 data->cpu = u.val32[0]; 810 data->cpu = u.val32[0];
811 array++; 811 array++;
812 } 812 }
813 813
814 if (type & PERF_SAMPLE_PERIOD) { 814 if (type & PERF_SAMPLE_PERIOD) {
815 data->period = *array; 815 data->period = *array;
816 array++; 816 array++;
817 } 817 }
818 818
819 if (type & PERF_SAMPLE_READ) { 819 if (type & PERF_SAMPLE_READ) {
820 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n"); 820 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
821 return -1; 821 return -1;
822 } 822 }
823 823
824 if (type & PERF_SAMPLE_CALLCHAIN) { 824 if (type & PERF_SAMPLE_CALLCHAIN) {
825 if (sample_overlap(event, array, sizeof(data->callchain->nr))) 825 if (sample_overlap(event, array, sizeof(data->callchain->nr)))
826 return -EFAULT; 826 return -EFAULT;
827 827
828 data->callchain = (struct ip_callchain *)array; 828 data->callchain = (struct ip_callchain *)array;
829 829
830 if (sample_overlap(event, array, data->callchain->nr)) 830 if (sample_overlap(event, array, data->callchain->nr))
831 return -EFAULT; 831 return -EFAULT;
832 832
833 array += 1 + data->callchain->nr; 833 array += 1 + data->callchain->nr;
834 } 834 }
835 835
836 if (type & PERF_SAMPLE_RAW) { 836 if (type & PERF_SAMPLE_RAW) {
837 const u64 *pdata; 837 const u64 *pdata;
838 838
839 u.val64 = *array; 839 u.val64 = *array;
840 if (WARN_ONCE(swapped, 840 if (WARN_ONCE(swapped,
841 "Endianness of raw data not corrected!\n")) { 841 "Endianness of raw data not corrected!\n")) {
842 /* undo swap of u64, then swap on individual u32s */ 842 /* undo swap of u64, then swap on individual u32s */
843 u.val64 = bswap_64(u.val64); 843 u.val64 = bswap_64(u.val64);
844 u.val32[0] = bswap_32(u.val32[0]); 844 u.val32[0] = bswap_32(u.val32[0]);
845 u.val32[1] = bswap_32(u.val32[1]); 845 u.val32[1] = bswap_32(u.val32[1]);
846 } 846 }
847 847
848 if (sample_overlap(event, array, sizeof(u32))) 848 if (sample_overlap(event, array, sizeof(u32)))
849 return -EFAULT; 849 return -EFAULT;
850 850
851 data->raw_size = u.val32[0]; 851 data->raw_size = u.val32[0];
852 pdata = (void *) array + sizeof(u32); 852 pdata = (void *) array + sizeof(u32);
853 853
854 if (sample_overlap(event, pdata, data->raw_size)) 854 if (sample_overlap(event, pdata, data->raw_size))
855 return -EFAULT; 855 return -EFAULT;
856 856
857 data->raw_data = (void *) pdata; 857 data->raw_data = (void *) pdata;
858 858
859 array = (void *)array + data->raw_size + sizeof(u32); 859 array = (void *)array + data->raw_size + sizeof(u32);
860 } 860 }
861 861
862 if (type & PERF_SAMPLE_BRANCH_STACK) { 862 if (type & PERF_SAMPLE_BRANCH_STACK) {
863 u64 sz; 863 u64 sz;
864 864
865 data->branch_stack = (struct branch_stack *)array; 865 data->branch_stack = (struct branch_stack *)array;
866 array++; /* nr */ 866 array++; /* nr */
867 867
868 sz = data->branch_stack->nr * sizeof(struct branch_entry); 868 sz = data->branch_stack->nr * sizeof(struct branch_entry);
869 sz /= sizeof(u64); 869 sz /= sizeof(u64);
870 array += sz; 870 array += sz;
871 } 871 }
872 return 0; 872 return 0;
873 } 873 }
874 874
875 int perf_event__synthesize_sample(union perf_event *event, u64 type, 875 int perf_event__synthesize_sample(union perf_event *event, u64 type,
876 const struct perf_sample *sample, 876 const struct perf_sample *sample,
877 bool swapped) 877 bool swapped)
878 { 878 {
879 u64 *array; 879 u64 *array;
880 880
881 /* 881 /*
882 * used for cross-endian analysis. See git commit 65014ab3 882 * used for cross-endian analysis. See git commit 65014ab3
883 * for why this goofiness is needed. 883 * for why this goofiness is needed.
884 */ 884 */
885 union u64_swap u; 885 union u64_swap u;
886 886
887 array = event->sample.array; 887 array = event->sample.array;
888 888
889 if (type & PERF_SAMPLE_IP) { 889 if (type & PERF_SAMPLE_IP) {
890 event->ip.ip = sample->ip; 890 event->ip.ip = sample->ip;
891 array++; 891 array++;
892 } 892 }
893 893
894 if (type & PERF_SAMPLE_TID) { 894 if (type & PERF_SAMPLE_TID) {
895 u.val32[0] = sample->pid; 895 u.val32[0] = sample->pid;
896 u.val32[1] = sample->tid; 896 u.val32[1] = sample->tid;
897 if (swapped) { 897 if (swapped) {
898 /* 898 /*
899 * Inverse of what is done in perf_event__parse_sample 899 * Inverse of what is done in perf_evsel__parse_sample
900 */ 900 */
901 u.val32[0] = bswap_32(u.val32[0]); 901 u.val32[0] = bswap_32(u.val32[0]);
902 u.val32[1] = bswap_32(u.val32[1]); 902 u.val32[1] = bswap_32(u.val32[1]);
903 u.val64 = bswap_64(u.val64); 903 u.val64 = bswap_64(u.val64);
904 } 904 }
905 905
906 *array = u.val64; 906 *array = u.val64;
907 array++; 907 array++;
908 } 908 }
909 909
910 if (type & PERF_SAMPLE_TIME) { 910 if (type & PERF_SAMPLE_TIME) {
911 *array = sample->time; 911 *array = sample->time;
912 array++; 912 array++;
913 } 913 }
914 914
915 if (type & PERF_SAMPLE_ADDR) { 915 if (type & PERF_SAMPLE_ADDR) {
916 *array = sample->addr; 916 *array = sample->addr;
917 array++; 917 array++;
918 } 918 }
919 919
920 if (type & PERF_SAMPLE_ID) { 920 if (type & PERF_SAMPLE_ID) {
921 *array = sample->id; 921 *array = sample->id;
922 array++; 922 array++;
923 } 923 }
924 924
925 if (type & PERF_SAMPLE_STREAM_ID) { 925 if (type & PERF_SAMPLE_STREAM_ID) {
926 *array = sample->stream_id; 926 *array = sample->stream_id;
927 array++; 927 array++;
928 } 928 }
929 929
930 if (type & PERF_SAMPLE_CPU) { 930 if (type & PERF_SAMPLE_CPU) {
931 u.val32[0] = sample->cpu; 931 u.val32[0] = sample->cpu;
932 if (swapped) { 932 if (swapped) {
933 /* 933 /*
934 * Inverse of what is done in perf_event__parse_sample 934 * Inverse of what is done in perf_evsel__parse_sample
935 */ 935 */
936 u.val32[0] = bswap_32(u.val32[0]); 936 u.val32[0] = bswap_32(u.val32[0]);
937 u.val64 = bswap_64(u.val64); 937 u.val64 = bswap_64(u.val64);
938 } 938 }
939 *array = u.val64; 939 *array = u.val64;
940 array++; 940 array++;
941 } 941 }
942 942
943 if (type & PERF_SAMPLE_PERIOD) { 943 if (type & PERF_SAMPLE_PERIOD) {
944 *array = sample->period; 944 *array = sample->period;
945 array++; 945 array++;
946 } 946 }
947 947
948 return 0; 948 return 0;
949 } 949 }
tools/perf/util/evsel.h
1 #ifndef __PERF_EVSEL_H 1 #ifndef __PERF_EVSEL_H
2 #define __PERF_EVSEL_H 1 2 #define __PERF_EVSEL_H 1
3 3
4 #include <linux/list.h> 4 #include <linux/list.h>
5 #include <stdbool.h> 5 #include <stdbool.h>
6 #include "../../../include/linux/perf_event.h" 6 #include "../../../include/linux/perf_event.h"
7 #include "types.h" 7 #include "types.h"
8 #include "xyarray.h" 8 #include "xyarray.h"
9 #include "cgroup.h" 9 #include "cgroup.h"
10 #include "hist.h" 10 #include "hist.h"
11 11
12 struct perf_counts_values { 12 struct perf_counts_values {
13 union { 13 union {
14 struct { 14 struct {
15 u64 val; 15 u64 val;
16 u64 ena; 16 u64 ena;
17 u64 run; 17 u64 run;
18 }; 18 };
19 u64 values[3]; 19 u64 values[3];
20 }; 20 };
21 }; 21 };
22 22
23 struct perf_counts { 23 struct perf_counts {
24 s8 scaled; 24 s8 scaled;
25 struct perf_counts_values aggr; 25 struct perf_counts_values aggr;
26 struct perf_counts_values cpu[]; 26 struct perf_counts_values cpu[];
27 }; 27 };
28 28
29 struct perf_evsel; 29 struct perf_evsel;
30 30
31 /* 31 /*
32 * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are 32 * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
33 * more than one entry in the evlist. 33 * more than one entry in the evlist.
34 */ 34 */
35 struct perf_sample_id { 35 struct perf_sample_id {
36 struct hlist_node node; 36 struct hlist_node node;
37 u64 id; 37 u64 id;
38 struct perf_evsel *evsel; 38 struct perf_evsel *evsel;
39 }; 39 };
40 40
41 /** struct perf_evsel - event selector 41 /** struct perf_evsel - event selector
42 * 42 *
43 * @name - Can be set to retain the original event name passed by the user, 43 * @name - Can be set to retain the original event name passed by the user,
44 * so that when showing results in tools such as 'perf stat', we 44 * so that when showing results in tools such as 'perf stat', we
45 * show the name used, not some alias. 45 * show the name used, not some alias.
46 */ 46 */
47 struct perf_evsel { 47 struct perf_evsel {
48 struct list_head node; 48 struct list_head node;
49 struct perf_event_attr attr; 49 struct perf_event_attr attr;
50 char *filter; 50 char *filter;
51 struct xyarray *fd; 51 struct xyarray *fd;
52 struct xyarray *sample_id; 52 struct xyarray *sample_id;
53 u64 *id; 53 u64 *id;
54 struct perf_counts *counts; 54 struct perf_counts *counts;
55 int idx; 55 int idx;
56 int ids; 56 int ids;
57 struct hists hists; 57 struct hists hists;
58 char *name; 58 char *name;
59 union { 59 union {
60 void *priv; 60 void *priv;
61 off_t id_offset; 61 off_t id_offset;
62 }; 62 };
63 struct cgroup_sel *cgrp; 63 struct cgroup_sel *cgrp;
64 struct { 64 struct {
65 void *func; 65 void *func;
66 void *data; 66 void *data;
67 } handler; 67 } handler;
68 unsigned int sample_size; 68 unsigned int sample_size;
69 bool supported; 69 bool supported;
70 }; 70 };
71 71
72 struct cpu_map; 72 struct cpu_map;
73 struct thread_map; 73 struct thread_map;
74 struct perf_evlist; 74 struct perf_evlist;
75 struct perf_record_opts; 75 struct perf_record_opts;
76 76
77 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 77 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
78 void perf_evsel__init(struct perf_evsel *evsel, 78 void perf_evsel__init(struct perf_evsel *evsel,
79 struct perf_event_attr *attr, int idx); 79 struct perf_event_attr *attr, int idx);
80 void perf_evsel__exit(struct perf_evsel *evsel); 80 void perf_evsel__exit(struct perf_evsel *evsel);
81 void perf_evsel__delete(struct perf_evsel *evsel); 81 void perf_evsel__delete(struct perf_evsel *evsel);
82 82
83 void perf_evsel__config(struct perf_evsel *evsel, 83 void perf_evsel__config(struct perf_evsel *evsel,
84 struct perf_record_opts *opts, 84 struct perf_record_opts *opts,
85 struct perf_evsel *first); 85 struct perf_evsel *first);
86 86
87 bool perf_evsel__is_cache_op_valid(u8 type, u8 op); 87 bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
88 88
89 #define PERF_EVSEL__MAX_ALIASES 8 89 #define PERF_EVSEL__MAX_ALIASES 8
90 90
91 extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] 91 extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
92 [PERF_EVSEL__MAX_ALIASES]; 92 [PERF_EVSEL__MAX_ALIASES];
93 extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] 93 extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
94 [PERF_EVSEL__MAX_ALIASES]; 94 [PERF_EVSEL__MAX_ALIASES];
95 const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] 95 const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
96 [PERF_EVSEL__MAX_ALIASES]; 96 [PERF_EVSEL__MAX_ALIASES];
97 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, 97 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
98 char *bf, size_t size); 98 char *bf, size_t size);
99 const char *perf_evsel__name(struct perf_evsel *evsel); 99 const char *perf_evsel__name(struct perf_evsel *evsel);
100 100
101 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 101 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
102 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 102 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
103 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 103 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
104 void perf_evsel__free_fd(struct perf_evsel *evsel); 104 void perf_evsel__free_fd(struct perf_evsel *evsel);
105 void perf_evsel__free_id(struct perf_evsel *evsel); 105 void perf_evsel__free_id(struct perf_evsel *evsel);
106 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 106 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
107 107
108 int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 108 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
109 struct cpu_map *cpus, bool group, 109 struct cpu_map *cpus, bool group,
110 struct xyarray *group_fds); 110 struct xyarray *group_fds);
111 int perf_evsel__open_per_thread(struct perf_evsel *evsel, 111 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
112 struct thread_map *threads, bool group, 112 struct thread_map *threads, bool group,
113 struct xyarray *group_fds); 113 struct xyarray *group_fds);
114 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 114 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
115 struct thread_map *threads, bool group, 115 struct thread_map *threads, bool group,
116 struct xyarray *group_fds); 116 struct xyarray *group_fds);
117 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); 117 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
118 118
119 #define perf_evsel__match(evsel, t, c) \ 119 #define perf_evsel__match(evsel, t, c) \
120 (evsel->attr.type == PERF_TYPE_##t && \ 120 (evsel->attr.type == PERF_TYPE_##t && \
121 evsel->attr.config == PERF_COUNT_##c) 121 evsel->attr.config == PERF_COUNT_##c)
122 122
123 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 123 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
124 int cpu, int thread, bool scale); 124 int cpu, int thread, bool scale);
125 125
126 /** 126 /**
127 * perf_evsel__read_on_cpu - Read out the results on a CPU and thread 127 * perf_evsel__read_on_cpu - Read out the results on a CPU and thread
128 * 128 *
129 * @evsel - event selector to read value 129 * @evsel - event selector to read value
130 * @cpu - CPU of interest 130 * @cpu - CPU of interest
131 * @thread - thread of interest 131 * @thread - thread of interest
132 */ 132 */
133 static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel, 133 static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
134 int cpu, int thread) 134 int cpu, int thread)
135 { 135 {
136 return __perf_evsel__read_on_cpu(evsel, cpu, thread, false); 136 return __perf_evsel__read_on_cpu(evsel, cpu, thread, false);
137 } 137 }
138 138
139 /** 139 /**
140 * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled 140 * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled
141 * 141 *
142 * @evsel - event selector to read value 142 * @evsel - event selector to read value
143 * @cpu - CPU of interest 143 * @cpu - CPU of interest
144 * @thread - thread of interest 144 * @thread - thread of interest
145 */ 145 */
146 static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel, 146 static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
147 int cpu, int thread) 147 int cpu, int thread)
148 { 148 {
149 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); 149 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
150 } 150 }
151 151
152 int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads, 152 int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
153 bool scale); 153 bool scale);
154 154
155 /** 155 /**
156 * perf_evsel__read - Read the aggregate results on all CPUs 156 * perf_evsel__read - Read the aggregate results on all CPUs
157 * 157 *
158 * @evsel - event selector to read value 158 * @evsel - event selector to read value
159 * @ncpus - Number of cpus affected, from zero 159 * @ncpus - Number of cpus affected, from zero
160 * @nthreads - Number of threads affected, from zero 160 * @nthreads - Number of threads affected, from zero
161 */ 161 */
162 static inline int perf_evsel__read(struct perf_evsel *evsel, 162 static inline int perf_evsel__read(struct perf_evsel *evsel,
163 int ncpus, int nthreads) 163 int ncpus, int nthreads)
164 { 164 {
165 return __perf_evsel__read(evsel, ncpus, nthreads, false); 165 return __perf_evsel__read(evsel, ncpus, nthreads, false);
166 } 166 }
167 167
168 /** 168 /**
169 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled 169 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
170 * 170 *
171 * @evsel - event selector to read value 171 * @evsel - event selector to read value
172 * @ncpus - Number of cpus affected, from zero 172 * @ncpus - Number of cpus affected, from zero
173 * @nthreads - Number of threads affected, from zero 173 * @nthreads - Number of threads affected, from zero
174 */ 174 */
175 static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, 175 static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
176 int ncpus, int nthreads) 176 int ncpus, int nthreads)
177 { 177 {
178 return __perf_evsel__read(evsel, ncpus, nthreads, true); 178 return __perf_evsel__read(evsel, ncpus, nthreads, true);
179 } 179 }
180 180
181 void hists__init(struct hists *hists); 181 void hists__init(struct hists *hists);
182 182
183 int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
184 struct perf_sample *sample, bool swapped);
183 #endif /* __PERF_EVSEL_H */ 185 #endif /* __PERF_EVSEL_H */
184 186