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" 10553873e1SBorislav Petkov #include <api/fs/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" 21994a1f78SJiri Olsa #include "parse-options.h" 2250d08e47SArnaldo Carvalho de Melo 23f8a95309SArnaldo Carvalho de Melo #include <sys/mman.h> 24f8a95309SArnaldo Carvalho de Melo 2570db7533SArnaldo Carvalho de Melo #include <linux/bitops.h> 2670db7533SArnaldo Carvalho de Melo #include <linux/hash.h> 2770db7533SArnaldo Carvalho de Melo 28f8a95309SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 29a91e5431SArnaldo Carvalho de Melo #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 30f8a95309SArnaldo Carvalho de Melo 317e2ed097SArnaldo Carvalho de Melo void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 327e2ed097SArnaldo Carvalho de Melo struct thread_map *threads) 33361c99a6SArnaldo Carvalho de Melo { 3470db7533SArnaldo Carvalho de Melo int i; 3570db7533SArnaldo Carvalho de Melo 3670db7533SArnaldo Carvalho de Melo for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) 3770db7533SArnaldo Carvalho de Melo INIT_HLIST_HEAD(&evlist->heads[i]); 38361c99a6SArnaldo Carvalho de Melo INIT_LIST_HEAD(&evlist->entries); 397e2ed097SArnaldo Carvalho de Melo perf_evlist__set_maps(evlist, cpus, threads); 4035b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = -1; 41361c99a6SArnaldo Carvalho de Melo } 42361c99a6SArnaldo Carvalho de Melo 43334fe7a3SNamhyung Kim struct perf_evlist *perf_evlist__new(void) 44ef1d1af2SArnaldo Carvalho de Melo { 45ef1d1af2SArnaldo Carvalho de Melo struct perf_evlist *evlist = zalloc(sizeof(*evlist)); 46ef1d1af2SArnaldo Carvalho de Melo 47ef1d1af2SArnaldo Carvalho de Melo if (evlist != NULL) 48334fe7a3SNamhyung Kim perf_evlist__init(evlist, NULL, NULL); 49ef1d1af2SArnaldo Carvalho de Melo 50361c99a6SArnaldo Carvalho de Melo return evlist; 51361c99a6SArnaldo Carvalho de Melo } 52361c99a6SArnaldo Carvalho de Melo 53b22d54b0SJiri Olsa struct perf_evlist *perf_evlist__new_default(void) 54b22d54b0SJiri Olsa { 55b22d54b0SJiri Olsa struct perf_evlist *evlist = perf_evlist__new(); 56b22d54b0SJiri Olsa 57b22d54b0SJiri Olsa if (evlist && perf_evlist__add_default(evlist)) { 58b22d54b0SJiri Olsa perf_evlist__delete(evlist); 59b22d54b0SJiri Olsa evlist = NULL; 60b22d54b0SJiri Olsa } 61b22d54b0SJiri Olsa 62b22d54b0SJiri Olsa return evlist; 63b22d54b0SJiri Olsa } 64b22d54b0SJiri Olsa 6575562573SAdrian Hunter /** 6675562573SAdrian Hunter * perf_evlist__set_id_pos - set the positions of event ids. 6775562573SAdrian Hunter * @evlist: selected event list 6875562573SAdrian Hunter * 6975562573SAdrian Hunter * Events with compatible sample types all have the same id_pos 7075562573SAdrian Hunter * and is_pos. For convenience, put a copy on evlist. 7175562573SAdrian Hunter */ 7275562573SAdrian Hunter void perf_evlist__set_id_pos(struct perf_evlist *evlist) 7375562573SAdrian Hunter { 7475562573SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 7575562573SAdrian Hunter 7675562573SAdrian Hunter evlist->id_pos = first->id_pos; 7775562573SAdrian Hunter evlist->is_pos = first->is_pos; 7875562573SAdrian Hunter } 7975562573SAdrian Hunter 80733cd2feSAdrian Hunter static void perf_evlist__update_id_pos(struct perf_evlist *evlist) 81733cd2feSAdrian Hunter { 82733cd2feSAdrian Hunter struct perf_evsel *evsel; 83733cd2feSAdrian Hunter 84733cd2feSAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) 85733cd2feSAdrian Hunter perf_evsel__calc_id_pos(evsel); 86733cd2feSAdrian Hunter 87733cd2feSAdrian Hunter perf_evlist__set_id_pos(evlist); 88733cd2feSAdrian Hunter } 89733cd2feSAdrian Hunter 90361c99a6SArnaldo Carvalho de Melo static void perf_evlist__purge(struct perf_evlist *evlist) 91361c99a6SArnaldo Carvalho de Melo { 92361c99a6SArnaldo Carvalho de Melo struct perf_evsel *pos, *n; 93361c99a6SArnaldo Carvalho de Melo 94361c99a6SArnaldo Carvalho de Melo list_for_each_entry_safe(pos, n, &evlist->entries, node) { 95361c99a6SArnaldo Carvalho de Melo list_del_init(&pos->node); 96361c99a6SArnaldo Carvalho de Melo perf_evsel__delete(pos); 97361c99a6SArnaldo Carvalho de Melo } 98361c99a6SArnaldo Carvalho de Melo 99361c99a6SArnaldo Carvalho de Melo evlist->nr_entries = 0; 100361c99a6SArnaldo Carvalho de Melo } 101361c99a6SArnaldo Carvalho de Melo 102ef1d1af2SArnaldo Carvalho de Melo void perf_evlist__exit(struct perf_evlist *evlist) 103ef1d1af2SArnaldo Carvalho de Melo { 10404662523SArnaldo Carvalho de Melo zfree(&evlist->mmap); 10504662523SArnaldo Carvalho de Melo zfree(&evlist->pollfd); 106ef1d1af2SArnaldo Carvalho de Melo } 107ef1d1af2SArnaldo Carvalho de Melo 108361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist) 109361c99a6SArnaldo Carvalho de Melo { 110361c99a6SArnaldo Carvalho de Melo perf_evlist__purge(evlist); 111ef1d1af2SArnaldo Carvalho de Melo perf_evlist__exit(evlist); 112361c99a6SArnaldo Carvalho de Melo free(evlist); 113361c99a6SArnaldo Carvalho de Melo } 114361c99a6SArnaldo Carvalho de Melo 115361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 116361c99a6SArnaldo Carvalho de Melo { 117361c99a6SArnaldo Carvalho de Melo list_add_tail(&entry->node, &evlist->entries); 118ef503831SArnaldo Carvalho de Melo entry->idx = evlist->nr_entries; 119ef503831SArnaldo Carvalho de Melo 12075562573SAdrian Hunter if (!evlist->nr_entries++) 12175562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 122361c99a6SArnaldo Carvalho de Melo } 123361c99a6SArnaldo Carvalho de Melo 1240529bc1fSJiri Olsa void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 12550d08e47SArnaldo Carvalho de Melo struct list_head *list, 12650d08e47SArnaldo Carvalho de Melo int nr_entries) 12750d08e47SArnaldo Carvalho de Melo { 12875562573SAdrian Hunter bool set_id_pos = !evlist->nr_entries; 12975562573SAdrian Hunter 13050d08e47SArnaldo Carvalho de Melo list_splice_tail(list, &evlist->entries); 13150d08e47SArnaldo Carvalho de Melo evlist->nr_entries += nr_entries; 13275562573SAdrian Hunter if (set_id_pos) 13375562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 13450d08e47SArnaldo Carvalho de Melo } 13550d08e47SArnaldo Carvalho de Melo 13663dab225SArnaldo Carvalho de Melo void __perf_evlist__set_leader(struct list_head *list) 13763dab225SArnaldo Carvalho de Melo { 13863dab225SArnaldo Carvalho de Melo struct perf_evsel *evsel, *leader; 13963dab225SArnaldo Carvalho de Melo 14063dab225SArnaldo Carvalho de Melo leader = list_entry(list->next, struct perf_evsel, node); 14197f63e4aSNamhyung Kim evsel = list_entry(list->prev, struct perf_evsel, node); 14297f63e4aSNamhyung Kim 14397f63e4aSNamhyung Kim leader->nr_members = evsel->idx - leader->idx + 1; 14463dab225SArnaldo Carvalho de Melo 14563dab225SArnaldo Carvalho de Melo list_for_each_entry(evsel, list, node) { 14663dab225SArnaldo Carvalho de Melo evsel->leader = leader; 14763dab225SArnaldo Carvalho de Melo } 14863dab225SArnaldo Carvalho de Melo } 14963dab225SArnaldo Carvalho de Melo 15063dab225SArnaldo Carvalho de Melo void perf_evlist__set_leader(struct perf_evlist *evlist) 1516a4bb04cSJiri Olsa { 15297f63e4aSNamhyung Kim if (evlist->nr_entries) { 15397f63e4aSNamhyung Kim evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; 15463dab225SArnaldo Carvalho de Melo __perf_evlist__set_leader(&evlist->entries); 1556a4bb04cSJiri Olsa } 15697f63e4aSNamhyung Kim } 1576a4bb04cSJiri Olsa 158361c99a6SArnaldo Carvalho de Melo int perf_evlist__add_default(struct perf_evlist *evlist) 159361c99a6SArnaldo Carvalho de Melo { 160361c99a6SArnaldo Carvalho de Melo struct perf_event_attr attr = { 161361c99a6SArnaldo Carvalho de Melo .type = PERF_TYPE_HARDWARE, 162361c99a6SArnaldo Carvalho de Melo .config = PERF_COUNT_HW_CPU_CYCLES, 163361c99a6SArnaldo Carvalho de Melo }; 1641aed2671SJoerg Roedel struct perf_evsel *evsel; 165361c99a6SArnaldo Carvalho de Melo 1661aed2671SJoerg Roedel event_attr_init(&attr); 1671aed2671SJoerg Roedel 168ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new(&attr); 169361c99a6SArnaldo Carvalho de Melo if (evsel == NULL) 170cc2d86b0SStephane Eranian goto error; 171cc2d86b0SStephane Eranian 172cc2d86b0SStephane Eranian /* use strdup() because free(evsel) assumes name is allocated */ 173cc2d86b0SStephane Eranian evsel->name = strdup("cycles"); 174cc2d86b0SStephane Eranian if (!evsel->name) 175cc2d86b0SStephane Eranian goto error_free; 176361c99a6SArnaldo Carvalho de Melo 177361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 178361c99a6SArnaldo Carvalho de Melo return 0; 179cc2d86b0SStephane Eranian error_free: 180cc2d86b0SStephane Eranian perf_evsel__delete(evsel); 181cc2d86b0SStephane Eranian error: 182cc2d86b0SStephane Eranian return -ENOMEM; 183361c99a6SArnaldo Carvalho de Melo } 1845c581041SArnaldo Carvalho de Melo 185e60fc847SArnaldo Carvalho de Melo static int perf_evlist__add_attrs(struct perf_evlist *evlist, 18650d08e47SArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 18750d08e47SArnaldo Carvalho de Melo { 18850d08e47SArnaldo Carvalho de Melo struct perf_evsel *evsel, *n; 18950d08e47SArnaldo Carvalho de Melo LIST_HEAD(head); 19050d08e47SArnaldo Carvalho de Melo size_t i; 19150d08e47SArnaldo Carvalho de Melo 19250d08e47SArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) { 193ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); 19450d08e47SArnaldo Carvalho de Melo if (evsel == NULL) 19550d08e47SArnaldo Carvalho de Melo goto out_delete_partial_list; 19650d08e47SArnaldo Carvalho de Melo list_add_tail(&evsel->node, &head); 19750d08e47SArnaldo Carvalho de Melo } 19850d08e47SArnaldo Carvalho de Melo 19950d08e47SArnaldo Carvalho de Melo perf_evlist__splice_list_tail(evlist, &head, nr_attrs); 20050d08e47SArnaldo Carvalho de Melo 20150d08e47SArnaldo Carvalho de Melo return 0; 20250d08e47SArnaldo Carvalho de Melo 20350d08e47SArnaldo Carvalho de Melo out_delete_partial_list: 20450d08e47SArnaldo Carvalho de Melo list_for_each_entry_safe(evsel, n, &head, node) 20550d08e47SArnaldo Carvalho de Melo perf_evsel__delete(evsel); 20650d08e47SArnaldo Carvalho de Melo return -1; 20750d08e47SArnaldo Carvalho de Melo } 20850d08e47SArnaldo Carvalho de Melo 20979695e1bSArnaldo Carvalho de Melo int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 21079695e1bSArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 21179695e1bSArnaldo Carvalho de Melo { 21279695e1bSArnaldo Carvalho de Melo size_t i; 21379695e1bSArnaldo Carvalho de Melo 21479695e1bSArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) 21579695e1bSArnaldo Carvalho de Melo event_attr_init(attrs + i); 21679695e1bSArnaldo Carvalho de Melo 21779695e1bSArnaldo Carvalho de Melo return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 21879695e1bSArnaldo Carvalho de Melo } 21979695e1bSArnaldo Carvalho de Melo 220da378962SArnaldo Carvalho de Melo struct perf_evsel * 221ee29be62SArnaldo Carvalho de Melo perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 222ee29be62SArnaldo Carvalho de Melo { 223ee29be62SArnaldo Carvalho de Melo struct perf_evsel *evsel; 224ee29be62SArnaldo Carvalho de Melo 225ee29be62SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 226ee29be62SArnaldo Carvalho de Melo if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 227ee29be62SArnaldo Carvalho de Melo (int)evsel->attr.config == id) 228ee29be62SArnaldo Carvalho de Melo return evsel; 229ee29be62SArnaldo Carvalho de Melo } 230ee29be62SArnaldo Carvalho de Melo 231ee29be62SArnaldo Carvalho de Melo return NULL; 232ee29be62SArnaldo Carvalho de Melo } 233ee29be62SArnaldo Carvalho de Melo 234a2f2804aSDavid Ahern struct perf_evsel * 235a2f2804aSDavid Ahern perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, 236a2f2804aSDavid Ahern const char *name) 237a2f2804aSDavid Ahern { 238a2f2804aSDavid Ahern struct perf_evsel *evsel; 239a2f2804aSDavid Ahern 240a2f2804aSDavid Ahern list_for_each_entry(evsel, &evlist->entries, node) { 241a2f2804aSDavid Ahern if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && 242a2f2804aSDavid Ahern (strcmp(evsel->name, name) == 0)) 243a2f2804aSDavid Ahern return evsel; 244a2f2804aSDavid Ahern } 245a2f2804aSDavid Ahern 246a2f2804aSDavid Ahern return NULL; 247a2f2804aSDavid Ahern } 248a2f2804aSDavid Ahern 24939876e7dSArnaldo Carvalho de Melo int perf_evlist__add_newtp(struct perf_evlist *evlist, 25039876e7dSArnaldo Carvalho de Melo const char *sys, const char *name, void *handler) 25139876e7dSArnaldo Carvalho de Melo { 252ef503831SArnaldo Carvalho de Melo struct perf_evsel *evsel = perf_evsel__newtp(sys, name); 25339876e7dSArnaldo Carvalho de Melo 25439876e7dSArnaldo Carvalho de Melo if (evsel == NULL) 25539876e7dSArnaldo Carvalho de Melo return -1; 25639876e7dSArnaldo Carvalho de Melo 257744a9719SArnaldo Carvalho de Melo evsel->handler = handler; 25839876e7dSArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 25939876e7dSArnaldo Carvalho de Melo return 0; 26039876e7dSArnaldo Carvalho de Melo } 26139876e7dSArnaldo Carvalho de Melo 2624152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist) 2634152ab37SArnaldo Carvalho de Melo { 2644152ab37SArnaldo Carvalho de Melo int cpu, thread; 2654152ab37SArnaldo Carvalho de Melo struct perf_evsel *pos; 266b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 267b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 2684152ab37SArnaldo Carvalho de Melo 269b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 2704152ab37SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 271395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 2723fe4430dSJiri Olsa continue; 273b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 27455da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 27555da8005SNamhyung Kim PERF_EVENT_IOC_DISABLE, 0); 2764152ab37SArnaldo Carvalho de Melo } 2774152ab37SArnaldo Carvalho de Melo } 2784152ab37SArnaldo Carvalho de Melo } 2794152ab37SArnaldo Carvalho de Melo 280764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist) 281764e16a3SDavid Ahern { 282764e16a3SDavid Ahern int cpu, thread; 283764e16a3SDavid Ahern struct perf_evsel *pos; 284b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 285b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 286764e16a3SDavid Ahern 287b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 288764e16a3SDavid Ahern list_for_each_entry(pos, &evlist->entries, node) { 289395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 2903fe4430dSJiri Olsa continue; 291b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 29255da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 29355da8005SNamhyung Kim PERF_EVENT_IOC_ENABLE, 0); 294764e16a3SDavid Ahern } 295764e16a3SDavid Ahern } 296764e16a3SDavid Ahern } 297764e16a3SDavid Ahern 298395c3070SAdrian Hunter int perf_evlist__disable_event(struct perf_evlist *evlist, 299395c3070SAdrian Hunter struct perf_evsel *evsel) 300395c3070SAdrian Hunter { 301395c3070SAdrian Hunter int cpu, thread, err; 302395c3070SAdrian Hunter 303395c3070SAdrian Hunter if (!evsel->fd) 304395c3070SAdrian Hunter return 0; 305395c3070SAdrian Hunter 306395c3070SAdrian Hunter for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 307395c3070SAdrian Hunter for (thread = 0; thread < evlist->threads->nr; thread++) { 308395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 309395c3070SAdrian Hunter PERF_EVENT_IOC_DISABLE, 0); 310395c3070SAdrian Hunter if (err) 311395c3070SAdrian Hunter return err; 312395c3070SAdrian Hunter } 313395c3070SAdrian Hunter } 314395c3070SAdrian Hunter return 0; 315395c3070SAdrian Hunter } 316395c3070SAdrian Hunter 317395c3070SAdrian Hunter int perf_evlist__enable_event(struct perf_evlist *evlist, 318395c3070SAdrian Hunter struct perf_evsel *evsel) 319395c3070SAdrian Hunter { 320395c3070SAdrian Hunter int cpu, thread, err; 321395c3070SAdrian Hunter 322395c3070SAdrian Hunter if (!evsel->fd) 323395c3070SAdrian Hunter return -EINVAL; 324395c3070SAdrian Hunter 325395c3070SAdrian Hunter for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 326395c3070SAdrian Hunter for (thread = 0; thread < evlist->threads->nr; thread++) { 327395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 328395c3070SAdrian Hunter PERF_EVENT_IOC_ENABLE, 0); 329395c3070SAdrian Hunter if (err) 330395c3070SAdrian Hunter return err; 331395c3070SAdrian Hunter } 332395c3070SAdrian Hunter } 333395c3070SAdrian Hunter return 0; 334395c3070SAdrian Hunter } 335395c3070SAdrian Hunter 336806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 3375c581041SArnaldo Carvalho de Melo { 338b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 339b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 340b3a319d5SNamhyung Kim int nfds = nr_cpus * nr_threads * evlist->nr_entries; 3415c581041SArnaldo Carvalho de Melo evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 3425c581041SArnaldo Carvalho de Melo return evlist->pollfd != NULL ? 0 : -ENOMEM; 3435c581041SArnaldo Carvalho de Melo } 34470082dd9SArnaldo Carvalho de Melo 34570082dd9SArnaldo Carvalho de Melo void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 34670082dd9SArnaldo Carvalho de Melo { 34770082dd9SArnaldo Carvalho de Melo fcntl(fd, F_SETFL, O_NONBLOCK); 34870082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].fd = fd; 34970082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].events = POLLIN; 35070082dd9SArnaldo Carvalho de Melo evlist->nr_fds++; 35170082dd9SArnaldo Carvalho de Melo } 35270db7533SArnaldo Carvalho de Melo 353a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist, 354a91e5431SArnaldo Carvalho de Melo struct perf_evsel *evsel, 3553d3b5e95SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 3563d3b5e95SArnaldo Carvalho de Melo { 3573d3b5e95SArnaldo Carvalho de Melo int hash; 3583d3b5e95SArnaldo Carvalho de Melo struct perf_sample_id *sid = SID(evsel, cpu, thread); 3593d3b5e95SArnaldo Carvalho de Melo 3603d3b5e95SArnaldo Carvalho de Melo sid->id = id; 3613d3b5e95SArnaldo Carvalho de Melo sid->evsel = evsel; 3623d3b5e95SArnaldo Carvalho de Melo hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); 3633d3b5e95SArnaldo Carvalho de Melo hlist_add_head(&sid->node, &evlist->heads[hash]); 3643d3b5e95SArnaldo Carvalho de Melo } 3653d3b5e95SArnaldo Carvalho de Melo 366a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 367a91e5431SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 368a91e5431SArnaldo Carvalho de Melo { 369a91e5431SArnaldo Carvalho de Melo perf_evlist__id_hash(evlist, evsel, cpu, thread, id); 370a91e5431SArnaldo Carvalho de Melo evsel->id[evsel->ids++] = id; 371a91e5431SArnaldo Carvalho de Melo } 372a91e5431SArnaldo Carvalho de Melo 373a91e5431SArnaldo Carvalho de Melo static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 3743d3b5e95SArnaldo Carvalho de Melo struct perf_evsel *evsel, 375f8a95309SArnaldo Carvalho de Melo int cpu, int thread, int fd) 376f8a95309SArnaldo Carvalho de Melo { 377f8a95309SArnaldo Carvalho de Melo u64 read_data[4] = { 0, }; 3783d3b5e95SArnaldo Carvalho de Melo int id_idx = 1; /* The first entry is the counter value */ 379e2b5abe0SJiri Olsa u64 id; 380e2b5abe0SJiri Olsa int ret; 381e2b5abe0SJiri Olsa 382e2b5abe0SJiri Olsa ret = ioctl(fd, PERF_EVENT_IOC_ID, &id); 383e2b5abe0SJiri Olsa if (!ret) 384e2b5abe0SJiri Olsa goto add; 385e2b5abe0SJiri Olsa 386e2b5abe0SJiri Olsa if (errno != ENOTTY) 387e2b5abe0SJiri Olsa return -1; 388e2b5abe0SJiri Olsa 389e2b5abe0SJiri Olsa /* Legacy way to get event id.. All hail to old kernels! */ 390f8a95309SArnaldo Carvalho de Melo 391c4861afeSJiri Olsa /* 392c4861afeSJiri Olsa * This way does not work with group format read, so bail 393c4861afeSJiri Olsa * out in that case. 394c4861afeSJiri Olsa */ 395c4861afeSJiri Olsa if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP) 396c4861afeSJiri Olsa return -1; 397c4861afeSJiri Olsa 398f8a95309SArnaldo Carvalho de Melo if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 399f8a95309SArnaldo Carvalho de Melo read(fd, &read_data, sizeof(read_data)) == -1) 400f8a95309SArnaldo Carvalho de Melo return -1; 401f8a95309SArnaldo Carvalho de Melo 402f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 403f8a95309SArnaldo Carvalho de Melo ++id_idx; 404f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 405f8a95309SArnaldo Carvalho de Melo ++id_idx; 406f8a95309SArnaldo Carvalho de Melo 407e2b5abe0SJiri Olsa id = read_data[id_idx]; 408e2b5abe0SJiri Olsa 409e2b5abe0SJiri Olsa add: 410e2b5abe0SJiri Olsa perf_evlist__id_add(evlist, evsel, cpu, thread, id); 411f8a95309SArnaldo Carvalho de Melo return 0; 412f8a95309SArnaldo Carvalho de Melo } 413f8a95309SArnaldo Carvalho de Melo 414932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 41570db7533SArnaldo Carvalho de Melo { 41670db7533SArnaldo Carvalho de Melo struct hlist_head *head; 41770db7533SArnaldo Carvalho de Melo struct perf_sample_id *sid; 41870db7533SArnaldo Carvalho de Melo int hash; 41970db7533SArnaldo Carvalho de Melo 42070db7533SArnaldo Carvalho de Melo hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 42170db7533SArnaldo Carvalho de Melo head = &evlist->heads[hash]; 42270db7533SArnaldo Carvalho de Melo 423b67bfe0dSSasha Levin hlist_for_each_entry(sid, head, node) 42470db7533SArnaldo Carvalho de Melo if (sid->id == id) 425932a3594SJiri Olsa return sid; 426932a3594SJiri Olsa 427932a3594SJiri Olsa return NULL; 428932a3594SJiri Olsa } 429932a3594SJiri Olsa 430932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 431932a3594SJiri Olsa { 432932a3594SJiri Olsa struct perf_sample_id *sid; 433932a3594SJiri Olsa 434932a3594SJiri Olsa if (evlist->nr_entries == 1) 435932a3594SJiri Olsa return perf_evlist__first(evlist); 436932a3594SJiri Olsa 437932a3594SJiri Olsa sid = perf_evlist__id2sid(evlist, id); 438932a3594SJiri Olsa if (sid) 43970db7533SArnaldo Carvalho de Melo return sid->evsel; 44030e68bccSNamhyung Kim 44130e68bccSNamhyung Kim if (!perf_evlist__sample_id_all(evlist)) 4420c21f736SArnaldo Carvalho de Melo return perf_evlist__first(evlist); 44330e68bccSNamhyung Kim 44470db7533SArnaldo Carvalho de Melo return NULL; 44570db7533SArnaldo Carvalho de Melo } 44604391debSArnaldo Carvalho de Melo 44775562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist, 44875562573SAdrian Hunter union perf_event *event, u64 *id) 44975562573SAdrian Hunter { 45075562573SAdrian Hunter const u64 *array = event->sample.array; 45175562573SAdrian Hunter ssize_t n; 45275562573SAdrian Hunter 45375562573SAdrian Hunter n = (event->header.size - sizeof(event->header)) >> 3; 45475562573SAdrian Hunter 45575562573SAdrian Hunter if (event->header.type == PERF_RECORD_SAMPLE) { 45675562573SAdrian Hunter if (evlist->id_pos >= n) 45775562573SAdrian Hunter return -1; 45875562573SAdrian Hunter *id = array[evlist->id_pos]; 45975562573SAdrian Hunter } else { 46075562573SAdrian Hunter if (evlist->is_pos > n) 46175562573SAdrian Hunter return -1; 46275562573SAdrian Hunter n -= evlist->is_pos; 46375562573SAdrian Hunter *id = array[n]; 46475562573SAdrian Hunter } 46575562573SAdrian Hunter return 0; 46675562573SAdrian Hunter } 46775562573SAdrian Hunter 46875562573SAdrian Hunter static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 46975562573SAdrian Hunter union perf_event *event) 47075562573SAdrian Hunter { 47198be6966SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 47275562573SAdrian Hunter struct hlist_head *head; 47375562573SAdrian Hunter struct perf_sample_id *sid; 47475562573SAdrian Hunter int hash; 47575562573SAdrian Hunter u64 id; 47675562573SAdrian Hunter 47775562573SAdrian Hunter if (evlist->nr_entries == 1) 47898be6966SAdrian Hunter return first; 47998be6966SAdrian Hunter 48098be6966SAdrian Hunter if (!first->attr.sample_id_all && 48198be6966SAdrian Hunter event->header.type != PERF_RECORD_SAMPLE) 48298be6966SAdrian Hunter return first; 48375562573SAdrian Hunter 48475562573SAdrian Hunter if (perf_evlist__event2id(evlist, event, &id)) 48575562573SAdrian Hunter return NULL; 48675562573SAdrian Hunter 48775562573SAdrian Hunter /* Synthesized events have an id of zero */ 48875562573SAdrian Hunter if (!id) 48998be6966SAdrian Hunter return first; 49075562573SAdrian Hunter 49175562573SAdrian Hunter hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 49275562573SAdrian Hunter head = &evlist->heads[hash]; 49375562573SAdrian Hunter 49475562573SAdrian Hunter hlist_for_each_entry(sid, head, node) { 49575562573SAdrian Hunter if (sid->id == id) 49675562573SAdrian Hunter return sid->evsel; 49775562573SAdrian Hunter } 49875562573SAdrian Hunter return NULL; 49975562573SAdrian Hunter } 50075562573SAdrian Hunter 501aece948fSArnaldo Carvalho de Melo union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 50204391debSArnaldo Carvalho de Melo { 503aece948fSArnaldo Carvalho de Melo struct perf_mmap *md = &evlist->mmap[idx]; 50404391debSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 50504391debSArnaldo Carvalho de Melo unsigned int old = md->prev; 50604391debSArnaldo Carvalho de Melo unsigned char *data = md->base + page_size; 5078115d60cSArnaldo Carvalho de Melo union perf_event *event = NULL; 50804391debSArnaldo Carvalho de Melo 5097bb41152SArnaldo Carvalho de Melo if (evlist->overwrite) { 51004391debSArnaldo Carvalho de Melo /* 51104391debSArnaldo Carvalho de Melo * If we're further behind than half the buffer, there's a chance 51204391debSArnaldo Carvalho de Melo * the writer will bite our tail and mess up the samples under us. 51304391debSArnaldo Carvalho de Melo * 51404391debSArnaldo Carvalho de Melo * If we somehow ended up ahead of the head, we got messed up. 51504391debSArnaldo Carvalho de Melo * 51604391debSArnaldo Carvalho de Melo * In either case, truncate and restart at head. 51704391debSArnaldo Carvalho de Melo */ 5187bb41152SArnaldo Carvalho de Melo int diff = head - old; 51904391debSArnaldo Carvalho de Melo if (diff > md->mask / 2 || diff < 0) { 52004391debSArnaldo Carvalho de Melo fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 52104391debSArnaldo Carvalho de Melo 52204391debSArnaldo Carvalho de Melo /* 52304391debSArnaldo Carvalho de Melo * head points to a known good entry, start there. 52404391debSArnaldo Carvalho de Melo */ 52504391debSArnaldo Carvalho de Melo old = head; 52604391debSArnaldo Carvalho de Melo } 5277bb41152SArnaldo Carvalho de Melo } 52804391debSArnaldo Carvalho de Melo 52904391debSArnaldo Carvalho de Melo if (old != head) { 53004391debSArnaldo Carvalho de Melo size_t size; 53104391debSArnaldo Carvalho de Melo 5328115d60cSArnaldo Carvalho de Melo event = (union perf_event *)&data[old & md->mask]; 53304391debSArnaldo Carvalho de Melo size = event->header.size; 53404391debSArnaldo Carvalho de Melo 53504391debSArnaldo Carvalho de Melo /* 53604391debSArnaldo Carvalho de Melo * Event straddles the mmap boundary -- header should always 53704391debSArnaldo Carvalho de Melo * be inside due to u64 alignment of output. 53804391debSArnaldo Carvalho de Melo */ 53904391debSArnaldo Carvalho de Melo if ((old & md->mask) + size != ((old + size) & md->mask)) { 54004391debSArnaldo Carvalho de Melo unsigned int offset = old; 54104391debSArnaldo Carvalho de Melo unsigned int len = min(sizeof(*event), size), cpy; 542a65cb4b9SJiri Olsa void *dst = md->event_copy; 54304391debSArnaldo Carvalho de Melo 54404391debSArnaldo Carvalho de Melo do { 54504391debSArnaldo Carvalho de Melo cpy = min(md->mask + 1 - (offset & md->mask), len); 54604391debSArnaldo Carvalho de Melo memcpy(dst, &data[offset & md->mask], cpy); 54704391debSArnaldo Carvalho de Melo offset += cpy; 54804391debSArnaldo Carvalho de Melo dst += cpy; 54904391debSArnaldo Carvalho de Melo len -= cpy; 55004391debSArnaldo Carvalho de Melo } while (len); 55104391debSArnaldo Carvalho de Melo 552a65cb4b9SJiri Olsa event = (union perf_event *) md->event_copy; 55304391debSArnaldo Carvalho de Melo } 55404391debSArnaldo Carvalho de Melo 55504391debSArnaldo Carvalho de Melo old += size; 55604391debSArnaldo Carvalho de Melo } 55704391debSArnaldo Carvalho de Melo 55804391debSArnaldo Carvalho de Melo md->prev = old; 5597bb41152SArnaldo Carvalho de Melo 56004391debSArnaldo Carvalho de Melo return event; 56104391debSArnaldo Carvalho de Melo } 562f8a95309SArnaldo Carvalho de Melo 5638e50d384SZhouyi Zhou void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 5648e50d384SZhouyi Zhou { 5658e50d384SZhouyi Zhou if (!evlist->overwrite) { 5668e50d384SZhouyi Zhou struct perf_mmap *md = &evlist->mmap[idx]; 5678e50d384SZhouyi Zhou unsigned int old = md->prev; 5688e50d384SZhouyi Zhou 5698e50d384SZhouyi Zhou perf_mmap__write_tail(md, old); 5708e50d384SZhouyi Zhou } 5718e50d384SZhouyi Zhou } 5728e50d384SZhouyi Zhou 57393edcbd9SAdrian Hunter static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 57493edcbd9SAdrian Hunter { 57593edcbd9SAdrian Hunter if (evlist->mmap[idx].base != NULL) { 57693edcbd9SAdrian Hunter munmap(evlist->mmap[idx].base, evlist->mmap_len); 57793edcbd9SAdrian Hunter evlist->mmap[idx].base = NULL; 57893edcbd9SAdrian Hunter } 57993edcbd9SAdrian Hunter } 58093edcbd9SAdrian Hunter 5817e2ed097SArnaldo Carvalho de Melo void perf_evlist__munmap(struct perf_evlist *evlist) 582f8a95309SArnaldo Carvalho de Melo { 583aece948fSArnaldo Carvalho de Melo int i; 584f8a95309SArnaldo Carvalho de Melo 58593edcbd9SAdrian Hunter for (i = 0; i < evlist->nr_mmaps; i++) 58693edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, i); 587aece948fSArnaldo Carvalho de Melo 58804662523SArnaldo Carvalho de Melo zfree(&evlist->mmap); 589f8a95309SArnaldo Carvalho de Melo } 590f8a95309SArnaldo Carvalho de Melo 591806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 592f8a95309SArnaldo Carvalho de Melo { 593a14bb7a6SArnaldo Carvalho de Melo evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 594ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(evlist->cpus)) 595b3a319d5SNamhyung Kim evlist->nr_mmaps = thread_map__nr(evlist->threads); 596aece948fSArnaldo Carvalho de Melo evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 597f8a95309SArnaldo Carvalho de Melo return evlist->mmap != NULL ? 0 : -ENOMEM; 598f8a95309SArnaldo Carvalho de Melo } 599f8a95309SArnaldo Carvalho de Melo 600bccdaba0SArnaldo Carvalho de Melo static int __perf_evlist__mmap(struct perf_evlist *evlist, 601aece948fSArnaldo Carvalho de Melo int idx, int prot, int mask, int fd) 602f8a95309SArnaldo Carvalho de Melo { 603aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].prev = 0; 604aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].mask = mask; 605aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 606f8a95309SArnaldo Carvalho de Melo MAP_SHARED, fd, 0); 607301b195dSNelson Elhage if (evlist->mmap[idx].base == MAP_FAILED) { 60802635965SAdrian Hunter pr_debug2("failed to mmap perf event ring buffer, error %d\n", 60902635965SAdrian Hunter errno); 610301b195dSNelson Elhage evlist->mmap[idx].base = NULL; 611f8a95309SArnaldo Carvalho de Melo return -1; 612301b195dSNelson Elhage } 613f8a95309SArnaldo Carvalho de Melo 614f8a95309SArnaldo Carvalho de Melo perf_evlist__add_pollfd(evlist, fd); 615f8a95309SArnaldo Carvalho de Melo return 0; 616f8a95309SArnaldo Carvalho de Melo } 617f8a95309SArnaldo Carvalho de Melo 61804e21314SAdrian Hunter static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 61904e21314SAdrian Hunter int prot, int mask, int cpu, int thread, 62004e21314SAdrian Hunter int *output) 621aece948fSArnaldo Carvalho de Melo { 622aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 62304e21314SAdrian Hunter 62404e21314SAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) { 62504e21314SAdrian Hunter int fd = FD(evsel, cpu, thread); 62604e21314SAdrian Hunter 62704e21314SAdrian Hunter if (*output == -1) { 62804e21314SAdrian Hunter *output = fd; 62904e21314SAdrian Hunter if (__perf_evlist__mmap(evlist, idx, prot, mask, 63004e21314SAdrian Hunter *output) < 0) 63104e21314SAdrian Hunter return -1; 63204e21314SAdrian Hunter } else { 63304e21314SAdrian Hunter if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 63404e21314SAdrian Hunter return -1; 63504e21314SAdrian Hunter } 63604e21314SAdrian Hunter 63704e21314SAdrian Hunter if ((evsel->attr.read_format & PERF_FORMAT_ID) && 63804e21314SAdrian Hunter perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 63904e21314SAdrian Hunter return -1; 64004e21314SAdrian Hunter } 64104e21314SAdrian Hunter 64204e21314SAdrian Hunter return 0; 64304e21314SAdrian Hunter } 64404e21314SAdrian Hunter 64504e21314SAdrian Hunter static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, 64604e21314SAdrian Hunter int mask) 64704e21314SAdrian Hunter { 648aece948fSArnaldo Carvalho de Melo int cpu, thread; 649b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 650b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 651aece948fSArnaldo Carvalho de Melo 652e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per cpu\n"); 653b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 654aece948fSArnaldo Carvalho de Melo int output = -1; 655aece948fSArnaldo Carvalho de Melo 656b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 65704e21314SAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask, 65804e21314SAdrian Hunter cpu, thread, &output)) 659aece948fSArnaldo Carvalho de Melo goto out_unmap; 660aece948fSArnaldo Carvalho de Melo } 661aece948fSArnaldo Carvalho de Melo } 662aece948fSArnaldo Carvalho de Melo 663aece948fSArnaldo Carvalho de Melo return 0; 664aece948fSArnaldo Carvalho de Melo 665aece948fSArnaldo Carvalho de Melo out_unmap: 66693edcbd9SAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) 66793edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, cpu); 668aece948fSArnaldo Carvalho de Melo return -1; 669aece948fSArnaldo Carvalho de Melo } 670aece948fSArnaldo Carvalho de Melo 67104e21314SAdrian Hunter static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, 67204e21314SAdrian Hunter int mask) 673aece948fSArnaldo Carvalho de Melo { 674aece948fSArnaldo Carvalho de Melo int thread; 675b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 676aece948fSArnaldo Carvalho de Melo 677e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per thread\n"); 678b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 679aece948fSArnaldo Carvalho de Melo int output = -1; 680aece948fSArnaldo Carvalho de Melo 68104e21314SAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0, 68204e21314SAdrian Hunter thread, &output)) 683aece948fSArnaldo Carvalho de Melo goto out_unmap; 684aece948fSArnaldo Carvalho de Melo } 685aece948fSArnaldo Carvalho de Melo 686aece948fSArnaldo Carvalho de Melo return 0; 687aece948fSArnaldo Carvalho de Melo 688aece948fSArnaldo Carvalho de Melo out_unmap: 68993edcbd9SAdrian Hunter for (thread = 0; thread < nr_threads; thread++) 69093edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, thread); 691aece948fSArnaldo Carvalho de Melo return -1; 692aece948fSArnaldo Carvalho de Melo } 693aece948fSArnaldo Carvalho de Melo 694994a1f78SJiri Olsa static size_t perf_evlist__mmap_size(unsigned long pages) 695994a1f78SJiri Olsa { 696994a1f78SJiri Olsa /* 512 kiB: default amount of unprivileged mlocked memory */ 697994a1f78SJiri Olsa if (pages == UINT_MAX) 698994a1f78SJiri Olsa pages = (512 * 1024) / page_size; 699994a1f78SJiri Olsa else if (!is_power_of_2(pages)) 700994a1f78SJiri Olsa return 0; 701994a1f78SJiri Olsa 702994a1f78SJiri Olsa return (pages + 1) * page_size; 703994a1f78SJiri Olsa } 704994a1f78SJiri Olsa 70533c2dcfdSDavid Ahern static long parse_pages_arg(const char *str, unsigned long min, 70633c2dcfdSDavid Ahern unsigned long max) 707994a1f78SJiri Olsa { 7082fbe4abeSAdrian Hunter unsigned long pages, val; 70927050f53SJiri Olsa static struct parse_tag tags[] = { 71027050f53SJiri Olsa { .tag = 'B', .mult = 1 }, 71127050f53SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 71227050f53SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 71327050f53SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 71427050f53SJiri Olsa { .tag = 0 }, 71527050f53SJiri Olsa }; 716994a1f78SJiri Olsa 7178973504bSDavid Ahern if (str == NULL) 71833c2dcfdSDavid Ahern return -EINVAL; 7198973504bSDavid Ahern 72027050f53SJiri Olsa val = parse_tag_value(str, tags); 7212fbe4abeSAdrian Hunter if (val != (unsigned long) -1) { 72227050f53SJiri Olsa /* we got file size value */ 72327050f53SJiri Olsa pages = PERF_ALIGN(val, page_size) / page_size; 72427050f53SJiri Olsa } else { 72527050f53SJiri Olsa /* we got pages count value */ 72627050f53SJiri Olsa char *eptr; 727994a1f78SJiri Olsa pages = strtoul(str, &eptr, 10); 72833c2dcfdSDavid Ahern if (*eptr != '\0') 72933c2dcfdSDavid Ahern return -EINVAL; 73027050f53SJiri Olsa } 731994a1f78SJiri Olsa 7322bcab6c1SAdrian Hunter if (pages == 0 && min == 0) { 73333c2dcfdSDavid Ahern /* leave number of pages at 0 */ 7341dbfa938SAdrian Hunter } else if (!is_power_of_2(pages)) { 73533c2dcfdSDavid Ahern /* round pages up to next power of 2 */ 7361dbfa938SAdrian Hunter pages = next_pow2_l(pages); 7371dbfa938SAdrian Hunter if (!pages) 7381dbfa938SAdrian Hunter return -EINVAL; 7399639837eSDavid Ahern pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 7409639837eSDavid Ahern pages * page_size, pages); 7412fbe4abeSAdrian Hunter } 7422fbe4abeSAdrian Hunter 74333c2dcfdSDavid Ahern if (pages > max) 74433c2dcfdSDavid Ahern return -EINVAL; 74533c2dcfdSDavid Ahern 74633c2dcfdSDavid Ahern return pages; 74733c2dcfdSDavid Ahern } 74833c2dcfdSDavid Ahern 74933c2dcfdSDavid Ahern int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, 75033c2dcfdSDavid Ahern int unset __maybe_unused) 75133c2dcfdSDavid Ahern { 75233c2dcfdSDavid Ahern unsigned int *mmap_pages = opt->value; 75333c2dcfdSDavid Ahern unsigned long max = UINT_MAX; 75433c2dcfdSDavid Ahern long pages; 75533c2dcfdSDavid Ahern 756f5ae9c42SAdrian Hunter if (max > SIZE_MAX / page_size) 75733c2dcfdSDavid Ahern max = SIZE_MAX / page_size; 75833c2dcfdSDavid Ahern 75933c2dcfdSDavid Ahern pages = parse_pages_arg(str, 1, max); 76033c2dcfdSDavid Ahern if (pages < 0) { 76133c2dcfdSDavid Ahern pr_err("Invalid argument for --mmap_pages/-m\n"); 762994a1f78SJiri Olsa return -1; 763994a1f78SJiri Olsa } 764994a1f78SJiri Olsa 765994a1f78SJiri Olsa *mmap_pages = pages; 766994a1f78SJiri Olsa return 0; 767994a1f78SJiri Olsa } 768994a1f78SJiri Olsa 769c83fa7f2SAdrian Hunter /** 770c83fa7f2SAdrian Hunter * perf_evlist__mmap - Create mmaps to receive events. 771c83fa7f2SAdrian Hunter * @evlist: list of events 772c83fa7f2SAdrian Hunter * @pages: map length in pages 773c83fa7f2SAdrian Hunter * @overwrite: overwrite older events? 774f8a95309SArnaldo Carvalho de Melo * 775c83fa7f2SAdrian Hunter * If @overwrite is %false the user needs to signal event consumption using 776c83fa7f2SAdrian Hunter * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this 777c83fa7f2SAdrian Hunter * automatically. 778f8a95309SArnaldo Carvalho de Melo * 779c83fa7f2SAdrian Hunter * Return: %0 on success, negative error code otherwise. 780f8a95309SArnaldo Carvalho de Melo */ 78150a682ceSArnaldo Carvalho de Melo int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 78250a682ceSArnaldo Carvalho de Melo bool overwrite) 783f8a95309SArnaldo Carvalho de Melo { 784aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 7857e2ed097SArnaldo Carvalho de Melo const struct cpu_map *cpus = evlist->cpus; 7867e2ed097SArnaldo Carvalho de Melo const struct thread_map *threads = evlist->threads; 78750a682ceSArnaldo Carvalho de Melo int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 78850a682ceSArnaldo Carvalho de Melo 7897e2ed097SArnaldo Carvalho de Melo if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 790f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 791f8a95309SArnaldo Carvalho de Melo 7927e2ed097SArnaldo Carvalho de Melo if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 793f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 794f8a95309SArnaldo Carvalho de Melo 795f8a95309SArnaldo Carvalho de Melo evlist->overwrite = overwrite; 796994a1f78SJiri Olsa evlist->mmap_len = perf_evlist__mmap_size(pages); 7972af68ef5SAdrian Hunter pr_debug("mmap size %zuB\n", evlist->mmap_len); 798994a1f78SJiri Olsa mask = evlist->mmap_len - page_size - 1; 799f8a95309SArnaldo Carvalho de Melo 800f8a95309SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 801f8a95309SArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 802a91e5431SArnaldo Carvalho de Melo evsel->sample_id == NULL && 803a14bb7a6SArnaldo Carvalho de Melo perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 804f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 805f8a95309SArnaldo Carvalho de Melo } 806f8a95309SArnaldo Carvalho de Melo 807ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(cpus)) 808aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_thread(evlist, prot, mask); 809f8a95309SArnaldo Carvalho de Melo 810aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_cpu(evlist, prot, mask); 811f8a95309SArnaldo Carvalho de Melo } 8127e2ed097SArnaldo Carvalho de Melo 813602ad878SArnaldo Carvalho de Melo int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 8147e2ed097SArnaldo Carvalho de Melo { 815b809ac10SNamhyung Kim evlist->threads = thread_map__new_str(target->pid, target->tid, 816b809ac10SNamhyung Kim target->uid); 8177e2ed097SArnaldo Carvalho de Melo 8187e2ed097SArnaldo Carvalho de Melo if (evlist->threads == NULL) 8197e2ed097SArnaldo Carvalho de Melo return -1; 8207e2ed097SArnaldo Carvalho de Melo 8219c105fbcSDongsheng Yang if (target__uses_dummy_map(target)) 822d1cb9fceSNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 823879d77d0SNamhyung Kim else 824879d77d0SNamhyung Kim evlist->cpus = cpu_map__new(target->cpu_list); 8257e2ed097SArnaldo Carvalho de Melo 8267e2ed097SArnaldo Carvalho de Melo if (evlist->cpus == NULL) 8277e2ed097SArnaldo Carvalho de Melo goto out_delete_threads; 8287e2ed097SArnaldo Carvalho de Melo 8297e2ed097SArnaldo Carvalho de Melo return 0; 8307e2ed097SArnaldo Carvalho de Melo 8317e2ed097SArnaldo Carvalho de Melo out_delete_threads: 8327e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 8337e2ed097SArnaldo Carvalho de Melo return -1; 8347e2ed097SArnaldo Carvalho de Melo } 8357e2ed097SArnaldo Carvalho de Melo 8367e2ed097SArnaldo Carvalho de Melo void perf_evlist__delete_maps(struct perf_evlist *evlist) 8377e2ed097SArnaldo Carvalho de Melo { 8387e2ed097SArnaldo Carvalho de Melo cpu_map__delete(evlist->cpus); 8397e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 8407e2ed097SArnaldo Carvalho de Melo evlist->cpus = NULL; 8417e2ed097SArnaldo Carvalho de Melo evlist->threads = NULL; 8427e2ed097SArnaldo Carvalho de Melo } 8430a102479SFrederic Weisbecker 8441491a632SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist) 8450a102479SFrederic Weisbecker { 8460a102479SFrederic Weisbecker struct perf_evsel *evsel; 847745cefc5SArnaldo Carvalho de Melo int err = 0; 848745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 849b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 8500a102479SFrederic Weisbecker 8510a102479SFrederic Weisbecker list_for_each_entry(evsel, &evlist->entries, node) { 852745cefc5SArnaldo Carvalho de Melo if (evsel->filter == NULL) 8530a102479SFrederic Weisbecker continue; 854745cefc5SArnaldo Carvalho de Melo 855745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 8560a102479SFrederic Weisbecker if (err) 857745cefc5SArnaldo Carvalho de Melo break; 8580a102479SFrederic Weisbecker } 8590a102479SFrederic Weisbecker 860745cefc5SArnaldo Carvalho de Melo return err; 861745cefc5SArnaldo Carvalho de Melo } 862745cefc5SArnaldo Carvalho de Melo 863745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) 864745cefc5SArnaldo Carvalho de Melo { 865745cefc5SArnaldo Carvalho de Melo struct perf_evsel *evsel; 866745cefc5SArnaldo Carvalho de Melo int err = 0; 867745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 868b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 869745cefc5SArnaldo Carvalho de Melo 870745cefc5SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 871745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); 872745cefc5SArnaldo Carvalho de Melo if (err) 873745cefc5SArnaldo Carvalho de Melo break; 874745cefc5SArnaldo Carvalho de Melo } 875745cefc5SArnaldo Carvalho de Melo 876745cefc5SArnaldo Carvalho de Melo return err; 8770a102479SFrederic Weisbecker } 87874429964SFrederic Weisbecker 8790c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 88074429964SFrederic Weisbecker { 88175562573SAdrian Hunter struct perf_evsel *pos; 882c2a70653SArnaldo Carvalho de Melo 88375562573SAdrian Hunter if (evlist->nr_entries == 1) 88475562573SAdrian Hunter return true; 88575562573SAdrian Hunter 88675562573SAdrian Hunter if (evlist->id_pos < 0 || evlist->is_pos < 0) 88775562573SAdrian Hunter return false; 88875562573SAdrian Hunter 88975562573SAdrian Hunter list_for_each_entry(pos, &evlist->entries, node) { 89075562573SAdrian Hunter if (pos->id_pos != evlist->id_pos || 89175562573SAdrian Hunter pos->is_pos != evlist->is_pos) 892c2a70653SArnaldo Carvalho de Melo return false; 89374429964SFrederic Weisbecker } 89474429964SFrederic Weisbecker 895c2a70653SArnaldo Carvalho de Melo return true; 896c2a70653SArnaldo Carvalho de Melo } 897c2a70653SArnaldo Carvalho de Melo 89875562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) 899c2a70653SArnaldo Carvalho de Melo { 90075562573SAdrian Hunter struct perf_evsel *evsel; 90175562573SAdrian Hunter 90275562573SAdrian Hunter if (evlist->combined_sample_type) 90375562573SAdrian Hunter return evlist->combined_sample_type; 90475562573SAdrian Hunter 90575562573SAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) 90675562573SAdrian Hunter evlist->combined_sample_type |= evsel->attr.sample_type; 90775562573SAdrian Hunter 90875562573SAdrian Hunter return evlist->combined_sample_type; 90975562573SAdrian Hunter } 91075562573SAdrian Hunter 91175562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) 91275562573SAdrian Hunter { 91375562573SAdrian Hunter evlist->combined_sample_type = 0; 91475562573SAdrian Hunter return __perf_evlist__combined_sample_type(evlist); 915c2a70653SArnaldo Carvalho de Melo } 916c2a70653SArnaldo Carvalho de Melo 9179ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist) 9189ede473cSJiri Olsa { 9199ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 9209ede473cSJiri Olsa u64 read_format = first->attr.read_format; 9219ede473cSJiri Olsa u64 sample_type = first->attr.sample_type; 9229ede473cSJiri Olsa 9239ede473cSJiri Olsa list_for_each_entry_continue(pos, &evlist->entries, node) { 9249ede473cSJiri Olsa if (read_format != pos->attr.read_format) 9259ede473cSJiri Olsa return false; 9269ede473cSJiri Olsa } 9279ede473cSJiri Olsa 9289ede473cSJiri Olsa /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */ 9299ede473cSJiri Olsa if ((sample_type & PERF_SAMPLE_READ) && 9309ede473cSJiri Olsa !(read_format & PERF_FORMAT_ID)) { 9319ede473cSJiri Olsa return false; 9329ede473cSJiri Olsa } 9339ede473cSJiri Olsa 9349ede473cSJiri Olsa return true; 9359ede473cSJiri Olsa } 9369ede473cSJiri Olsa 9379ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist) 9389ede473cSJiri Olsa { 9399ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist); 9409ede473cSJiri Olsa return first->attr.read_format; 9419ede473cSJiri Olsa } 9429ede473cSJiri Olsa 9430c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) 94481e36bffSArnaldo Carvalho de Melo { 9450c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 94681e36bffSArnaldo Carvalho de Melo struct perf_sample *data; 94781e36bffSArnaldo Carvalho de Melo u64 sample_type; 94881e36bffSArnaldo Carvalho de Melo u16 size = 0; 94981e36bffSArnaldo Carvalho de Melo 95081e36bffSArnaldo Carvalho de Melo if (!first->attr.sample_id_all) 95181e36bffSArnaldo Carvalho de Melo goto out; 95281e36bffSArnaldo Carvalho de Melo 95381e36bffSArnaldo Carvalho de Melo sample_type = first->attr.sample_type; 95481e36bffSArnaldo Carvalho de Melo 95581e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TID) 95681e36bffSArnaldo Carvalho de Melo size += sizeof(data->tid) * 2; 95781e36bffSArnaldo Carvalho de Melo 95881e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TIME) 95981e36bffSArnaldo Carvalho de Melo size += sizeof(data->time); 96081e36bffSArnaldo Carvalho de Melo 96181e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_ID) 96281e36bffSArnaldo Carvalho de Melo size += sizeof(data->id); 96381e36bffSArnaldo Carvalho de Melo 96481e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_STREAM_ID) 96581e36bffSArnaldo Carvalho de Melo size += sizeof(data->stream_id); 96681e36bffSArnaldo Carvalho de Melo 96781e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_CPU) 96881e36bffSArnaldo Carvalho de Melo size += sizeof(data->cpu) * 2; 96975562573SAdrian Hunter 97075562573SAdrian Hunter if (sample_type & PERF_SAMPLE_IDENTIFIER) 97175562573SAdrian Hunter size += sizeof(data->id); 97281e36bffSArnaldo Carvalho de Melo out: 97381e36bffSArnaldo Carvalho de Melo return size; 97481e36bffSArnaldo Carvalho de Melo } 97581e36bffSArnaldo Carvalho de Melo 9760c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) 977c2a70653SArnaldo Carvalho de Melo { 9780c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 979c2a70653SArnaldo Carvalho de Melo 980c2a70653SArnaldo Carvalho de Melo list_for_each_entry_continue(pos, &evlist->entries, node) { 981c2a70653SArnaldo Carvalho de Melo if (first->attr.sample_id_all != pos->attr.sample_id_all) 982c2a70653SArnaldo Carvalho de Melo return false; 983c2a70653SArnaldo Carvalho de Melo } 984c2a70653SArnaldo Carvalho de Melo 985c2a70653SArnaldo Carvalho de Melo return true; 98674429964SFrederic Weisbecker } 98774429964SFrederic Weisbecker 9880c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist) 98974429964SFrederic Weisbecker { 9900c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 991c2a70653SArnaldo Carvalho de Melo return first->attr.sample_id_all; 99274429964SFrederic Weisbecker } 99381cce8deSArnaldo Carvalho de Melo 99481cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist, 99581cce8deSArnaldo Carvalho de Melo struct perf_evsel *evsel) 99681cce8deSArnaldo Carvalho de Melo { 99781cce8deSArnaldo Carvalho de Melo evlist->selected = evsel; 99881cce8deSArnaldo Carvalho de Melo } 999727ab04eSArnaldo Carvalho de Melo 1000a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist) 1001a74b4b66SNamhyung Kim { 1002a74b4b66SNamhyung Kim struct perf_evsel *evsel; 1003a74b4b66SNamhyung Kim int ncpus = cpu_map__nr(evlist->cpus); 1004a74b4b66SNamhyung Kim int nthreads = thread_map__nr(evlist->threads); 1005a74b4b66SNamhyung Kim 1006a74b4b66SNamhyung Kim list_for_each_entry_reverse(evsel, &evlist->entries, node) 1007a74b4b66SNamhyung Kim perf_evsel__close(evsel, ncpus, nthreads); 1008a74b4b66SNamhyung Kim } 1009a74b4b66SNamhyung Kim 10106a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist) 1011727ab04eSArnaldo Carvalho de Melo { 10126a4bb04cSJiri Olsa struct perf_evsel *evsel; 1013a74b4b66SNamhyung Kim int err; 1014727ab04eSArnaldo Carvalho de Melo 1015733cd2feSAdrian Hunter perf_evlist__update_id_pos(evlist); 1016733cd2feSAdrian Hunter 1017727ab04eSArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 10186a4bb04cSJiri Olsa err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1019727ab04eSArnaldo Carvalho de Melo if (err < 0) 1020727ab04eSArnaldo Carvalho de Melo goto out_err; 1021727ab04eSArnaldo Carvalho de Melo } 1022727ab04eSArnaldo Carvalho de Melo 1023727ab04eSArnaldo Carvalho de Melo return 0; 1024727ab04eSArnaldo Carvalho de Melo out_err: 1025a74b4b66SNamhyung Kim perf_evlist__close(evlist); 102641c21a68SNamhyung Kim errno = -err; 1027727ab04eSArnaldo Carvalho de Melo return err; 1028727ab04eSArnaldo Carvalho de Melo } 102935b9d88eSArnaldo Carvalho de Melo 1030602ad878SArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, 103155e162eaSNamhyung Kim const char *argv[], bool pipe_output, 103255e162eaSNamhyung Kim bool want_signal) 103335b9d88eSArnaldo Carvalho de Melo { 103435b9d88eSArnaldo Carvalho de Melo int child_ready_pipe[2], go_pipe[2]; 103535b9d88eSArnaldo Carvalho de Melo char bf; 103635b9d88eSArnaldo Carvalho de Melo 103735b9d88eSArnaldo Carvalho de Melo if (pipe(child_ready_pipe) < 0) { 103835b9d88eSArnaldo Carvalho de Melo perror("failed to create 'ready' pipe"); 103935b9d88eSArnaldo Carvalho de Melo return -1; 104035b9d88eSArnaldo Carvalho de Melo } 104135b9d88eSArnaldo Carvalho de Melo 104235b9d88eSArnaldo Carvalho de Melo if (pipe(go_pipe) < 0) { 104335b9d88eSArnaldo Carvalho de Melo perror("failed to create 'go' pipe"); 104435b9d88eSArnaldo Carvalho de Melo goto out_close_ready_pipe; 104535b9d88eSArnaldo Carvalho de Melo } 104635b9d88eSArnaldo Carvalho de Melo 104735b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = fork(); 104835b9d88eSArnaldo Carvalho de Melo if (evlist->workload.pid < 0) { 104935b9d88eSArnaldo Carvalho de Melo perror("failed to fork"); 105035b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 105135b9d88eSArnaldo Carvalho de Melo } 105235b9d88eSArnaldo Carvalho de Melo 105335b9d88eSArnaldo Carvalho de Melo if (!evlist->workload.pid) { 1054119fa3c9SNamhyung Kim if (pipe_output) 105535b9d88eSArnaldo Carvalho de Melo dup2(2, 1); 105635b9d88eSArnaldo Carvalho de Melo 10570817df08SDavid Ahern signal(SIGTERM, SIG_DFL); 10580817df08SDavid Ahern 105935b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 106035b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 106135b9d88eSArnaldo Carvalho de Melo fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 106235b9d88eSArnaldo Carvalho de Melo 106335b9d88eSArnaldo Carvalho de Melo /* 106435b9d88eSArnaldo Carvalho de Melo * Tell the parent we're ready to go 106535b9d88eSArnaldo Carvalho de Melo */ 106635b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 106735b9d88eSArnaldo Carvalho de Melo 106835b9d88eSArnaldo Carvalho de Melo /* 106935b9d88eSArnaldo Carvalho de Melo * Wait until the parent tells us to go. 107035b9d88eSArnaldo Carvalho de Melo */ 107135b9d88eSArnaldo Carvalho de Melo if (read(go_pipe[0], &bf, 1) == -1) 107235b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 107335b9d88eSArnaldo Carvalho de Melo 107435b9d88eSArnaldo Carvalho de Melo execvp(argv[0], (char **)argv); 107535b9d88eSArnaldo Carvalho de Melo 1076f33cbe72SArnaldo Carvalho de Melo if (want_signal) { 1077f33cbe72SArnaldo Carvalho de Melo union sigval val; 1078f33cbe72SArnaldo Carvalho de Melo 1079f33cbe72SArnaldo Carvalho de Melo val.sival_int = errno; 1080f33cbe72SArnaldo Carvalho de Melo if (sigqueue(getppid(), SIGUSR1, val)) 108135b9d88eSArnaldo Carvalho de Melo perror(argv[0]); 1082f33cbe72SArnaldo Carvalho de Melo } else 1083f33cbe72SArnaldo Carvalho de Melo perror(argv[0]); 108435b9d88eSArnaldo Carvalho de Melo exit(-1); 108535b9d88eSArnaldo Carvalho de Melo } 108635b9d88eSArnaldo Carvalho de Melo 1087602ad878SArnaldo Carvalho de Melo if (target__none(target)) 108835b9d88eSArnaldo Carvalho de Melo evlist->threads->map[0] = evlist->workload.pid; 108935b9d88eSArnaldo Carvalho de Melo 109035b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 109135b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 109235b9d88eSArnaldo Carvalho de Melo /* 109335b9d88eSArnaldo Carvalho de Melo * wait for child to settle 109435b9d88eSArnaldo Carvalho de Melo */ 109535b9d88eSArnaldo Carvalho de Melo if (read(child_ready_pipe[0], &bf, 1) == -1) { 109635b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 109735b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 109835b9d88eSArnaldo Carvalho de Melo } 109935b9d88eSArnaldo Carvalho de Melo 1100bcf3145fSNamhyung Kim fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC); 110135b9d88eSArnaldo Carvalho de Melo evlist->workload.cork_fd = go_pipe[1]; 110235b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 110335b9d88eSArnaldo Carvalho de Melo return 0; 110435b9d88eSArnaldo Carvalho de Melo 110535b9d88eSArnaldo Carvalho de Melo out_close_pipes: 110635b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 110735b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 110835b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe: 110935b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 111035b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 111135b9d88eSArnaldo Carvalho de Melo return -1; 111235b9d88eSArnaldo Carvalho de Melo } 111335b9d88eSArnaldo Carvalho de Melo 111435b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist) 111535b9d88eSArnaldo Carvalho de Melo { 111635b9d88eSArnaldo Carvalho de Melo if (evlist->workload.cork_fd > 0) { 1117b3824404SDavid Ahern char bf = 0; 1118bcf3145fSNamhyung Kim int ret; 111935b9d88eSArnaldo Carvalho de Melo /* 112035b9d88eSArnaldo Carvalho de Melo * Remove the cork, let it rip! 112135b9d88eSArnaldo Carvalho de Melo */ 1122bcf3145fSNamhyung Kim ret = write(evlist->workload.cork_fd, &bf, 1); 1123bcf3145fSNamhyung Kim if (ret < 0) 1124bcf3145fSNamhyung Kim perror("enable to write to pipe"); 1125bcf3145fSNamhyung Kim 1126bcf3145fSNamhyung Kim close(evlist->workload.cork_fd); 1127bcf3145fSNamhyung Kim return ret; 112835b9d88eSArnaldo Carvalho de Melo } 112935b9d88eSArnaldo Carvalho de Melo 113035b9d88eSArnaldo Carvalho de Melo return 0; 113135b9d88eSArnaldo Carvalho de Melo } 1132cb0b29e0SArnaldo Carvalho de Melo 1133a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 11340807d2d8SArnaldo Carvalho de Melo struct perf_sample *sample) 1135cb0b29e0SArnaldo Carvalho de Melo { 113675562573SAdrian Hunter struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); 113775562573SAdrian Hunter 113875562573SAdrian Hunter if (!evsel) 113975562573SAdrian Hunter return -EFAULT; 11400807d2d8SArnaldo Carvalho de Melo return perf_evsel__parse_sample(evsel, event, sample); 1141cb0b29e0SArnaldo Carvalho de Melo } 114278f067b3SArnaldo Carvalho de Melo 114378f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) 114478f067b3SArnaldo Carvalho de Melo { 114578f067b3SArnaldo Carvalho de Melo struct perf_evsel *evsel; 114678f067b3SArnaldo Carvalho de Melo size_t printed = 0; 114778f067b3SArnaldo Carvalho de Melo 114878f067b3SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 114978f067b3SArnaldo Carvalho de Melo printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 115078f067b3SArnaldo Carvalho de Melo perf_evsel__name(evsel)); 115178f067b3SArnaldo Carvalho de Melo } 115278f067b3SArnaldo Carvalho de Melo 1153b2222139SDavidlohr Bueso return printed + fprintf(fp, "\n"); 115478f067b3SArnaldo Carvalho de Melo } 11556ef068cbSArnaldo Carvalho de Melo 11566ef068cbSArnaldo Carvalho de Melo int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, 11576ef068cbSArnaldo Carvalho de Melo int err, char *buf, size_t size) 11586ef068cbSArnaldo Carvalho de Melo { 11596ef068cbSArnaldo Carvalho de Melo char sbuf[128]; 11606ef068cbSArnaldo Carvalho de Melo 11616ef068cbSArnaldo Carvalho de Melo switch (err) { 11626ef068cbSArnaldo Carvalho de Melo case ENOENT: 11636ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", 11646ef068cbSArnaldo Carvalho de Melo "Error:\tUnable to find debugfs\n" 11656ef068cbSArnaldo Carvalho de Melo "Hint:\tWas your kernel was compiled with debugfs support?\n" 11666ef068cbSArnaldo Carvalho de Melo "Hint:\tIs the debugfs filesystem mounted?\n" 11676ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); 11686ef068cbSArnaldo Carvalho de Melo break; 11696ef068cbSArnaldo Carvalho de Melo case EACCES: 11706ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, 11716ef068cbSArnaldo Carvalho de Melo "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" 11726ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", 11736ef068cbSArnaldo Carvalho de Melo debugfs_mountpoint, debugfs_mountpoint); 11746ef068cbSArnaldo Carvalho de Melo break; 11756ef068cbSArnaldo Carvalho de Melo default: 11766ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf))); 11776ef068cbSArnaldo Carvalho de Melo break; 11786ef068cbSArnaldo Carvalho de Melo } 11796ef068cbSArnaldo Carvalho de Melo 11806ef068cbSArnaldo Carvalho de Melo return 0; 11816ef068cbSArnaldo Carvalho de Melo } 1182a8f23d8fSArnaldo Carvalho de Melo 1183a8f23d8fSArnaldo Carvalho de Melo int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, 1184a8f23d8fSArnaldo Carvalho de Melo int err, char *buf, size_t size) 1185a8f23d8fSArnaldo Carvalho de Melo { 1186a8f23d8fSArnaldo Carvalho de Melo int printed, value; 1187a8f23d8fSArnaldo Carvalho de Melo char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1188a8f23d8fSArnaldo Carvalho de Melo 1189a8f23d8fSArnaldo Carvalho de Melo switch (err) { 1190a8f23d8fSArnaldo Carvalho de Melo case EACCES: 1191a8f23d8fSArnaldo Carvalho de Melo case EPERM: 1192a8f23d8fSArnaldo Carvalho de Melo printed = scnprintf(buf, size, 1193a8f23d8fSArnaldo Carvalho de Melo "Error:\t%s.\n" 1194a8f23d8fSArnaldo Carvalho de Melo "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1195a8f23d8fSArnaldo Carvalho de Melo 11961a47245dSAdrian Hunter value = perf_event_paranoid(); 1197a8f23d8fSArnaldo Carvalho de Melo 1198a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1199a8f23d8fSArnaldo Carvalho de Melo 1200a8f23d8fSArnaldo Carvalho de Melo if (value >= 2) { 1201a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1202a8f23d8fSArnaldo Carvalho de Melo "For your workloads it needs to be <= 1\nHint:\t"); 1203a8f23d8fSArnaldo Carvalho de Melo } 1204a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1205a8f23d8fSArnaldo Carvalho de Melo "For system wide tracing it needs to be set to -1"); 1206a8f23d8fSArnaldo Carvalho de Melo 1207a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1208a8f23d8fSArnaldo Carvalho de Melo ".\nHint:\tThe current value is %d.", value); 1209a8f23d8fSArnaldo Carvalho de Melo break; 1210a8f23d8fSArnaldo Carvalho de Melo default: 1211a8f23d8fSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", emsg); 1212a8f23d8fSArnaldo Carvalho de Melo break; 1213a8f23d8fSArnaldo Carvalho de Melo } 1214a8f23d8fSArnaldo Carvalho de Melo 1215a8f23d8fSArnaldo Carvalho de Melo return 0; 1216a8f23d8fSArnaldo Carvalho de Melo } 1217a025e4f0SAdrian Hunter 1218a025e4f0SAdrian Hunter void perf_evlist__to_front(struct perf_evlist *evlist, 1219a025e4f0SAdrian Hunter struct perf_evsel *move_evsel) 1220a025e4f0SAdrian Hunter { 1221a025e4f0SAdrian Hunter struct perf_evsel *evsel, *n; 1222a025e4f0SAdrian Hunter LIST_HEAD(move); 1223a025e4f0SAdrian Hunter 1224a025e4f0SAdrian Hunter if (move_evsel == perf_evlist__first(evlist)) 1225a025e4f0SAdrian Hunter return; 1226a025e4f0SAdrian Hunter 1227a025e4f0SAdrian Hunter list_for_each_entry_safe(evsel, n, &evlist->entries, node) { 1228a025e4f0SAdrian Hunter if (evsel->leader == move_evsel->leader) 1229a025e4f0SAdrian Hunter list_move_tail(&evsel->node, &move); 1230a025e4f0SAdrian Hunter } 1231a025e4f0SAdrian Hunter 1232a025e4f0SAdrian Hunter list_splice(&move, &evlist->entries); 1233a025e4f0SAdrian Hunter } 1234