perf evlist: Move perf_evlist__config() to a new source file
[deliverable/linux.git] / tools / perf / util / evlist.c
CommitLineData
f8a95309
ACM
1/*
2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
5 * copyright notes.
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
a8c9ae18 9#include "util.h"
85c66be1 10#include <lk/debugfs.h>
5c581041 11#include <poll.h>
f8a95309
ACM
12#include "cpumap.h"
13#include "thread_map.h"
12864b31 14#include "target.h"
361c99a6
ACM
15#include "evlist.h"
16#include "evsel.h"
e3e1a54f 17#include "debug.h"
35b9d88e 18#include <unistd.h>
361c99a6 19
50d08e47
ACM
20#include "parse-events.h"
21
f8a95309
ACM
22#include <sys/mman.h>
23
70db7533
ACM
24#include <linux/bitops.h>
25#include <linux/hash.h>
26
f8a95309 27#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
a91e5431 28#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
f8a95309 29
7e2ed097
ACM
30void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
31 struct thread_map *threads)
ef1d1af2
ACM
32{
33 int i;
34
35 for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
36 INIT_HLIST_HEAD(&evlist->heads[i]);
37 INIT_LIST_HEAD(&evlist->entries);
7e2ed097 38 perf_evlist__set_maps(evlist, cpus, threads);
35b9d88e 39 evlist->workload.pid = -1;
ef1d1af2
ACM
40}
41
334fe7a3 42struct perf_evlist *perf_evlist__new(void)
361c99a6
ACM
43{
44 struct perf_evlist *evlist = zalloc(sizeof(*evlist));
45
ef1d1af2 46 if (evlist != NULL)
334fe7a3 47 perf_evlist__init(evlist, NULL, NULL);
361c99a6
ACM
48
49 return evlist;
50}
51
52static void perf_evlist__purge(struct perf_evlist *evlist)
53{
54 struct perf_evsel *pos, *n;
55
56 list_for_each_entry_safe(pos, n, &evlist->entries, node) {
57 list_del_init(&pos->node);
58 perf_evsel__delete(pos);
59 }
60
61 evlist->nr_entries = 0;
62}
63
ef1d1af2 64void perf_evlist__exit(struct perf_evlist *evlist)
361c99a6 65{
70db7533 66 free(evlist->mmap);
5c581041 67 free(evlist->pollfd);
ef1d1af2
ACM
68 evlist->mmap = NULL;
69 evlist->pollfd = NULL;
70}
71
72void perf_evlist__delete(struct perf_evlist *evlist)
73{
74 perf_evlist__purge(evlist);
75 perf_evlist__exit(evlist);
361c99a6
ACM
76 free(evlist);
77}
78
79void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
80{
81 list_add_tail(&entry->node, &evlist->entries);
82 ++evlist->nr_entries;
83}
84
0529bc1f
JO
85void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
86 struct list_head *list,
87 int nr_entries)
50d08e47
ACM
88{
89 list_splice_tail(list, &evlist->entries);
90 evlist->nr_entries += nr_entries;
91}
92
63dab225
ACM
93void __perf_evlist__set_leader(struct list_head *list)
94{
95 struct perf_evsel *evsel, *leader;
96
97 leader = list_entry(list->next, struct perf_evsel, node);
97f63e4a
NK
98 evsel = list_entry(list->prev, struct perf_evsel, node);
99
100 leader->nr_members = evsel->idx - leader->idx + 1;
63dab225
ACM
101
102 list_for_each_entry(evsel, list, node) {
74b2133d 103 evsel->leader = leader;
63dab225
ACM
104 }
105}
106
107void perf_evlist__set_leader(struct perf_evlist *evlist)
6a4bb04c 108{
97f63e4a
NK
109 if (evlist->nr_entries) {
110 evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
63dab225 111 __perf_evlist__set_leader(&evlist->entries);
97f63e4a 112 }
6a4bb04c
JO
113}
114
361c99a6
ACM
115int perf_evlist__add_default(struct perf_evlist *evlist)
116{
117 struct perf_event_attr attr = {
118 .type = PERF_TYPE_HARDWARE,
119 .config = PERF_COUNT_HW_CPU_CYCLES,
120 };
1aed2671
JR
121 struct perf_evsel *evsel;
122
123 event_attr_init(&attr);
361c99a6 124
1aed2671 125 evsel = perf_evsel__new(&attr, 0);
361c99a6 126 if (evsel == NULL)
cc2d86b0
SE
127 goto error;
128
129 /* use strdup() because free(evsel) assumes name is allocated */
130 evsel->name = strdup("cycles");
131 if (!evsel->name)
132 goto error_free;
361c99a6
ACM
133
134 perf_evlist__add(evlist, evsel);
135 return 0;
cc2d86b0
SE
136error_free:
137 perf_evsel__delete(evsel);
138error:
139 return -ENOMEM;
361c99a6 140}
5c581041 141
e60fc847
ACM
142static int perf_evlist__add_attrs(struct perf_evlist *evlist,
143 struct perf_event_attr *attrs, size_t nr_attrs)
50d08e47
ACM
144{
145 struct perf_evsel *evsel, *n;
146 LIST_HEAD(head);
147 size_t i;
148
149 for (i = 0; i < nr_attrs; i++) {
150 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
151 if (evsel == NULL)
152 goto out_delete_partial_list;
153 list_add_tail(&evsel->node, &head);
154 }
155
156 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
157
158 return 0;
159
160out_delete_partial_list:
161 list_for_each_entry_safe(evsel, n, &head, node)
162 perf_evsel__delete(evsel);
163 return -1;
164}
165
79695e1b
ACM
166int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
167 struct perf_event_attr *attrs, size_t nr_attrs)
168{
169 size_t i;
170
171 for (i = 0; i < nr_attrs; i++)
172 event_attr_init(attrs + i);
173
174 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
175}
176
da378962
ACM
177struct perf_evsel *
178perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
ee29be62
ACM
179{
180 struct perf_evsel *evsel;
181
182 list_for_each_entry(evsel, &evlist->entries, node) {
183 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
184 (int)evsel->attr.config == id)
185 return evsel;
186 }
187
188 return NULL;
189}
190
39876e7d
ACM
191int perf_evlist__add_newtp(struct perf_evlist *evlist,
192 const char *sys, const char *name, void *handler)
193{
194 struct perf_evsel *evsel;
195
196 evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
197 if (evsel == NULL)
198 return -1;
199
200 evsel->handler.func = handler;
201 perf_evlist__add(evlist, evsel);
202 return 0;
203}
204
4152ab37
ACM
205void perf_evlist__disable(struct perf_evlist *evlist)
206{
207 int cpu, thread;
208 struct perf_evsel *pos;
b3a319d5
NK
209 int nr_cpus = cpu_map__nr(evlist->cpus);
210 int nr_threads = thread_map__nr(evlist->threads);
4152ab37 211
b3a319d5 212 for (cpu = 0; cpu < nr_cpus; cpu++) {
4152ab37 213 list_for_each_entry(pos, &evlist->entries, node) {
823254ed 214 if (!perf_evsel__is_group_leader(pos))
3fe4430d 215 continue;
b3a319d5 216 for (thread = 0; thread < nr_threads; thread++)
55da8005
NK
217 ioctl(FD(pos, cpu, thread),
218 PERF_EVENT_IOC_DISABLE, 0);
4152ab37
ACM
219 }
220 }
221}
222
764e16a3
DA
223void perf_evlist__enable(struct perf_evlist *evlist)
224{
225 int cpu, thread;
226 struct perf_evsel *pos;
b3a319d5
NK
227 int nr_cpus = cpu_map__nr(evlist->cpus);
228 int nr_threads = thread_map__nr(evlist->threads);
764e16a3 229
b3a319d5 230 for (cpu = 0; cpu < nr_cpus; cpu++) {
764e16a3 231 list_for_each_entry(pos, &evlist->entries, node) {
823254ed 232 if (!perf_evsel__is_group_leader(pos))
3fe4430d 233 continue;
b3a319d5 234 for (thread = 0; thread < nr_threads; thread++)
55da8005
NK
235 ioctl(FD(pos, cpu, thread),
236 PERF_EVENT_IOC_ENABLE, 0);
764e16a3
DA
237 }
238 }
239}
240
806fb630 241static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
5c581041 242{
b3a319d5
NK
243 int nr_cpus = cpu_map__nr(evlist->cpus);
244 int nr_threads = thread_map__nr(evlist->threads);
245 int nfds = nr_cpus * nr_threads * evlist->nr_entries;
5c581041
ACM
246 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
247 return evlist->pollfd != NULL ? 0 : -ENOMEM;
248}
70082dd9
ACM
249
250void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
251{
252 fcntl(fd, F_SETFL, O_NONBLOCK);
253 evlist->pollfd[evlist->nr_fds].fd = fd;
254 evlist->pollfd[evlist->nr_fds].events = POLLIN;
255 evlist->nr_fds++;
256}
70db7533 257
a91e5431
ACM
258static void perf_evlist__id_hash(struct perf_evlist *evlist,
259 struct perf_evsel *evsel,
260 int cpu, int thread, u64 id)
3d3b5e95
ACM
261{
262 int hash;
263 struct perf_sample_id *sid = SID(evsel, cpu, thread);
264
265 sid->id = id;
266 sid->evsel = evsel;
267 hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
268 hlist_add_head(&sid->node, &evlist->heads[hash]);
269}
270
a91e5431
ACM
271void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
272 int cpu, int thread, u64 id)
273{
274 perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
275 evsel->id[evsel->ids++] = id;
276}
277
278static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
279 struct perf_evsel *evsel,
280 int cpu, int thread, int fd)
f8a95309 281{
f8a95309 282 u64 read_data[4] = { 0, };
3d3b5e95 283 int id_idx = 1; /* The first entry is the counter value */
e2b5abe0
JO
284 u64 id;
285 int ret;
286
287 ret = ioctl(fd, PERF_EVENT_IOC_ID, &id);
288 if (!ret)
289 goto add;
290
291 if (errno != ENOTTY)
292 return -1;
293
294 /* Legacy way to get event id.. All hail to old kernels! */
f8a95309 295
c4861afe
JO
296 /*
297 * This way does not work with group format read, so bail
298 * out in that case.
299 */
300 if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP)
301 return -1;
302
f8a95309
ACM
303 if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
304 read(fd, &read_data, sizeof(read_data)) == -1)
305 return -1;
306
307 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
308 ++id_idx;
309 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
310 ++id_idx;
311
e2b5abe0
JO
312 id = read_data[id_idx];
313
314 add:
315 perf_evlist__id_add(evlist, evsel, cpu, thread, id);
f8a95309
ACM
316 return 0;
317}
318
932a3594 319struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
70db7533
ACM
320{
321 struct hlist_head *head;
70db7533
ACM
322 struct perf_sample_id *sid;
323 int hash;
324
70db7533
ACM
325 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
326 head = &evlist->heads[hash];
327
b67bfe0d 328 hlist_for_each_entry(sid, head, node)
70db7533 329 if (sid->id == id)
932a3594
JO
330 return sid;
331
332 return NULL;
333}
334
335struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
336{
337 struct perf_sample_id *sid;
338
339 if (evlist->nr_entries == 1)
340 return perf_evlist__first(evlist);
341
342 sid = perf_evlist__id2sid(evlist, id);
343 if (sid)
344 return sid->evsel;
30e68bcc
NK
345
346 if (!perf_evlist__sample_id_all(evlist))
0c21f736 347 return perf_evlist__first(evlist);
30e68bcc 348
70db7533
ACM
349 return NULL;
350}
04391deb 351
aece948f 352union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
04391deb 353{
aece948f 354 struct perf_mmap *md = &evlist->mmap[idx];
04391deb
ACM
355 unsigned int head = perf_mmap__read_head(md);
356 unsigned int old = md->prev;
357 unsigned char *data = md->base + page_size;
8115d60c 358 union perf_event *event = NULL;
04391deb 359
7bb41152 360 if (evlist->overwrite) {
04391deb 361 /*
7bb41152
ACM
362 * If we're further behind than half the buffer, there's a chance
363 * the writer will bite our tail and mess up the samples under us.
364 *
365 * If we somehow ended up ahead of the head, we got messed up.
366 *
367 * In either case, truncate and restart at head.
04391deb 368 */
7bb41152
ACM
369 int diff = head - old;
370 if (diff > md->mask / 2 || diff < 0) {
371 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
372
373 /*
374 * head points to a known good entry, start there.
375 */
376 old = head;
377 }
04391deb
ACM
378 }
379
380 if (old != head) {
381 size_t size;
382
8115d60c 383 event = (union perf_event *)&data[old & md->mask];
04391deb
ACM
384 size = event->header.size;
385
386 /*
387 * Event straddles the mmap boundary -- header should always
388 * be inside due to u64 alignment of output.
389 */
390 if ((old & md->mask) + size != ((old + size) & md->mask)) {
391 unsigned int offset = old;
392 unsigned int len = min(sizeof(*event), size), cpy;
0479b8b9 393 void *dst = &md->event_copy;
04391deb
ACM
394
395 do {
396 cpy = min(md->mask + 1 - (offset & md->mask), len);
397 memcpy(dst, &data[offset & md->mask], cpy);
398 offset += cpy;
399 dst += cpy;
400 len -= cpy;
401 } while (len);
402
0479b8b9 403 event = &md->event_copy;
04391deb
ACM
404 }
405
406 old += size;
407 }
408
409 md->prev = old;
7bb41152
ACM
410
411 if (!evlist->overwrite)
412 perf_mmap__write_tail(md, old);
413
04391deb
ACM
414 return event;
415}
f8a95309 416
93edcbd9
AH
417static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
418{
419 if (evlist->mmap[idx].base != NULL) {
420 munmap(evlist->mmap[idx].base, evlist->mmap_len);
421 evlist->mmap[idx].base = NULL;
422 }
423}
424
7e2ed097 425void perf_evlist__munmap(struct perf_evlist *evlist)
f8a95309 426{
aece948f 427 int i;
f8a95309 428
93edcbd9
AH
429 for (i = 0; i < evlist->nr_mmaps; i++)
430 __perf_evlist__munmap(evlist, i);
aece948f
ACM
431
432 free(evlist->mmap);
433 evlist->mmap = NULL;
f8a95309
ACM
434}
435
806fb630 436static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
f8a95309 437{
a14bb7a6 438 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
ec1e7e43 439 if (cpu_map__empty(evlist->cpus))
b3a319d5 440 evlist->nr_mmaps = thread_map__nr(evlist->threads);
aece948f 441 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
f8a95309
ACM
442 return evlist->mmap != NULL ? 0 : -ENOMEM;
443}
444
bccdaba0 445static int __perf_evlist__mmap(struct perf_evlist *evlist,
aece948f 446 int idx, int prot, int mask, int fd)
f8a95309 447{
aece948f
ACM
448 evlist->mmap[idx].prev = 0;
449 evlist->mmap[idx].mask = mask;
450 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
f8a95309 451 MAP_SHARED, fd, 0);
301b195d
NE
452 if (evlist->mmap[idx].base == MAP_FAILED) {
453 evlist->mmap[idx].base = NULL;
f8a95309 454 return -1;
301b195d 455 }
f8a95309
ACM
456
457 perf_evlist__add_pollfd(evlist, fd);
458 return 0;
459}
460
aece948f
ACM
461static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask)
462{
463 struct perf_evsel *evsel;
464 int cpu, thread;
b3a319d5
NK
465 int nr_cpus = cpu_map__nr(evlist->cpus);
466 int nr_threads = thread_map__nr(evlist->threads);
aece948f 467
e3e1a54f 468 pr_debug2("perf event ring buffer mmapped per cpu\n");
b3a319d5 469 for (cpu = 0; cpu < nr_cpus; cpu++) {
aece948f
ACM
470 int output = -1;
471
b3a319d5 472 for (thread = 0; thread < nr_threads; thread++) {
aece948f
ACM
473 list_for_each_entry(evsel, &evlist->entries, node) {
474 int fd = FD(evsel, cpu, thread);
475
476 if (output == -1) {
477 output = fd;
bccdaba0 478 if (__perf_evlist__mmap(evlist, cpu,
aece948f
ACM
479 prot, mask, output) < 0)
480 goto out_unmap;
481 } else {
482 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
483 goto out_unmap;
484 }
485
486 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
487 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
488 goto out_unmap;
489 }
490 }
491 }
492
493 return 0;
494
495out_unmap:
93edcbd9
AH
496 for (cpu = 0; cpu < nr_cpus; cpu++)
497 __perf_evlist__munmap(evlist, cpu);
aece948f
ACM
498 return -1;
499}
500
501static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask)
502{
503 struct perf_evsel *evsel;
504 int thread;
b3a319d5 505 int nr_threads = thread_map__nr(evlist->threads);
aece948f 506
e3e1a54f 507 pr_debug2("perf event ring buffer mmapped per thread\n");
b3a319d5 508 for (thread = 0; thread < nr_threads; thread++) {
aece948f
ACM
509 int output = -1;
510
511 list_for_each_entry(evsel, &evlist->entries, node) {
512 int fd = FD(evsel, 0, thread);
513
514 if (output == -1) {
515 output = fd;
bccdaba0 516 if (__perf_evlist__mmap(evlist, thread,
aece948f
ACM
517 prot, mask, output) < 0)
518 goto out_unmap;
519 } else {
520 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
521 goto out_unmap;
522 }
523
524 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
525 perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
526 goto out_unmap;
527 }
528 }
529
530 return 0;
531
532out_unmap:
93edcbd9
AH
533 for (thread = 0; thread < nr_threads; thread++)
534 __perf_evlist__munmap(evlist, thread);
aece948f
ACM
535 return -1;
536}
537
f8a95309
ACM
538/** perf_evlist__mmap - Create per cpu maps to receive events
539 *
540 * @evlist - list of events
f8a95309
ACM
541 * @pages - map length in pages
542 * @overwrite - overwrite older events?
543 *
544 * If overwrite is false the user needs to signal event consuption using:
545 *
546 * struct perf_mmap *m = &evlist->mmap[cpu];
547 * unsigned int head = perf_mmap__read_head(m);
548 *
549 * perf_mmap__write_tail(m, head)
7e2ed097
ACM
550 *
551 * Using perf_evlist__read_on_cpu does this automatically.
f8a95309 552 */
50a682ce
ACM
553int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
554 bool overwrite)
f8a95309 555{
aece948f 556 struct perf_evsel *evsel;
7e2ed097
ACM
557 const struct cpu_map *cpus = evlist->cpus;
558 const struct thread_map *threads = evlist->threads;
50a682ce
ACM
559 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
560
561 /* 512 kiB: default amount of unprivileged mlocked memory */
562 if (pages == UINT_MAX)
563 pages = (512 * 1024) / page_size;
41d0d933
NE
564 else if (!is_power_of_2(pages))
565 return -EINVAL;
50a682ce
ACM
566
567 mask = pages * page_size - 1;
f8a95309 568
7e2ed097 569 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
f8a95309
ACM
570 return -ENOMEM;
571
7e2ed097 572 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
f8a95309
ACM
573 return -ENOMEM;
574
575 evlist->overwrite = overwrite;
576 evlist->mmap_len = (pages + 1) * page_size;
f8a95309
ACM
577
578 list_for_each_entry(evsel, &evlist->entries, node) {
579 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
a91e5431 580 evsel->sample_id == NULL &&
a14bb7a6 581 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
f8a95309 582 return -ENOMEM;
f8a95309
ACM
583 }
584
ec1e7e43 585 if (cpu_map__empty(cpus))
aece948f 586 return perf_evlist__mmap_per_thread(evlist, prot, mask);
f8a95309 587
aece948f 588 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
f8a95309 589}
7e2ed097 590
b809ac10
NK
591int perf_evlist__create_maps(struct perf_evlist *evlist,
592 struct perf_target *target)
7e2ed097 593{
b809ac10
NK
594 evlist->threads = thread_map__new_str(target->pid, target->tid,
595 target->uid);
7e2ed097
ACM
596
597 if (evlist->threads == NULL)
598 return -1;
599
879d77d0 600 if (perf_target__has_task(target))
d67356e7 601 evlist->cpus = cpu_map__dummy_new();
d1cb9fce
NK
602 else if (!perf_target__has_cpu(target) && !target->uses_mmap)
603 evlist->cpus = cpu_map__dummy_new();
879d77d0
NK
604 else
605 evlist->cpus = cpu_map__new(target->cpu_list);
7e2ed097
ACM
606
607 if (evlist->cpus == NULL)
608 goto out_delete_threads;
609
610 return 0;
611
612out_delete_threads:
613 thread_map__delete(evlist->threads);
614 return -1;
615}
616
617void perf_evlist__delete_maps(struct perf_evlist *evlist)
618{
619 cpu_map__delete(evlist->cpus);
620 thread_map__delete(evlist->threads);
621 evlist->cpus = NULL;
622 evlist->threads = NULL;
623}
0a102479 624
1491a632 625int perf_evlist__apply_filters(struct perf_evlist *evlist)
0a102479 626{
0a102479 627 struct perf_evsel *evsel;
745cefc5
ACM
628 int err = 0;
629 const int ncpus = cpu_map__nr(evlist->cpus),
b3a319d5 630 nthreads = thread_map__nr(evlist->threads);
0a102479
FW
631
632 list_for_each_entry(evsel, &evlist->entries, node) {
745cefc5 633 if (evsel->filter == NULL)
0a102479 634 continue;
745cefc5
ACM
635
636 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
637 if (err)
638 break;
0a102479
FW
639 }
640
745cefc5
ACM
641 return err;
642}
643
644int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
645{
646 struct perf_evsel *evsel;
647 int err = 0;
648 const int ncpus = cpu_map__nr(evlist->cpus),
b3a319d5 649 nthreads = thread_map__nr(evlist->threads);
745cefc5
ACM
650
651 list_for_each_entry(evsel, &evlist->entries, node) {
652 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
653 if (err)
654 break;
655 }
656
657 return err;
0a102479 658}
74429964 659
0c21f736 660bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
74429964 661{
0c21f736 662 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
c2a70653
ACM
663
664 list_for_each_entry_continue(pos, &evlist->entries, node) {
665 if (first->attr.sample_type != pos->attr.sample_type)
666 return false;
74429964
FW
667 }
668
c2a70653 669 return true;
74429964
FW
670}
671
0c21f736 672u64 perf_evlist__sample_type(struct perf_evlist *evlist)
c2a70653 673{
0c21f736 674 struct perf_evsel *first = perf_evlist__first(evlist);
c2a70653
ACM
675 return first->attr.sample_type;
676}
677
9ede473c
JO
678bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
679{
680 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
681 u64 read_format = first->attr.read_format;
682 u64 sample_type = first->attr.sample_type;
683
684 list_for_each_entry_continue(pos, &evlist->entries, node) {
685 if (read_format != pos->attr.read_format)
686 return false;
687 }
688
689 /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */
690 if ((sample_type & PERF_SAMPLE_READ) &&
691 !(read_format & PERF_FORMAT_ID)) {
692 return false;
693 }
694
695 return true;
696}
697
698u64 perf_evlist__read_format(struct perf_evlist *evlist)
699{
700 struct perf_evsel *first = perf_evlist__first(evlist);
701 return first->attr.read_format;
702}
703
0c21f736 704u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
81e36bff 705{
0c21f736 706 struct perf_evsel *first = perf_evlist__first(evlist);
81e36bff
ACM
707 struct perf_sample *data;
708 u64 sample_type;
709 u16 size = 0;
710
81e36bff
ACM
711 if (!first->attr.sample_id_all)
712 goto out;
713
714 sample_type = first->attr.sample_type;
715
716 if (sample_type & PERF_SAMPLE_TID)
717 size += sizeof(data->tid) * 2;
718
719 if (sample_type & PERF_SAMPLE_TIME)
720 size += sizeof(data->time);
721
722 if (sample_type & PERF_SAMPLE_ID)
723 size += sizeof(data->id);
724
725 if (sample_type & PERF_SAMPLE_STREAM_ID)
726 size += sizeof(data->stream_id);
727
728 if (sample_type & PERF_SAMPLE_CPU)
729 size += sizeof(data->cpu) * 2;
730out:
731 return size;
732}
733
0c21f736 734bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
74429964 735{
0c21f736 736 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
c2a70653
ACM
737
738 list_for_each_entry_continue(pos, &evlist->entries, node) {
739 if (first->attr.sample_id_all != pos->attr.sample_id_all)
740 return false;
74429964
FW
741 }
742
c2a70653
ACM
743 return true;
744}
745
0c21f736 746bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
c2a70653 747{
0c21f736 748 struct perf_evsel *first = perf_evlist__first(evlist);
c2a70653 749 return first->attr.sample_id_all;
74429964 750}
81cce8de
ACM
751
752void perf_evlist__set_selected(struct perf_evlist *evlist,
753 struct perf_evsel *evsel)
754{
755 evlist->selected = evsel;
756}
727ab04e 757
a74b4b66
NK
758void perf_evlist__close(struct perf_evlist *evlist)
759{
760 struct perf_evsel *evsel;
761 int ncpus = cpu_map__nr(evlist->cpus);
762 int nthreads = thread_map__nr(evlist->threads);
763
764 list_for_each_entry_reverse(evsel, &evlist->entries, node)
765 perf_evsel__close(evsel, ncpus, nthreads);
766}
767
6a4bb04c 768int perf_evlist__open(struct perf_evlist *evlist)
727ab04e 769{
6a4bb04c 770 struct perf_evsel *evsel;
a74b4b66 771 int err;
727ab04e 772
727ab04e 773 list_for_each_entry(evsel, &evlist->entries, node) {
6a4bb04c 774 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
727ab04e
ACM
775 if (err < 0)
776 goto out_err;
777 }
778
779 return 0;
780out_err:
a74b4b66 781 perf_evlist__close(evlist);
41c21a68 782 errno = -err;
727ab04e
ACM
783 return err;
784}
35b9d88e
ACM
785
786int perf_evlist__prepare_workload(struct perf_evlist *evlist,
6ef73ec4 787 struct perf_target *target,
55e162ea
NK
788 const char *argv[], bool pipe_output,
789 bool want_signal)
35b9d88e
ACM
790{
791 int child_ready_pipe[2], go_pipe[2];
792 char bf;
793
794 if (pipe(child_ready_pipe) < 0) {
795 perror("failed to create 'ready' pipe");
796 return -1;
797 }
798
799 if (pipe(go_pipe) < 0) {
800 perror("failed to create 'go' pipe");
801 goto out_close_ready_pipe;
802 }
803
804 evlist->workload.pid = fork();
805 if (evlist->workload.pid < 0) {
806 perror("failed to fork");
807 goto out_close_pipes;
808 }
809
810 if (!evlist->workload.pid) {
119fa3c9 811 if (pipe_output)
35b9d88e
ACM
812 dup2(2, 1);
813
0817df08
DA
814 signal(SIGTERM, SIG_DFL);
815
35b9d88e
ACM
816 close(child_ready_pipe[0]);
817 close(go_pipe[1]);
818 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
819
35b9d88e
ACM
820 /*
821 * Tell the parent we're ready to go
822 */
823 close(child_ready_pipe[1]);
824
825 /*
826 * Wait until the parent tells us to go.
827 */
828 if (read(go_pipe[0], &bf, 1) == -1)
829 perror("unable to read pipe");
830
831 execvp(argv[0], (char **)argv);
832
833 perror(argv[0]);
55e162ea
NK
834 if (want_signal)
835 kill(getppid(), SIGUSR1);
35b9d88e
ACM
836 exit(-1);
837 }
838
6ef73ec4 839 if (perf_target__none(target))
35b9d88e
ACM
840 evlist->threads->map[0] = evlist->workload.pid;
841
842 close(child_ready_pipe[1]);
843 close(go_pipe[0]);
844 /*
845 * wait for child to settle
846 */
847 if (read(child_ready_pipe[0], &bf, 1) == -1) {
848 perror("unable to read pipe");
849 goto out_close_pipes;
850 }
851
bcf3145f 852 fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
35b9d88e
ACM
853 evlist->workload.cork_fd = go_pipe[1];
854 close(child_ready_pipe[0]);
855 return 0;
856
857out_close_pipes:
858 close(go_pipe[0]);
859 close(go_pipe[1]);
860out_close_ready_pipe:
861 close(child_ready_pipe[0]);
862 close(child_ready_pipe[1]);
863 return -1;
864}
865
866int perf_evlist__start_workload(struct perf_evlist *evlist)
867{
868 if (evlist->workload.cork_fd > 0) {
b3824404 869 char bf = 0;
bcf3145f 870 int ret;
35b9d88e
ACM
871 /*
872 * Remove the cork, let it rip!
873 */
bcf3145f
NK
874 ret = write(evlist->workload.cork_fd, &bf, 1);
875 if (ret < 0)
876 perror("enable to write to pipe");
877
878 close(evlist->workload.cork_fd);
879 return ret;
35b9d88e
ACM
880 }
881
882 return 0;
883}
cb0b29e0 884
a3f698fe 885int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
0807d2d8 886 struct perf_sample *sample)
cb0b29e0 887{
0c21f736 888 struct perf_evsel *evsel = perf_evlist__first(evlist);
0807d2d8 889 return perf_evsel__parse_sample(evsel, event, sample);
cb0b29e0 890}
78f067b3
ACM
891
892size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
893{
894 struct perf_evsel *evsel;
895 size_t printed = 0;
896
897 list_for_each_entry(evsel, &evlist->entries, node) {
898 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
899 perf_evsel__name(evsel));
900 }
901
902 return printed + fprintf(fp, "\n");;
903}
This page took 0.135278 seconds and 5 git commands to generate.