1f8a95309SArnaldo Carvalho de Melo /* 2f8a95309SArnaldo Carvalho de Melo * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 3f8a95309SArnaldo Carvalho de Melo * 4f8a95309SArnaldo Carvalho de Melo * Parts came from builtin-{top,stat,record}.c, see those files for further 5f8a95309SArnaldo Carvalho de Melo * copyright notes. 6f8a95309SArnaldo Carvalho de Melo * 7f8a95309SArnaldo Carvalho de Melo * Released under the GPL v2. (and only v2, not any later version) 8f8a95309SArnaldo Carvalho de Melo */ 9a8c9ae18SArnaldo Carvalho de Melo #include "util.h" 1085c66be1SBorislav Petkov #include <lk/debugfs.h> 115c581041SArnaldo Carvalho de Melo #include <poll.h> 12f8a95309SArnaldo Carvalho de Melo #include "cpumap.h" 13f8a95309SArnaldo Carvalho de Melo #include "thread_map.h" 1412864b31SNamhyung Kim #include "target.h" 15361c99a6SArnaldo Carvalho de Melo #include "evlist.h" 16361c99a6SArnaldo Carvalho de Melo #include "evsel.h" 17e3e1a54fSAdrian Hunter #include "debug.h" 1835b9d88eSArnaldo Carvalho de Melo #include <unistd.h> 19361c99a6SArnaldo Carvalho de Melo 2050d08e47SArnaldo Carvalho de Melo #include "parse-events.h" 2150d08e47SArnaldo Carvalho de Melo 22f8a95309SArnaldo Carvalho de Melo #include <sys/mman.h> 23f8a95309SArnaldo Carvalho de Melo 2470db7533SArnaldo Carvalho de Melo #include <linux/bitops.h> 2570db7533SArnaldo Carvalho de Melo #include <linux/hash.h> 2670db7533SArnaldo Carvalho de Melo 27f8a95309SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 28a91e5431SArnaldo Carvalho de Melo #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 29f8a95309SArnaldo Carvalho de Melo 307e2ed097SArnaldo Carvalho de Melo void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 317e2ed097SArnaldo Carvalho de Melo struct thread_map *threads) 32361c99a6SArnaldo Carvalho de Melo { 3370db7533SArnaldo Carvalho de Melo int i; 3470db7533SArnaldo Carvalho de Melo 3570db7533SArnaldo Carvalho de Melo for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) 3670db7533SArnaldo Carvalho de Melo INIT_HLIST_HEAD(&evlist->heads[i]); 37361c99a6SArnaldo Carvalho de Melo INIT_LIST_HEAD(&evlist->entries); 387e2ed097SArnaldo Carvalho de Melo perf_evlist__set_maps(evlist, cpus, threads); 3935b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = -1; 40361c99a6SArnaldo Carvalho de Melo } 41361c99a6SArnaldo Carvalho de Melo 42334fe7a3SNamhyung Kim struct perf_evlist *perf_evlist__new(void) 43ef1d1af2SArnaldo Carvalho de Melo { 44ef1d1af2SArnaldo Carvalho de Melo struct perf_evlist *evlist = zalloc(sizeof(*evlist)); 45ef1d1af2SArnaldo Carvalho de Melo 46ef1d1af2SArnaldo Carvalho de Melo if (evlist != NULL) 47334fe7a3SNamhyung Kim perf_evlist__init(evlist, NULL, NULL); 48ef1d1af2SArnaldo Carvalho de Melo 49361c99a6SArnaldo Carvalho de Melo return evlist; 50361c99a6SArnaldo Carvalho de Melo } 51361c99a6SArnaldo Carvalho de Melo 5275562573SAdrian Hunter /** 5375562573SAdrian Hunter * perf_evlist__set_id_pos - set the positions of event ids. 5475562573SAdrian Hunter * @evlist: selected event list 5575562573SAdrian Hunter * 5675562573SAdrian Hunter * Events with compatible sample types all have the same id_pos 5775562573SAdrian Hunter * and is_pos. For convenience, put a copy on evlist. 5875562573SAdrian Hunter */ 5975562573SAdrian Hunter void perf_evlist__set_id_pos(struct perf_evlist *evlist) 6075562573SAdrian Hunter { 6175562573SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 6275562573SAdrian Hunter 6375562573SAdrian Hunter evlist->id_pos = first->id_pos; 6475562573SAdrian Hunter evlist->is_pos = first->is_pos; 6575562573SAdrian Hunter } 6675562573SAdrian Hunter 67361c99a6SArnaldo Carvalho de Melo static void perf_evlist__purge(struct perf_evlist *evlist) 68361c99a6SArnaldo Carvalho de Melo { 69361c99a6SArnaldo Carvalho de Melo struct perf_evsel *pos, *n; 70361c99a6SArnaldo Carvalho de Melo 71361c99a6SArnaldo Carvalho de Melo list_for_each_entry_safe(pos, n, &evlist->entries, node) { 72361c99a6SArnaldo Carvalho de Melo list_del_init(&pos->node); 73361c99a6SArnaldo Carvalho de Melo perf_evsel__delete(pos); 74361c99a6SArnaldo Carvalho de Melo } 75361c99a6SArnaldo Carvalho de Melo 76361c99a6SArnaldo Carvalho de Melo evlist->nr_entries = 0; 77361c99a6SArnaldo Carvalho de Melo } 78361c99a6SArnaldo Carvalho de Melo 79ef1d1af2SArnaldo Carvalho de Melo void perf_evlist__exit(struct perf_evlist *evlist) 80ef1d1af2SArnaldo Carvalho de Melo { 81ef1d1af2SArnaldo Carvalho de Melo free(evlist->mmap); 82ef1d1af2SArnaldo Carvalho de Melo free(evlist->pollfd); 83ef1d1af2SArnaldo Carvalho de Melo evlist->mmap = NULL; 84ef1d1af2SArnaldo Carvalho de Melo evlist->pollfd = NULL; 85ef1d1af2SArnaldo Carvalho de Melo } 86ef1d1af2SArnaldo Carvalho de Melo 87361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist) 88361c99a6SArnaldo Carvalho de Melo { 89361c99a6SArnaldo Carvalho de Melo perf_evlist__purge(evlist); 90ef1d1af2SArnaldo Carvalho de Melo perf_evlist__exit(evlist); 91361c99a6SArnaldo Carvalho de Melo free(evlist); 92361c99a6SArnaldo Carvalho de Melo } 93361c99a6SArnaldo Carvalho de Melo 94361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 95361c99a6SArnaldo Carvalho de Melo { 96361c99a6SArnaldo Carvalho de Melo list_add_tail(&entry->node, &evlist->entries); 9775562573SAdrian Hunter if (!evlist->nr_entries++) 9875562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 99361c99a6SArnaldo Carvalho de Melo } 100361c99a6SArnaldo Carvalho de Melo 1010529bc1fSJiri Olsa void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 10250d08e47SArnaldo Carvalho de Melo struct list_head *list, 10350d08e47SArnaldo Carvalho de Melo int nr_entries) 10450d08e47SArnaldo Carvalho de Melo { 10575562573SAdrian Hunter bool set_id_pos = !evlist->nr_entries; 10675562573SAdrian Hunter 10750d08e47SArnaldo Carvalho de Melo list_splice_tail(list, &evlist->entries); 10850d08e47SArnaldo Carvalho de Melo evlist->nr_entries += nr_entries; 10975562573SAdrian Hunter if (set_id_pos) 11075562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 11150d08e47SArnaldo Carvalho de Melo } 11250d08e47SArnaldo Carvalho de Melo 11363dab225SArnaldo Carvalho de Melo void __perf_evlist__set_leader(struct list_head *list) 11463dab225SArnaldo Carvalho de Melo { 11563dab225SArnaldo Carvalho de Melo struct perf_evsel *evsel, *leader; 11663dab225SArnaldo Carvalho de Melo 11763dab225SArnaldo Carvalho de Melo leader = list_entry(list->next, struct perf_evsel, node); 11897f63e4aSNamhyung Kim evsel = list_entry(list->prev, struct perf_evsel, node); 11997f63e4aSNamhyung Kim 12097f63e4aSNamhyung Kim leader->nr_members = evsel->idx - leader->idx + 1; 12163dab225SArnaldo Carvalho de Melo 12263dab225SArnaldo Carvalho de Melo list_for_each_entry(evsel, list, node) { 12363dab225SArnaldo Carvalho de Melo evsel->leader = leader; 12463dab225SArnaldo Carvalho de Melo } 12563dab225SArnaldo Carvalho de Melo } 12663dab225SArnaldo Carvalho de Melo 12763dab225SArnaldo Carvalho de Melo void perf_evlist__set_leader(struct perf_evlist *evlist) 1286a4bb04cSJiri Olsa { 12997f63e4aSNamhyung Kim if (evlist->nr_entries) { 13097f63e4aSNamhyung Kim evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; 13163dab225SArnaldo Carvalho de Melo __perf_evlist__set_leader(&evlist->entries); 1326a4bb04cSJiri Olsa } 13397f63e4aSNamhyung Kim } 1346a4bb04cSJiri Olsa 135361c99a6SArnaldo Carvalho de Melo int perf_evlist__add_default(struct perf_evlist *evlist) 136361c99a6SArnaldo Carvalho de Melo { 137361c99a6SArnaldo Carvalho de Melo struct perf_event_attr attr = { 138361c99a6SArnaldo Carvalho de Melo .type = PERF_TYPE_HARDWARE, 139361c99a6SArnaldo Carvalho de Melo .config = PERF_COUNT_HW_CPU_CYCLES, 140361c99a6SArnaldo Carvalho de Melo }; 1411aed2671SJoerg Roedel struct perf_evsel *evsel; 142361c99a6SArnaldo Carvalho de Melo 1431aed2671SJoerg Roedel event_attr_init(&attr); 1441aed2671SJoerg Roedel 1451aed2671SJoerg Roedel evsel = perf_evsel__new(&attr, 0); 146361c99a6SArnaldo Carvalho de Melo if (evsel == NULL) 147cc2d86b0SStephane Eranian goto error; 148cc2d86b0SStephane Eranian 149cc2d86b0SStephane Eranian /* use strdup() because free(evsel) assumes name is allocated */ 150cc2d86b0SStephane Eranian evsel->name = strdup("cycles"); 151cc2d86b0SStephane Eranian if (!evsel->name) 152cc2d86b0SStephane Eranian goto error_free; 153361c99a6SArnaldo Carvalho de Melo 154361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 155361c99a6SArnaldo Carvalho de Melo return 0; 156cc2d86b0SStephane Eranian error_free: 157cc2d86b0SStephane Eranian perf_evsel__delete(evsel); 158cc2d86b0SStephane Eranian error: 159cc2d86b0SStephane Eranian return -ENOMEM; 160361c99a6SArnaldo Carvalho de Melo } 1615c581041SArnaldo Carvalho de Melo 162e60fc847SArnaldo Carvalho de Melo static int perf_evlist__add_attrs(struct perf_evlist *evlist, 16350d08e47SArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 16450d08e47SArnaldo Carvalho de Melo { 16550d08e47SArnaldo Carvalho de Melo struct perf_evsel *evsel, *n; 16650d08e47SArnaldo Carvalho de Melo LIST_HEAD(head); 16750d08e47SArnaldo Carvalho de Melo size_t i; 16850d08e47SArnaldo Carvalho de Melo 16950d08e47SArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) { 17050d08e47SArnaldo Carvalho de Melo evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i); 17150d08e47SArnaldo Carvalho de Melo if (evsel == NULL) 17250d08e47SArnaldo Carvalho de Melo goto out_delete_partial_list; 17350d08e47SArnaldo Carvalho de Melo list_add_tail(&evsel->node, &head); 17450d08e47SArnaldo Carvalho de Melo } 17550d08e47SArnaldo Carvalho de Melo 17650d08e47SArnaldo Carvalho de Melo perf_evlist__splice_list_tail(evlist, &head, nr_attrs); 17750d08e47SArnaldo Carvalho de Melo 17850d08e47SArnaldo Carvalho de Melo return 0; 17950d08e47SArnaldo Carvalho de Melo 18050d08e47SArnaldo Carvalho de Melo out_delete_partial_list: 18150d08e47SArnaldo Carvalho de Melo list_for_each_entry_safe(evsel, n, &head, node) 18250d08e47SArnaldo Carvalho de Melo perf_evsel__delete(evsel); 18350d08e47SArnaldo Carvalho de Melo return -1; 18450d08e47SArnaldo Carvalho de Melo } 18550d08e47SArnaldo Carvalho de Melo 18679695e1bSArnaldo Carvalho de Melo int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 18779695e1bSArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 18879695e1bSArnaldo Carvalho de Melo { 18979695e1bSArnaldo Carvalho de Melo size_t i; 19079695e1bSArnaldo Carvalho de Melo 19179695e1bSArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) 19279695e1bSArnaldo Carvalho de Melo event_attr_init(attrs + i); 19379695e1bSArnaldo Carvalho de Melo 19479695e1bSArnaldo Carvalho de Melo return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 19579695e1bSArnaldo Carvalho de Melo } 19679695e1bSArnaldo Carvalho de Melo 197da378962SArnaldo Carvalho de Melo struct perf_evsel * 198ee29be62SArnaldo Carvalho de Melo perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 199ee29be62SArnaldo Carvalho de Melo { 200ee29be62SArnaldo Carvalho de Melo struct perf_evsel *evsel; 201ee29be62SArnaldo Carvalho de Melo 202ee29be62SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 203ee29be62SArnaldo Carvalho de Melo if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 204ee29be62SArnaldo Carvalho de Melo (int)evsel->attr.config == id) 205ee29be62SArnaldo Carvalho de Melo return evsel; 206ee29be62SArnaldo Carvalho de Melo } 207ee29be62SArnaldo Carvalho de Melo 208ee29be62SArnaldo Carvalho de Melo return NULL; 209ee29be62SArnaldo Carvalho de Melo } 210ee29be62SArnaldo Carvalho de Melo 21139876e7dSArnaldo Carvalho de Melo int perf_evlist__add_newtp(struct perf_evlist *evlist, 21239876e7dSArnaldo Carvalho de Melo const char *sys, const char *name, void *handler) 21339876e7dSArnaldo Carvalho de Melo { 21439876e7dSArnaldo Carvalho de Melo struct perf_evsel *evsel; 21539876e7dSArnaldo Carvalho de Melo 21639876e7dSArnaldo Carvalho de Melo evsel = perf_evsel__newtp(sys, name, evlist->nr_entries); 21739876e7dSArnaldo Carvalho de Melo if (evsel == NULL) 21839876e7dSArnaldo Carvalho de Melo return -1; 21939876e7dSArnaldo Carvalho de Melo 22039876e7dSArnaldo Carvalho de Melo evsel->handler.func = handler; 22139876e7dSArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 22239876e7dSArnaldo Carvalho de Melo return 0; 22339876e7dSArnaldo Carvalho de Melo } 22439876e7dSArnaldo Carvalho de Melo 2254152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist) 2264152ab37SArnaldo Carvalho de Melo { 2274152ab37SArnaldo Carvalho de Melo int cpu, thread; 2284152ab37SArnaldo Carvalho de Melo struct perf_evsel *pos; 229b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 230b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 2314152ab37SArnaldo Carvalho de Melo 232b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 2334152ab37SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 234823254edSNamhyung Kim if (!perf_evsel__is_group_leader(pos)) 2353fe4430dSJiri Olsa continue; 236b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 23755da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 23855da8005SNamhyung Kim PERF_EVENT_IOC_DISABLE, 0); 2394152ab37SArnaldo Carvalho de Melo } 2404152ab37SArnaldo Carvalho de Melo } 2414152ab37SArnaldo Carvalho de Melo } 2424152ab37SArnaldo Carvalho de Melo 243764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist) 244764e16a3SDavid Ahern { 245764e16a3SDavid Ahern int cpu, thread; 246764e16a3SDavid Ahern struct perf_evsel *pos; 247b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 248b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 249764e16a3SDavid Ahern 250b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 251764e16a3SDavid Ahern list_for_each_entry(pos, &evlist->entries, node) { 252823254edSNamhyung Kim if (!perf_evsel__is_group_leader(pos)) 2533fe4430dSJiri Olsa continue; 254b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 25555da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 25655da8005SNamhyung Kim PERF_EVENT_IOC_ENABLE, 0); 257764e16a3SDavid Ahern } 258764e16a3SDavid Ahern } 259764e16a3SDavid Ahern } 260764e16a3SDavid Ahern 261806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 2625c581041SArnaldo Carvalho de Melo { 263b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 264b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 265b3a319d5SNamhyung Kim int nfds = nr_cpus * nr_threads * evlist->nr_entries; 2665c581041SArnaldo Carvalho de Melo evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 2675c581041SArnaldo Carvalho de Melo return evlist->pollfd != NULL ? 0 : -ENOMEM; 2685c581041SArnaldo Carvalho de Melo } 26970082dd9SArnaldo Carvalho de Melo 27070082dd9SArnaldo Carvalho de Melo void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 27170082dd9SArnaldo Carvalho de Melo { 27270082dd9SArnaldo Carvalho de Melo fcntl(fd, F_SETFL, O_NONBLOCK); 27370082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].fd = fd; 27470082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].events = POLLIN; 27570082dd9SArnaldo Carvalho de Melo evlist->nr_fds++; 27670082dd9SArnaldo Carvalho de Melo } 27770db7533SArnaldo Carvalho de Melo 278a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist, 279a91e5431SArnaldo Carvalho de Melo struct perf_evsel *evsel, 2803d3b5e95SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 2813d3b5e95SArnaldo Carvalho de Melo { 2823d3b5e95SArnaldo Carvalho de Melo int hash; 2833d3b5e95SArnaldo Carvalho de Melo struct perf_sample_id *sid = SID(evsel, cpu, thread); 2843d3b5e95SArnaldo Carvalho de Melo 2853d3b5e95SArnaldo Carvalho de Melo sid->id = id; 2863d3b5e95SArnaldo Carvalho de Melo sid->evsel = evsel; 2873d3b5e95SArnaldo Carvalho de Melo hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); 2883d3b5e95SArnaldo Carvalho de Melo hlist_add_head(&sid->node, &evlist->heads[hash]); 2893d3b5e95SArnaldo Carvalho de Melo } 2903d3b5e95SArnaldo Carvalho de Melo 291a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 292a91e5431SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 293a91e5431SArnaldo Carvalho de Melo { 294a91e5431SArnaldo Carvalho de Melo perf_evlist__id_hash(evlist, evsel, cpu, thread, id); 295a91e5431SArnaldo Carvalho de Melo evsel->id[evsel->ids++] = id; 296a91e5431SArnaldo Carvalho de Melo } 297a91e5431SArnaldo Carvalho de Melo 298a91e5431SArnaldo Carvalho de Melo static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 2993d3b5e95SArnaldo Carvalho de Melo struct perf_evsel *evsel, 300f8a95309SArnaldo Carvalho de Melo int cpu, int thread, int fd) 301f8a95309SArnaldo Carvalho de Melo { 302f8a95309SArnaldo Carvalho de Melo u64 read_data[4] = { 0, }; 3033d3b5e95SArnaldo Carvalho de Melo int id_idx = 1; /* The first entry is the counter value */ 304e2b5abe0SJiri Olsa u64 id; 305e2b5abe0SJiri Olsa int ret; 306e2b5abe0SJiri Olsa 307e2b5abe0SJiri Olsa ret = ioctl(fd, PERF_EVENT_IOC_ID, &id); 308e2b5abe0SJiri Olsa if (!ret) 309e2b5abe0SJiri Olsa goto add; 310e2b5abe0SJiri Olsa 311e2b5abe0SJiri Olsa if (errno != ENOTTY) 312e2b5abe0SJiri Olsa return -1; 313e2b5abe0SJiri Olsa 314e2b5abe0SJiri Olsa /* Legacy way to get event id.. All hail to old kernels! */ 315f8a95309SArnaldo Carvalho de Melo 316c4861afeSJiri Olsa /* 317c4861afeSJiri Olsa * This way does not work with group format read, so bail 318c4861afeSJiri Olsa * out in that case. 319c4861afeSJiri Olsa */ 320c4861afeSJiri Olsa if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP) 321c4861afeSJiri Olsa return -1; 322c4861afeSJiri Olsa 323f8a95309SArnaldo Carvalho de Melo if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 324f8a95309SArnaldo Carvalho de Melo read(fd, &read_data, sizeof(read_data)) == -1) 325f8a95309SArnaldo Carvalho de Melo return -1; 326f8a95309SArnaldo Carvalho de Melo 327f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 328f8a95309SArnaldo Carvalho de Melo ++id_idx; 329f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 330f8a95309SArnaldo Carvalho de Melo ++id_idx; 331f8a95309SArnaldo Carvalho de Melo 332e2b5abe0SJiri Olsa id = read_data[id_idx]; 333e2b5abe0SJiri Olsa 334e2b5abe0SJiri Olsa add: 335e2b5abe0SJiri Olsa perf_evlist__id_add(evlist, evsel, cpu, thread, id); 336f8a95309SArnaldo Carvalho de Melo return 0; 337f8a95309SArnaldo Carvalho de Melo } 338f8a95309SArnaldo Carvalho de Melo 339932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 34070db7533SArnaldo Carvalho de Melo { 34170db7533SArnaldo Carvalho de Melo struct hlist_head *head; 34270db7533SArnaldo Carvalho de Melo struct perf_sample_id *sid; 34370db7533SArnaldo Carvalho de Melo int hash; 34470db7533SArnaldo Carvalho de Melo 34570db7533SArnaldo Carvalho de Melo hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 34670db7533SArnaldo Carvalho de Melo head = &evlist->heads[hash]; 34770db7533SArnaldo Carvalho de Melo 348b67bfe0dSSasha Levin hlist_for_each_entry(sid, head, node) 34970db7533SArnaldo Carvalho de Melo if (sid->id == id) 350932a3594SJiri Olsa return sid; 351932a3594SJiri Olsa 352932a3594SJiri Olsa return NULL; 353932a3594SJiri Olsa } 354932a3594SJiri Olsa 355932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 356932a3594SJiri Olsa { 357932a3594SJiri Olsa struct perf_sample_id *sid; 358932a3594SJiri Olsa 359932a3594SJiri Olsa if (evlist->nr_entries == 1) 360932a3594SJiri Olsa return perf_evlist__first(evlist); 361932a3594SJiri Olsa 362932a3594SJiri Olsa sid = perf_evlist__id2sid(evlist, id); 363932a3594SJiri Olsa if (sid) 36470db7533SArnaldo Carvalho de Melo return sid->evsel; 36530e68bccSNamhyung Kim 36630e68bccSNamhyung Kim if (!perf_evlist__sample_id_all(evlist)) 3670c21f736SArnaldo Carvalho de Melo return perf_evlist__first(evlist); 36830e68bccSNamhyung Kim 36970db7533SArnaldo Carvalho de Melo return NULL; 37070db7533SArnaldo Carvalho de Melo } 37104391debSArnaldo Carvalho de Melo 37275562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist, 37375562573SAdrian Hunter union perf_event *event, u64 *id) 37475562573SAdrian Hunter { 37575562573SAdrian Hunter const u64 *array = event->sample.array; 37675562573SAdrian Hunter ssize_t n; 37775562573SAdrian Hunter 37875562573SAdrian Hunter n = (event->header.size - sizeof(event->header)) >> 3; 37975562573SAdrian Hunter 38075562573SAdrian Hunter if (event->header.type == PERF_RECORD_SAMPLE) { 38175562573SAdrian Hunter if (evlist->id_pos >= n) 38275562573SAdrian Hunter return -1; 38375562573SAdrian Hunter *id = array[evlist->id_pos]; 38475562573SAdrian Hunter } else { 38575562573SAdrian Hunter if (evlist->is_pos > n) 38675562573SAdrian Hunter return -1; 38775562573SAdrian Hunter n -= evlist->is_pos; 38875562573SAdrian Hunter *id = array[n]; 38975562573SAdrian Hunter } 39075562573SAdrian Hunter return 0; 39175562573SAdrian Hunter } 39275562573SAdrian Hunter 39375562573SAdrian Hunter static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 39475562573SAdrian Hunter union perf_event *event) 39575562573SAdrian Hunter { 39675562573SAdrian Hunter struct hlist_head *head; 39775562573SAdrian Hunter struct perf_sample_id *sid; 39875562573SAdrian Hunter int hash; 39975562573SAdrian Hunter u64 id; 40075562573SAdrian Hunter 40175562573SAdrian Hunter if (evlist->nr_entries == 1) 40275562573SAdrian Hunter return perf_evlist__first(evlist); 40375562573SAdrian Hunter 40475562573SAdrian Hunter if (perf_evlist__event2id(evlist, event, &id)) 40575562573SAdrian Hunter return NULL; 40675562573SAdrian Hunter 40775562573SAdrian Hunter /* Synthesized events have an id of zero */ 40875562573SAdrian Hunter if (!id) 40975562573SAdrian Hunter return perf_evlist__first(evlist); 41075562573SAdrian Hunter 41175562573SAdrian Hunter hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 41275562573SAdrian Hunter head = &evlist->heads[hash]; 41375562573SAdrian Hunter 41475562573SAdrian Hunter hlist_for_each_entry(sid, head, node) { 41575562573SAdrian Hunter if (sid->id == id) 41675562573SAdrian Hunter return sid->evsel; 41775562573SAdrian Hunter } 41875562573SAdrian Hunter return NULL; 41975562573SAdrian Hunter } 42075562573SAdrian Hunter 421aece948fSArnaldo Carvalho de Melo union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 42204391debSArnaldo Carvalho de Melo { 423aece948fSArnaldo Carvalho de Melo struct perf_mmap *md = &evlist->mmap[idx]; 42404391debSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 42504391debSArnaldo Carvalho de Melo unsigned int old = md->prev; 42604391debSArnaldo Carvalho de Melo unsigned char *data = md->base + page_size; 4278115d60cSArnaldo Carvalho de Melo union perf_event *event = NULL; 42804391debSArnaldo Carvalho de Melo 4297bb41152SArnaldo Carvalho de Melo if (evlist->overwrite) { 43004391debSArnaldo Carvalho de Melo /* 43104391debSArnaldo Carvalho de Melo * If we're further behind than half the buffer, there's a chance 43204391debSArnaldo Carvalho de Melo * the writer will bite our tail and mess up the samples under us. 43304391debSArnaldo Carvalho de Melo * 43404391debSArnaldo Carvalho de Melo * If we somehow ended up ahead of the head, we got messed up. 43504391debSArnaldo Carvalho de Melo * 43604391debSArnaldo Carvalho de Melo * In either case, truncate and restart at head. 43704391debSArnaldo Carvalho de Melo */ 4387bb41152SArnaldo Carvalho de Melo int diff = head - old; 43904391debSArnaldo Carvalho de Melo if (diff > md->mask / 2 || diff < 0) { 44004391debSArnaldo Carvalho de Melo fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 44104391debSArnaldo Carvalho de Melo 44204391debSArnaldo Carvalho de Melo /* 44304391debSArnaldo Carvalho de Melo * head points to a known good entry, start there. 44404391debSArnaldo Carvalho de Melo */ 44504391debSArnaldo Carvalho de Melo old = head; 44604391debSArnaldo Carvalho de Melo } 4477bb41152SArnaldo Carvalho de Melo } 44804391debSArnaldo Carvalho de Melo 44904391debSArnaldo Carvalho de Melo if (old != head) { 45004391debSArnaldo Carvalho de Melo size_t size; 45104391debSArnaldo Carvalho de Melo 4528115d60cSArnaldo Carvalho de Melo event = (union perf_event *)&data[old & md->mask]; 45304391debSArnaldo Carvalho de Melo size = event->header.size; 45404391debSArnaldo Carvalho de Melo 45504391debSArnaldo Carvalho de Melo /* 45604391debSArnaldo Carvalho de Melo * Event straddles the mmap boundary -- header should always 45704391debSArnaldo Carvalho de Melo * be inside due to u64 alignment of output. 45804391debSArnaldo Carvalho de Melo */ 45904391debSArnaldo Carvalho de Melo if ((old & md->mask) + size != ((old + size) & md->mask)) { 46004391debSArnaldo Carvalho de Melo unsigned int offset = old; 46104391debSArnaldo Carvalho de Melo unsigned int len = min(sizeof(*event), size), cpy; 4620479b8b9SDavid Ahern void *dst = &md->event_copy; 46304391debSArnaldo Carvalho de Melo 46404391debSArnaldo Carvalho de Melo do { 46504391debSArnaldo Carvalho de Melo cpy = min(md->mask + 1 - (offset & md->mask), len); 46604391debSArnaldo Carvalho de Melo memcpy(dst, &data[offset & md->mask], cpy); 46704391debSArnaldo Carvalho de Melo offset += cpy; 46804391debSArnaldo Carvalho de Melo dst += cpy; 46904391debSArnaldo Carvalho de Melo len -= cpy; 47004391debSArnaldo Carvalho de Melo } while (len); 47104391debSArnaldo Carvalho de Melo 4720479b8b9SDavid Ahern event = &md->event_copy; 47304391debSArnaldo Carvalho de Melo } 47404391debSArnaldo Carvalho de Melo 47504391debSArnaldo Carvalho de Melo old += size; 47604391debSArnaldo Carvalho de Melo } 47704391debSArnaldo Carvalho de Melo 47804391debSArnaldo Carvalho de Melo md->prev = old; 4797bb41152SArnaldo Carvalho de Melo 4807bb41152SArnaldo Carvalho de Melo if (!evlist->overwrite) 4817bb41152SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 4827bb41152SArnaldo Carvalho de Melo 48304391debSArnaldo Carvalho de Melo return event; 48404391debSArnaldo Carvalho de Melo } 485f8a95309SArnaldo Carvalho de Melo 48693edcbd9SAdrian Hunter static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 48793edcbd9SAdrian Hunter { 48893edcbd9SAdrian Hunter if (evlist->mmap[idx].base != NULL) { 48993edcbd9SAdrian Hunter munmap(evlist->mmap[idx].base, evlist->mmap_len); 49093edcbd9SAdrian Hunter evlist->mmap[idx].base = NULL; 49193edcbd9SAdrian Hunter } 49293edcbd9SAdrian Hunter } 49393edcbd9SAdrian Hunter 4947e2ed097SArnaldo Carvalho de Melo void perf_evlist__munmap(struct perf_evlist *evlist) 495f8a95309SArnaldo Carvalho de Melo { 496aece948fSArnaldo Carvalho de Melo int i; 497f8a95309SArnaldo Carvalho de Melo 49893edcbd9SAdrian Hunter for (i = 0; i < evlist->nr_mmaps; i++) 49993edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, i); 500aece948fSArnaldo Carvalho de Melo 501aece948fSArnaldo Carvalho de Melo free(evlist->mmap); 502aece948fSArnaldo Carvalho de Melo evlist->mmap = NULL; 503f8a95309SArnaldo Carvalho de Melo } 504f8a95309SArnaldo Carvalho de Melo 505806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 506f8a95309SArnaldo Carvalho de Melo { 507a14bb7a6SArnaldo Carvalho de Melo evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 508ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(evlist->cpus)) 509b3a319d5SNamhyung Kim evlist->nr_mmaps = thread_map__nr(evlist->threads); 510aece948fSArnaldo Carvalho de Melo evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 511f8a95309SArnaldo Carvalho de Melo return evlist->mmap != NULL ? 0 : -ENOMEM; 512f8a95309SArnaldo Carvalho de Melo } 513f8a95309SArnaldo Carvalho de Melo 514bccdaba0SArnaldo Carvalho de Melo static int __perf_evlist__mmap(struct perf_evlist *evlist, 515aece948fSArnaldo Carvalho de Melo int idx, int prot, int mask, int fd) 516f8a95309SArnaldo Carvalho de Melo { 517aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].prev = 0; 518aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].mask = mask; 519aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 520f8a95309SArnaldo Carvalho de Melo MAP_SHARED, fd, 0); 521301b195dSNelson Elhage if (evlist->mmap[idx].base == MAP_FAILED) { 522301b195dSNelson Elhage evlist->mmap[idx].base = NULL; 523f8a95309SArnaldo Carvalho de Melo return -1; 524301b195dSNelson Elhage } 525f8a95309SArnaldo Carvalho de Melo 526f8a95309SArnaldo Carvalho de Melo perf_evlist__add_pollfd(evlist, fd); 527f8a95309SArnaldo Carvalho de Melo return 0; 528f8a95309SArnaldo Carvalho de Melo } 529f8a95309SArnaldo Carvalho de Melo 530aece948fSArnaldo Carvalho de Melo static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) 531aece948fSArnaldo Carvalho de Melo { 532aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 533aece948fSArnaldo Carvalho de Melo int cpu, thread; 534b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 535b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 536aece948fSArnaldo Carvalho de Melo 537e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per cpu\n"); 538b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 539aece948fSArnaldo Carvalho de Melo int output = -1; 540aece948fSArnaldo Carvalho de Melo 541b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 542aece948fSArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 543aece948fSArnaldo Carvalho de Melo int fd = FD(evsel, cpu, thread); 544aece948fSArnaldo Carvalho de Melo 545aece948fSArnaldo Carvalho de Melo if (output == -1) { 546aece948fSArnaldo Carvalho de Melo output = fd; 547bccdaba0SArnaldo Carvalho de Melo if (__perf_evlist__mmap(evlist, cpu, 548aece948fSArnaldo Carvalho de Melo prot, mask, output) < 0) 549aece948fSArnaldo Carvalho de Melo goto out_unmap; 550aece948fSArnaldo Carvalho de Melo } else { 551aece948fSArnaldo Carvalho de Melo if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) 552aece948fSArnaldo Carvalho de Melo goto out_unmap; 553aece948fSArnaldo Carvalho de Melo } 554aece948fSArnaldo Carvalho de Melo 555aece948fSArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 556aece948fSArnaldo Carvalho de Melo perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 557aece948fSArnaldo Carvalho de Melo goto out_unmap; 558aece948fSArnaldo Carvalho de Melo } 559aece948fSArnaldo Carvalho de Melo } 560aece948fSArnaldo Carvalho de Melo } 561aece948fSArnaldo Carvalho de Melo 562aece948fSArnaldo Carvalho de Melo return 0; 563aece948fSArnaldo Carvalho de Melo 564aece948fSArnaldo Carvalho de Melo out_unmap: 56593edcbd9SAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) 56693edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, cpu); 567aece948fSArnaldo Carvalho de Melo return -1; 568aece948fSArnaldo Carvalho de Melo } 569aece948fSArnaldo Carvalho de Melo 570aece948fSArnaldo Carvalho de Melo static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) 571aece948fSArnaldo Carvalho de Melo { 572aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 573aece948fSArnaldo Carvalho de Melo int thread; 574b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 575aece948fSArnaldo Carvalho de Melo 576e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per thread\n"); 577b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 578aece948fSArnaldo Carvalho de Melo int output = -1; 579aece948fSArnaldo Carvalho de Melo 580aece948fSArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 581aece948fSArnaldo Carvalho de Melo int fd = FD(evsel, 0, thread); 582aece948fSArnaldo Carvalho de Melo 583aece948fSArnaldo Carvalho de Melo if (output == -1) { 584aece948fSArnaldo Carvalho de Melo output = fd; 585bccdaba0SArnaldo Carvalho de Melo if (__perf_evlist__mmap(evlist, thread, 586aece948fSArnaldo Carvalho de Melo prot, mask, output) < 0) 587aece948fSArnaldo Carvalho de Melo goto out_unmap; 588aece948fSArnaldo Carvalho de Melo } else { 589aece948fSArnaldo Carvalho de Melo if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) 590aece948fSArnaldo Carvalho de Melo goto out_unmap; 591aece948fSArnaldo Carvalho de Melo } 592aece948fSArnaldo Carvalho de Melo 593aece948fSArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 594aece948fSArnaldo Carvalho de Melo perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0) 595aece948fSArnaldo Carvalho de Melo goto out_unmap; 596aece948fSArnaldo Carvalho de Melo } 597aece948fSArnaldo Carvalho de Melo } 598aece948fSArnaldo Carvalho de Melo 599aece948fSArnaldo Carvalho de Melo return 0; 600aece948fSArnaldo Carvalho de Melo 601aece948fSArnaldo Carvalho de Melo out_unmap: 60293edcbd9SAdrian Hunter for (thread = 0; thread < nr_threads; thread++) 60393edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, thread); 604aece948fSArnaldo Carvalho de Melo return -1; 605aece948fSArnaldo Carvalho de Melo } 606aece948fSArnaldo Carvalho de Melo 607f8a95309SArnaldo Carvalho de Melo /** perf_evlist__mmap - Create per cpu maps to receive events 608f8a95309SArnaldo Carvalho de Melo * 609f8a95309SArnaldo Carvalho de Melo * @evlist - list of events 610f8a95309SArnaldo Carvalho de Melo * @pages - map length in pages 611f8a95309SArnaldo Carvalho de Melo * @overwrite - overwrite older events? 612f8a95309SArnaldo Carvalho de Melo * 613f8a95309SArnaldo Carvalho de Melo * If overwrite is false the user needs to signal event consuption using: 614f8a95309SArnaldo Carvalho de Melo * 615f8a95309SArnaldo Carvalho de Melo * struct perf_mmap *m = &evlist->mmap[cpu]; 616f8a95309SArnaldo Carvalho de Melo * unsigned int head = perf_mmap__read_head(m); 617f8a95309SArnaldo Carvalho de Melo * 618f8a95309SArnaldo Carvalho de Melo * perf_mmap__write_tail(m, head) 6197e2ed097SArnaldo Carvalho de Melo * 6207e2ed097SArnaldo Carvalho de Melo * Using perf_evlist__read_on_cpu does this automatically. 621f8a95309SArnaldo Carvalho de Melo */ 62250a682ceSArnaldo Carvalho de Melo int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 62350a682ceSArnaldo Carvalho de Melo bool overwrite) 624f8a95309SArnaldo Carvalho de Melo { 625aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 6267e2ed097SArnaldo Carvalho de Melo const struct cpu_map *cpus = evlist->cpus; 6277e2ed097SArnaldo Carvalho de Melo const struct thread_map *threads = evlist->threads; 62850a682ceSArnaldo Carvalho de Melo int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 62950a682ceSArnaldo Carvalho de Melo 63050a682ceSArnaldo Carvalho de Melo /* 512 kiB: default amount of unprivileged mlocked memory */ 63150a682ceSArnaldo Carvalho de Melo if (pages == UINT_MAX) 63250a682ceSArnaldo Carvalho de Melo pages = (512 * 1024) / page_size; 63341d0d933SNelson Elhage else if (!is_power_of_2(pages)) 63441d0d933SNelson Elhage return -EINVAL; 63550a682ceSArnaldo Carvalho de Melo 63650a682ceSArnaldo Carvalho de Melo mask = pages * page_size - 1; 637f8a95309SArnaldo Carvalho de Melo 6387e2ed097SArnaldo Carvalho de Melo if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 639f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 640f8a95309SArnaldo Carvalho de Melo 6417e2ed097SArnaldo Carvalho de Melo if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 642f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 643f8a95309SArnaldo Carvalho de Melo 644f8a95309SArnaldo Carvalho de Melo evlist->overwrite = overwrite; 645f8a95309SArnaldo Carvalho de Melo evlist->mmap_len = (pages + 1) * page_size; 646f8a95309SArnaldo Carvalho de Melo 647f8a95309SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 648f8a95309SArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 649a91e5431SArnaldo Carvalho de Melo evsel->sample_id == NULL && 650a14bb7a6SArnaldo Carvalho de Melo perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 651f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 652f8a95309SArnaldo Carvalho de Melo } 653f8a95309SArnaldo Carvalho de Melo 654ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(cpus)) 655aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_thread(evlist, prot, mask); 656f8a95309SArnaldo Carvalho de Melo 657aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_cpu(evlist, prot, mask); 658f8a95309SArnaldo Carvalho de Melo } 6597e2ed097SArnaldo Carvalho de Melo 660b809ac10SNamhyung Kim int perf_evlist__create_maps(struct perf_evlist *evlist, 661b809ac10SNamhyung Kim struct perf_target *target) 6627e2ed097SArnaldo Carvalho de Melo { 663b809ac10SNamhyung Kim evlist->threads = thread_map__new_str(target->pid, target->tid, 664b809ac10SNamhyung Kim target->uid); 6657e2ed097SArnaldo Carvalho de Melo 6667e2ed097SArnaldo Carvalho de Melo if (evlist->threads == NULL) 6677e2ed097SArnaldo Carvalho de Melo return -1; 6687e2ed097SArnaldo Carvalho de Melo 669879d77d0SNamhyung Kim if (perf_target__has_task(target)) 670d67356e7SNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 671d1cb9fceSNamhyung Kim else if (!perf_target__has_cpu(target) && !target->uses_mmap) 672d1cb9fceSNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 673879d77d0SNamhyung Kim else 674879d77d0SNamhyung Kim evlist->cpus = cpu_map__new(target->cpu_list); 6757e2ed097SArnaldo Carvalho de Melo 6767e2ed097SArnaldo Carvalho de Melo if (evlist->cpus == NULL) 6777e2ed097SArnaldo Carvalho de Melo goto out_delete_threads; 6787e2ed097SArnaldo Carvalho de Melo 6797e2ed097SArnaldo Carvalho de Melo return 0; 6807e2ed097SArnaldo Carvalho de Melo 6817e2ed097SArnaldo Carvalho de Melo out_delete_threads: 6827e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 6837e2ed097SArnaldo Carvalho de Melo return -1; 6847e2ed097SArnaldo Carvalho de Melo } 6857e2ed097SArnaldo Carvalho de Melo 6867e2ed097SArnaldo Carvalho de Melo void perf_evlist__delete_maps(struct perf_evlist *evlist) 6877e2ed097SArnaldo Carvalho de Melo { 6887e2ed097SArnaldo Carvalho de Melo cpu_map__delete(evlist->cpus); 6897e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 6907e2ed097SArnaldo Carvalho de Melo evlist->cpus = NULL; 6917e2ed097SArnaldo Carvalho de Melo evlist->threads = NULL; 6927e2ed097SArnaldo Carvalho de Melo } 6930a102479SFrederic Weisbecker 6941491a632SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist) 6950a102479SFrederic Weisbecker { 6960a102479SFrederic Weisbecker struct perf_evsel *evsel; 697745cefc5SArnaldo Carvalho de Melo int err = 0; 698745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 699b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 7000a102479SFrederic Weisbecker 7010a102479SFrederic Weisbecker list_for_each_entry(evsel, &evlist->entries, node) { 702745cefc5SArnaldo Carvalho de Melo if (evsel->filter == NULL) 7030a102479SFrederic Weisbecker continue; 704745cefc5SArnaldo Carvalho de Melo 705745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 7060a102479SFrederic Weisbecker if (err) 707745cefc5SArnaldo Carvalho de Melo break; 7080a102479SFrederic Weisbecker } 7090a102479SFrederic Weisbecker 710745cefc5SArnaldo Carvalho de Melo return err; 711745cefc5SArnaldo Carvalho de Melo } 712745cefc5SArnaldo Carvalho de Melo 713745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) 714745cefc5SArnaldo Carvalho de Melo { 715745cefc5SArnaldo Carvalho de Melo struct perf_evsel *evsel; 716745cefc5SArnaldo Carvalho de Melo int err = 0; 717745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 718b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 719745cefc5SArnaldo Carvalho de Melo 720745cefc5SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 721745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); 722745cefc5SArnaldo Carvalho de Melo if (err) 723745cefc5SArnaldo Carvalho de Melo break; 724745cefc5SArnaldo Carvalho de Melo } 725745cefc5SArnaldo Carvalho de Melo 726745cefc5SArnaldo Carvalho de Melo return err; 7270a102479SFrederic Weisbecker } 72874429964SFrederic Weisbecker 7290c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 73074429964SFrederic Weisbecker { 73175562573SAdrian Hunter struct perf_evsel *pos; 732c2a70653SArnaldo Carvalho de Melo 73375562573SAdrian Hunter if (evlist->nr_entries == 1) 73475562573SAdrian Hunter return true; 73575562573SAdrian Hunter 73675562573SAdrian Hunter if (evlist->id_pos < 0 || evlist->is_pos < 0) 73775562573SAdrian Hunter return false; 73875562573SAdrian Hunter 73975562573SAdrian Hunter list_for_each_entry(pos, &evlist->entries, node) { 74075562573SAdrian Hunter if (pos->id_pos != evlist->id_pos || 74175562573SAdrian Hunter pos->is_pos != evlist->is_pos) 742c2a70653SArnaldo Carvalho de Melo return false; 74374429964SFrederic Weisbecker } 74474429964SFrederic Weisbecker 745c2a70653SArnaldo Carvalho de Melo return true; 746c2a70653SArnaldo Carvalho de Melo } 747c2a70653SArnaldo Carvalho de Melo 74875562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) 749c2a70653SArnaldo Carvalho de Melo { 75075562573SAdrian Hunter struct perf_evsel *evsel; 75175562573SAdrian Hunter 75275562573SAdrian Hunter if (evlist->combined_sample_type) 75375562573SAdrian Hunter return evlist->combined_sample_type; 75475562573SAdrian Hunter 75575562573SAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) 75675562573SAdrian Hunter evlist->combined_sample_type |= evsel->attr.sample_type; 75775562573SAdrian Hunter 75875562573SAdrian Hunter return evlist->combined_sample_type; 75975562573SAdrian Hunter } 76075562573SAdrian Hunter 76175562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) 76275562573SAdrian Hunter { 76375562573SAdrian Hunter evlist->combined_sample_type = 0; 76475562573SAdrian Hunter return __perf_evlist__combined_sample_type(evlist); 765c2a70653SArnaldo Carvalho de Melo } 766c2a70653SArnaldo Carvalho de Melo 7679ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist) 7689ede473cSJiri Olsa { 7699ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 7709ede473cSJiri Olsa u64 read_format = first->attr.read_format; 7719ede473cSJiri Olsa u64 sample_type = first->attr.sample_type; 7729ede473cSJiri Olsa 7739ede473cSJiri Olsa list_for_each_entry_continue(pos, &evlist->entries, node) { 7749ede473cSJiri Olsa if (read_format != pos->attr.read_format) 7759ede473cSJiri Olsa return false; 7769ede473cSJiri Olsa } 7779ede473cSJiri Olsa 7789ede473cSJiri Olsa /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */ 7799ede473cSJiri Olsa if ((sample_type & PERF_SAMPLE_READ) && 7809ede473cSJiri Olsa !(read_format & PERF_FORMAT_ID)) { 7819ede473cSJiri Olsa return false; 7829ede473cSJiri Olsa } 7839ede473cSJiri Olsa 7849ede473cSJiri Olsa return true; 7859ede473cSJiri Olsa } 7869ede473cSJiri Olsa 7879ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist) 7889ede473cSJiri Olsa { 7899ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist); 7909ede473cSJiri Olsa return first->attr.read_format; 7919ede473cSJiri Olsa } 7929ede473cSJiri Olsa 7930c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) 79481e36bffSArnaldo Carvalho de Melo { 7950c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 79681e36bffSArnaldo Carvalho de Melo struct perf_sample *data; 79781e36bffSArnaldo Carvalho de Melo u64 sample_type; 79881e36bffSArnaldo Carvalho de Melo u16 size = 0; 79981e36bffSArnaldo Carvalho de Melo 80081e36bffSArnaldo Carvalho de Melo if (!first->attr.sample_id_all) 80181e36bffSArnaldo Carvalho de Melo goto out; 80281e36bffSArnaldo Carvalho de Melo 80381e36bffSArnaldo Carvalho de Melo sample_type = first->attr.sample_type; 80481e36bffSArnaldo Carvalho de Melo 80581e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TID) 80681e36bffSArnaldo Carvalho de Melo size += sizeof(data->tid) * 2; 80781e36bffSArnaldo Carvalho de Melo 80881e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TIME) 80981e36bffSArnaldo Carvalho de Melo size += sizeof(data->time); 81081e36bffSArnaldo Carvalho de Melo 81181e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_ID) 81281e36bffSArnaldo Carvalho de Melo size += sizeof(data->id); 81381e36bffSArnaldo Carvalho de Melo 81481e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_STREAM_ID) 81581e36bffSArnaldo Carvalho de Melo size += sizeof(data->stream_id); 81681e36bffSArnaldo Carvalho de Melo 81781e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_CPU) 81881e36bffSArnaldo Carvalho de Melo size += sizeof(data->cpu) * 2; 81975562573SAdrian Hunter 82075562573SAdrian Hunter if (sample_type & PERF_SAMPLE_IDENTIFIER) 82175562573SAdrian Hunter size += sizeof(data->id); 82281e36bffSArnaldo Carvalho de Melo out: 82381e36bffSArnaldo Carvalho de Melo return size; 82481e36bffSArnaldo Carvalho de Melo } 82581e36bffSArnaldo Carvalho de Melo 8260c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) 827c2a70653SArnaldo Carvalho de Melo { 8280c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 829c2a70653SArnaldo Carvalho de Melo 830c2a70653SArnaldo Carvalho de Melo list_for_each_entry_continue(pos, &evlist->entries, node) { 831c2a70653SArnaldo Carvalho de Melo if (first->attr.sample_id_all != pos->attr.sample_id_all) 832c2a70653SArnaldo Carvalho de Melo return false; 833c2a70653SArnaldo Carvalho de Melo } 834c2a70653SArnaldo Carvalho de Melo 835c2a70653SArnaldo Carvalho de Melo return true; 83674429964SFrederic Weisbecker } 83774429964SFrederic Weisbecker 8380c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist) 83974429964SFrederic Weisbecker { 8400c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 841c2a70653SArnaldo Carvalho de Melo return first->attr.sample_id_all; 84274429964SFrederic Weisbecker } 84381cce8deSArnaldo Carvalho de Melo 84481cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist, 84581cce8deSArnaldo Carvalho de Melo struct perf_evsel *evsel) 84681cce8deSArnaldo Carvalho de Melo { 84781cce8deSArnaldo Carvalho de Melo evlist->selected = evsel; 84881cce8deSArnaldo Carvalho de Melo } 849727ab04eSArnaldo Carvalho de Melo 850a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist) 851a74b4b66SNamhyung Kim { 852a74b4b66SNamhyung Kim struct perf_evsel *evsel; 853a74b4b66SNamhyung Kim int ncpus = cpu_map__nr(evlist->cpus); 854a74b4b66SNamhyung Kim int nthreads = thread_map__nr(evlist->threads); 855a74b4b66SNamhyung Kim 856a74b4b66SNamhyung Kim list_for_each_entry_reverse(evsel, &evlist->entries, node) 857a74b4b66SNamhyung Kim perf_evsel__close(evsel, ncpus, nthreads); 858a74b4b66SNamhyung Kim } 859a74b4b66SNamhyung Kim 8606a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist) 861727ab04eSArnaldo Carvalho de Melo { 8626a4bb04cSJiri Olsa struct perf_evsel *evsel; 863a74b4b66SNamhyung Kim int err; 864727ab04eSArnaldo Carvalho de Melo 865727ab04eSArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 8666a4bb04cSJiri Olsa err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 867727ab04eSArnaldo Carvalho de Melo if (err < 0) 868727ab04eSArnaldo Carvalho de Melo goto out_err; 869727ab04eSArnaldo Carvalho de Melo } 870727ab04eSArnaldo Carvalho de Melo 871727ab04eSArnaldo Carvalho de Melo return 0; 872727ab04eSArnaldo Carvalho de Melo out_err: 873a74b4b66SNamhyung Kim perf_evlist__close(evlist); 87441c21a68SNamhyung Kim errno = -err; 875727ab04eSArnaldo Carvalho de Melo return err; 876727ab04eSArnaldo Carvalho de Melo } 87735b9d88eSArnaldo Carvalho de Melo 87835b9d88eSArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, 8796ef73ec4SNamhyung Kim struct perf_target *target, 88055e162eaSNamhyung Kim const char *argv[], bool pipe_output, 88155e162eaSNamhyung Kim bool want_signal) 88235b9d88eSArnaldo Carvalho de Melo { 88335b9d88eSArnaldo Carvalho de Melo int child_ready_pipe[2], go_pipe[2]; 88435b9d88eSArnaldo Carvalho de Melo char bf; 88535b9d88eSArnaldo Carvalho de Melo 88635b9d88eSArnaldo Carvalho de Melo if (pipe(child_ready_pipe) < 0) { 88735b9d88eSArnaldo Carvalho de Melo perror("failed to create 'ready' pipe"); 88835b9d88eSArnaldo Carvalho de Melo return -1; 88935b9d88eSArnaldo Carvalho de Melo } 89035b9d88eSArnaldo Carvalho de Melo 89135b9d88eSArnaldo Carvalho de Melo if (pipe(go_pipe) < 0) { 89235b9d88eSArnaldo Carvalho de Melo perror("failed to create 'go' pipe"); 89335b9d88eSArnaldo Carvalho de Melo goto out_close_ready_pipe; 89435b9d88eSArnaldo Carvalho de Melo } 89535b9d88eSArnaldo Carvalho de Melo 89635b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = fork(); 89735b9d88eSArnaldo Carvalho de Melo if (evlist->workload.pid < 0) { 89835b9d88eSArnaldo Carvalho de Melo perror("failed to fork"); 89935b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 90035b9d88eSArnaldo Carvalho de Melo } 90135b9d88eSArnaldo Carvalho de Melo 90235b9d88eSArnaldo Carvalho de Melo if (!evlist->workload.pid) { 903119fa3c9SNamhyung Kim if (pipe_output) 90435b9d88eSArnaldo Carvalho de Melo dup2(2, 1); 90535b9d88eSArnaldo Carvalho de Melo 9060817df08SDavid Ahern signal(SIGTERM, SIG_DFL); 9070817df08SDavid Ahern 90835b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 90935b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 91035b9d88eSArnaldo Carvalho de Melo fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 91135b9d88eSArnaldo Carvalho de Melo 91235b9d88eSArnaldo Carvalho de Melo /* 91335b9d88eSArnaldo Carvalho de Melo * Tell the parent we're ready to go 91435b9d88eSArnaldo Carvalho de Melo */ 91535b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 91635b9d88eSArnaldo Carvalho de Melo 91735b9d88eSArnaldo Carvalho de Melo /* 91835b9d88eSArnaldo Carvalho de Melo * Wait until the parent tells us to go. 91935b9d88eSArnaldo Carvalho de Melo */ 92035b9d88eSArnaldo Carvalho de Melo if (read(go_pipe[0], &bf, 1) == -1) 92135b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 92235b9d88eSArnaldo Carvalho de Melo 92335b9d88eSArnaldo Carvalho de Melo execvp(argv[0], (char **)argv); 92435b9d88eSArnaldo Carvalho de Melo 92535b9d88eSArnaldo Carvalho de Melo perror(argv[0]); 92655e162eaSNamhyung Kim if (want_signal) 92735b9d88eSArnaldo Carvalho de Melo kill(getppid(), SIGUSR1); 92835b9d88eSArnaldo Carvalho de Melo exit(-1); 92935b9d88eSArnaldo Carvalho de Melo } 93035b9d88eSArnaldo Carvalho de Melo 9316ef73ec4SNamhyung Kim if (perf_target__none(target)) 93235b9d88eSArnaldo Carvalho de Melo evlist->threads->map[0] = evlist->workload.pid; 93335b9d88eSArnaldo Carvalho de Melo 93435b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 93535b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 93635b9d88eSArnaldo Carvalho de Melo /* 93735b9d88eSArnaldo Carvalho de Melo * wait for child to settle 93835b9d88eSArnaldo Carvalho de Melo */ 93935b9d88eSArnaldo Carvalho de Melo if (read(child_ready_pipe[0], &bf, 1) == -1) { 94035b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 94135b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 94235b9d88eSArnaldo Carvalho de Melo } 94335b9d88eSArnaldo Carvalho de Melo 944bcf3145fSNamhyung Kim fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC); 94535b9d88eSArnaldo Carvalho de Melo evlist->workload.cork_fd = go_pipe[1]; 94635b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 94735b9d88eSArnaldo Carvalho de Melo return 0; 94835b9d88eSArnaldo Carvalho de Melo 94935b9d88eSArnaldo Carvalho de Melo out_close_pipes: 95035b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 95135b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 95235b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe: 95335b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 95435b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 95535b9d88eSArnaldo Carvalho de Melo return -1; 95635b9d88eSArnaldo Carvalho de Melo } 95735b9d88eSArnaldo Carvalho de Melo 95835b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist) 95935b9d88eSArnaldo Carvalho de Melo { 96035b9d88eSArnaldo Carvalho de Melo if (evlist->workload.cork_fd > 0) { 961b3824404SDavid Ahern char bf = 0; 962bcf3145fSNamhyung Kim int ret; 96335b9d88eSArnaldo Carvalho de Melo /* 96435b9d88eSArnaldo Carvalho de Melo * Remove the cork, let it rip! 96535b9d88eSArnaldo Carvalho de Melo */ 966bcf3145fSNamhyung Kim ret = write(evlist->workload.cork_fd, &bf, 1); 967bcf3145fSNamhyung Kim if (ret < 0) 968bcf3145fSNamhyung Kim perror("enable to write to pipe"); 969bcf3145fSNamhyung Kim 970bcf3145fSNamhyung Kim close(evlist->workload.cork_fd); 971bcf3145fSNamhyung Kim return ret; 97235b9d88eSArnaldo Carvalho de Melo } 97335b9d88eSArnaldo Carvalho de Melo 97435b9d88eSArnaldo Carvalho de Melo return 0; 97535b9d88eSArnaldo Carvalho de Melo } 976cb0b29e0SArnaldo Carvalho de Melo 977a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 9780807d2d8SArnaldo Carvalho de Melo struct perf_sample *sample) 979cb0b29e0SArnaldo Carvalho de Melo { 98075562573SAdrian Hunter struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); 98175562573SAdrian Hunter 98275562573SAdrian Hunter if (!evsel) 98375562573SAdrian Hunter return -EFAULT; 9840807d2d8SArnaldo Carvalho de Melo return perf_evsel__parse_sample(evsel, event, sample); 985cb0b29e0SArnaldo Carvalho de Melo } 98678f067b3SArnaldo Carvalho de Melo 98778f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) 98878f067b3SArnaldo Carvalho de Melo { 98978f067b3SArnaldo Carvalho de Melo struct perf_evsel *evsel; 99078f067b3SArnaldo Carvalho de Melo size_t printed = 0; 99178f067b3SArnaldo Carvalho de Melo 99278f067b3SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 99378f067b3SArnaldo Carvalho de Melo printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 99478f067b3SArnaldo Carvalho de Melo perf_evsel__name(evsel)); 99578f067b3SArnaldo Carvalho de Melo } 99678f067b3SArnaldo Carvalho de Melo 99778f067b3SArnaldo Carvalho de Melo return printed + fprintf(fp, "\n");; 99878f067b3SArnaldo Carvalho de Melo } 999