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" 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 { 104ef1d1af2SArnaldo Carvalho de Melo free(evlist->mmap); 105ef1d1af2SArnaldo Carvalho de Melo free(evlist->pollfd); 106ef1d1af2SArnaldo Carvalho de Melo evlist->mmap = NULL; 107ef1d1af2SArnaldo Carvalho de Melo evlist->pollfd = NULL; 108ef1d1af2SArnaldo Carvalho de Melo } 109ef1d1af2SArnaldo Carvalho de Melo 110361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist) 111361c99a6SArnaldo Carvalho de Melo { 112361c99a6SArnaldo Carvalho de Melo perf_evlist__purge(evlist); 113ef1d1af2SArnaldo Carvalho de Melo perf_evlist__exit(evlist); 114361c99a6SArnaldo Carvalho de Melo free(evlist); 115361c99a6SArnaldo Carvalho de Melo } 116361c99a6SArnaldo Carvalho de Melo 117361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 118361c99a6SArnaldo Carvalho de Melo { 119361c99a6SArnaldo Carvalho de Melo list_add_tail(&entry->node, &evlist->entries); 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 1681aed2671SJoerg Roedel evsel = perf_evsel__new(&attr, 0); 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++) { 19350d08e47SArnaldo Carvalho de Melo evsel = perf_evsel__new(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 { 25239876e7dSArnaldo Carvalho de Melo struct perf_evsel *evsel; 25339876e7dSArnaldo Carvalho de Melo 25439876e7dSArnaldo Carvalho de Melo evsel = perf_evsel__newtp(sys, name, evlist->nr_entries); 25539876e7dSArnaldo Carvalho de Melo if (evsel == NULL) 25639876e7dSArnaldo Carvalho de Melo return -1; 25739876e7dSArnaldo Carvalho de Melo 25839876e7dSArnaldo Carvalho de Melo evsel->handler.func = handler; 25939876e7dSArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 26039876e7dSArnaldo Carvalho de Melo return 0; 26139876e7dSArnaldo Carvalho de Melo } 26239876e7dSArnaldo Carvalho de Melo 2634152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist) 2644152ab37SArnaldo Carvalho de Melo { 2654152ab37SArnaldo Carvalho de Melo int cpu, thread; 2664152ab37SArnaldo Carvalho de Melo struct perf_evsel *pos; 267b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 268b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 2694152ab37SArnaldo Carvalho de Melo 270b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 2714152ab37SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 272395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 2733fe4430dSJiri Olsa continue; 274b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 27555da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 27655da8005SNamhyung Kim PERF_EVENT_IOC_DISABLE, 0); 2774152ab37SArnaldo Carvalho de Melo } 2784152ab37SArnaldo Carvalho de Melo } 2794152ab37SArnaldo Carvalho de Melo } 2804152ab37SArnaldo Carvalho de Melo 281764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist) 282764e16a3SDavid Ahern { 283764e16a3SDavid Ahern int cpu, thread; 284764e16a3SDavid Ahern struct perf_evsel *pos; 285b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 286b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 287764e16a3SDavid Ahern 288b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 289764e16a3SDavid Ahern list_for_each_entry(pos, &evlist->entries, node) { 290395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 2913fe4430dSJiri Olsa continue; 292b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 29355da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 29455da8005SNamhyung Kim PERF_EVENT_IOC_ENABLE, 0); 295764e16a3SDavid Ahern } 296764e16a3SDavid Ahern } 297764e16a3SDavid Ahern } 298764e16a3SDavid Ahern 299395c3070SAdrian Hunter int perf_evlist__disable_event(struct perf_evlist *evlist, 300395c3070SAdrian Hunter struct perf_evsel *evsel) 301395c3070SAdrian Hunter { 302395c3070SAdrian Hunter int cpu, thread, err; 303395c3070SAdrian Hunter 304395c3070SAdrian Hunter if (!evsel->fd) 305395c3070SAdrian Hunter return 0; 306395c3070SAdrian Hunter 307395c3070SAdrian Hunter for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 308395c3070SAdrian Hunter for (thread = 0; thread < evlist->threads->nr; thread++) { 309395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 310395c3070SAdrian Hunter PERF_EVENT_IOC_DISABLE, 0); 311395c3070SAdrian Hunter if (err) 312395c3070SAdrian Hunter return err; 313395c3070SAdrian Hunter } 314395c3070SAdrian Hunter } 315395c3070SAdrian Hunter return 0; 316395c3070SAdrian Hunter } 317395c3070SAdrian Hunter 318395c3070SAdrian Hunter int perf_evlist__enable_event(struct perf_evlist *evlist, 319395c3070SAdrian Hunter struct perf_evsel *evsel) 320395c3070SAdrian Hunter { 321395c3070SAdrian Hunter int cpu, thread, err; 322395c3070SAdrian Hunter 323395c3070SAdrian Hunter if (!evsel->fd) 324395c3070SAdrian Hunter return -EINVAL; 325395c3070SAdrian Hunter 326395c3070SAdrian Hunter for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 327395c3070SAdrian Hunter for (thread = 0; thread < evlist->threads->nr; thread++) { 328395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 329395c3070SAdrian Hunter PERF_EVENT_IOC_ENABLE, 0); 330395c3070SAdrian Hunter if (err) 331395c3070SAdrian Hunter return err; 332395c3070SAdrian Hunter } 333395c3070SAdrian Hunter } 334395c3070SAdrian Hunter return 0; 335395c3070SAdrian Hunter } 336395c3070SAdrian Hunter 337806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 3385c581041SArnaldo Carvalho de Melo { 339b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 340b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 341b3a319d5SNamhyung Kim int nfds = nr_cpus * nr_threads * evlist->nr_entries; 3425c581041SArnaldo Carvalho de Melo evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 3435c581041SArnaldo Carvalho de Melo return evlist->pollfd != NULL ? 0 : -ENOMEM; 3445c581041SArnaldo Carvalho de Melo } 34570082dd9SArnaldo Carvalho de Melo 34670082dd9SArnaldo Carvalho de Melo void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 34770082dd9SArnaldo Carvalho de Melo { 34870082dd9SArnaldo Carvalho de Melo fcntl(fd, F_SETFL, O_NONBLOCK); 34970082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].fd = fd; 35070082dd9SArnaldo Carvalho de Melo evlist->pollfd[evlist->nr_fds].events = POLLIN; 35170082dd9SArnaldo Carvalho de Melo evlist->nr_fds++; 35270082dd9SArnaldo Carvalho de Melo } 35370db7533SArnaldo Carvalho de Melo 354a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist, 355a91e5431SArnaldo Carvalho de Melo struct perf_evsel *evsel, 3563d3b5e95SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 3573d3b5e95SArnaldo Carvalho de Melo { 3583d3b5e95SArnaldo Carvalho de Melo int hash; 3593d3b5e95SArnaldo Carvalho de Melo struct perf_sample_id *sid = SID(evsel, cpu, thread); 3603d3b5e95SArnaldo Carvalho de Melo 3613d3b5e95SArnaldo Carvalho de Melo sid->id = id; 3623d3b5e95SArnaldo Carvalho de Melo sid->evsel = evsel; 3633d3b5e95SArnaldo Carvalho de Melo hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); 3643d3b5e95SArnaldo Carvalho de Melo hlist_add_head(&sid->node, &evlist->heads[hash]); 3653d3b5e95SArnaldo Carvalho de Melo } 3663d3b5e95SArnaldo Carvalho de Melo 367a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 368a91e5431SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 369a91e5431SArnaldo Carvalho de Melo { 370a91e5431SArnaldo Carvalho de Melo perf_evlist__id_hash(evlist, evsel, cpu, thread, id); 371a91e5431SArnaldo Carvalho de Melo evsel->id[evsel->ids++] = id; 372a91e5431SArnaldo Carvalho de Melo } 373a91e5431SArnaldo Carvalho de Melo 374a91e5431SArnaldo Carvalho de Melo static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 3753d3b5e95SArnaldo Carvalho de Melo struct perf_evsel *evsel, 376f8a95309SArnaldo Carvalho de Melo int cpu, int thread, int fd) 377f8a95309SArnaldo Carvalho de Melo { 378f8a95309SArnaldo Carvalho de Melo u64 read_data[4] = { 0, }; 3793d3b5e95SArnaldo Carvalho de Melo int id_idx = 1; /* The first entry is the counter value */ 380e2b5abe0SJiri Olsa u64 id; 381e2b5abe0SJiri Olsa int ret; 382e2b5abe0SJiri Olsa 383e2b5abe0SJiri Olsa ret = ioctl(fd, PERF_EVENT_IOC_ID, &id); 384e2b5abe0SJiri Olsa if (!ret) 385e2b5abe0SJiri Olsa goto add; 386e2b5abe0SJiri Olsa 387e2b5abe0SJiri Olsa if (errno != ENOTTY) 388e2b5abe0SJiri Olsa return -1; 389e2b5abe0SJiri Olsa 390e2b5abe0SJiri Olsa /* Legacy way to get event id.. All hail to old kernels! */ 391f8a95309SArnaldo Carvalho de Melo 392c4861afeSJiri Olsa /* 393c4861afeSJiri Olsa * This way does not work with group format read, so bail 394c4861afeSJiri Olsa * out in that case. 395c4861afeSJiri Olsa */ 396c4861afeSJiri Olsa if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP) 397c4861afeSJiri Olsa return -1; 398c4861afeSJiri Olsa 399f8a95309SArnaldo Carvalho de Melo if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 400f8a95309SArnaldo Carvalho de Melo read(fd, &read_data, sizeof(read_data)) == -1) 401f8a95309SArnaldo Carvalho de Melo return -1; 402f8a95309SArnaldo Carvalho de Melo 403f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 404f8a95309SArnaldo Carvalho de Melo ++id_idx; 405f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 406f8a95309SArnaldo Carvalho de Melo ++id_idx; 407f8a95309SArnaldo Carvalho de Melo 408e2b5abe0SJiri Olsa id = read_data[id_idx]; 409e2b5abe0SJiri Olsa 410e2b5abe0SJiri Olsa add: 411e2b5abe0SJiri Olsa perf_evlist__id_add(evlist, evsel, cpu, thread, id); 412f8a95309SArnaldo Carvalho de Melo return 0; 413f8a95309SArnaldo Carvalho de Melo } 414f8a95309SArnaldo Carvalho de Melo 415932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 41670db7533SArnaldo Carvalho de Melo { 41770db7533SArnaldo Carvalho de Melo struct hlist_head *head; 41870db7533SArnaldo Carvalho de Melo struct perf_sample_id *sid; 41970db7533SArnaldo Carvalho de Melo int hash; 42070db7533SArnaldo Carvalho de Melo 42170db7533SArnaldo Carvalho de Melo hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 42270db7533SArnaldo Carvalho de Melo head = &evlist->heads[hash]; 42370db7533SArnaldo Carvalho de Melo 424b67bfe0dSSasha Levin hlist_for_each_entry(sid, head, node) 42570db7533SArnaldo Carvalho de Melo if (sid->id == id) 426932a3594SJiri Olsa return sid; 427932a3594SJiri Olsa 428932a3594SJiri Olsa return NULL; 429932a3594SJiri Olsa } 430932a3594SJiri Olsa 431932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 432932a3594SJiri Olsa { 433932a3594SJiri Olsa struct perf_sample_id *sid; 434932a3594SJiri Olsa 435932a3594SJiri Olsa if (evlist->nr_entries == 1) 436932a3594SJiri Olsa return perf_evlist__first(evlist); 437932a3594SJiri Olsa 438932a3594SJiri Olsa sid = perf_evlist__id2sid(evlist, id); 439932a3594SJiri Olsa if (sid) 44070db7533SArnaldo Carvalho de Melo return sid->evsel; 44130e68bccSNamhyung Kim 44230e68bccSNamhyung Kim if (!perf_evlist__sample_id_all(evlist)) 4430c21f736SArnaldo Carvalho de Melo return perf_evlist__first(evlist); 44430e68bccSNamhyung Kim 44570db7533SArnaldo Carvalho de Melo return NULL; 44670db7533SArnaldo Carvalho de Melo } 44704391debSArnaldo Carvalho de Melo 44875562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist, 44975562573SAdrian Hunter union perf_event *event, u64 *id) 45075562573SAdrian Hunter { 45175562573SAdrian Hunter const u64 *array = event->sample.array; 45275562573SAdrian Hunter ssize_t n; 45375562573SAdrian Hunter 45475562573SAdrian Hunter n = (event->header.size - sizeof(event->header)) >> 3; 45575562573SAdrian Hunter 45675562573SAdrian Hunter if (event->header.type == PERF_RECORD_SAMPLE) { 45775562573SAdrian Hunter if (evlist->id_pos >= n) 45875562573SAdrian Hunter return -1; 45975562573SAdrian Hunter *id = array[evlist->id_pos]; 46075562573SAdrian Hunter } else { 46175562573SAdrian Hunter if (evlist->is_pos > n) 46275562573SAdrian Hunter return -1; 46375562573SAdrian Hunter n -= evlist->is_pos; 46475562573SAdrian Hunter *id = array[n]; 46575562573SAdrian Hunter } 46675562573SAdrian Hunter return 0; 46775562573SAdrian Hunter } 46875562573SAdrian Hunter 46975562573SAdrian Hunter static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 47075562573SAdrian Hunter union perf_event *event) 47175562573SAdrian Hunter { 47298be6966SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 47375562573SAdrian Hunter struct hlist_head *head; 47475562573SAdrian Hunter struct perf_sample_id *sid; 47575562573SAdrian Hunter int hash; 47675562573SAdrian Hunter u64 id; 47775562573SAdrian Hunter 47875562573SAdrian Hunter if (evlist->nr_entries == 1) 47998be6966SAdrian Hunter return first; 48098be6966SAdrian Hunter 48198be6966SAdrian Hunter if (!first->attr.sample_id_all && 48298be6966SAdrian Hunter event->header.type != PERF_RECORD_SAMPLE) 48398be6966SAdrian Hunter return first; 48475562573SAdrian Hunter 48575562573SAdrian Hunter if (perf_evlist__event2id(evlist, event, &id)) 48675562573SAdrian Hunter return NULL; 48775562573SAdrian Hunter 48875562573SAdrian Hunter /* Synthesized events have an id of zero */ 48975562573SAdrian Hunter if (!id) 49098be6966SAdrian Hunter return first; 49175562573SAdrian Hunter 49275562573SAdrian Hunter hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 49375562573SAdrian Hunter head = &evlist->heads[hash]; 49475562573SAdrian Hunter 49575562573SAdrian Hunter hlist_for_each_entry(sid, head, node) { 49675562573SAdrian Hunter if (sid->id == id) 49775562573SAdrian Hunter return sid->evsel; 49875562573SAdrian Hunter } 49975562573SAdrian Hunter return NULL; 50075562573SAdrian Hunter } 50175562573SAdrian Hunter 502aece948fSArnaldo Carvalho de Melo union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 50304391debSArnaldo Carvalho de Melo { 504aece948fSArnaldo Carvalho de Melo struct perf_mmap *md = &evlist->mmap[idx]; 50504391debSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 50604391debSArnaldo Carvalho de Melo unsigned int old = md->prev; 50704391debSArnaldo Carvalho de Melo unsigned char *data = md->base + page_size; 5088115d60cSArnaldo Carvalho de Melo union perf_event *event = NULL; 50904391debSArnaldo Carvalho de Melo 5107bb41152SArnaldo Carvalho de Melo if (evlist->overwrite) { 51104391debSArnaldo Carvalho de Melo /* 51204391debSArnaldo Carvalho de Melo * If we're further behind than half the buffer, there's a chance 51304391debSArnaldo Carvalho de Melo * the writer will bite our tail and mess up the samples under us. 51404391debSArnaldo Carvalho de Melo * 51504391debSArnaldo Carvalho de Melo * If we somehow ended up ahead of the head, we got messed up. 51604391debSArnaldo Carvalho de Melo * 51704391debSArnaldo Carvalho de Melo * In either case, truncate and restart at head. 51804391debSArnaldo Carvalho de Melo */ 5197bb41152SArnaldo Carvalho de Melo int diff = head - old; 52004391debSArnaldo Carvalho de Melo if (diff > md->mask / 2 || diff < 0) { 52104391debSArnaldo Carvalho de Melo fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 52204391debSArnaldo Carvalho de Melo 52304391debSArnaldo Carvalho de Melo /* 52404391debSArnaldo Carvalho de Melo * head points to a known good entry, start there. 52504391debSArnaldo Carvalho de Melo */ 52604391debSArnaldo Carvalho de Melo old = head; 52704391debSArnaldo Carvalho de Melo } 5287bb41152SArnaldo Carvalho de Melo } 52904391debSArnaldo Carvalho de Melo 53004391debSArnaldo Carvalho de Melo if (old != head) { 53104391debSArnaldo Carvalho de Melo size_t size; 53204391debSArnaldo Carvalho de Melo 5338115d60cSArnaldo Carvalho de Melo event = (union perf_event *)&data[old & md->mask]; 53404391debSArnaldo Carvalho de Melo size = event->header.size; 53504391debSArnaldo Carvalho de Melo 53604391debSArnaldo Carvalho de Melo /* 53704391debSArnaldo Carvalho de Melo * Event straddles the mmap boundary -- header should always 53804391debSArnaldo Carvalho de Melo * be inside due to u64 alignment of output. 53904391debSArnaldo Carvalho de Melo */ 54004391debSArnaldo Carvalho de Melo if ((old & md->mask) + size != ((old + size) & md->mask)) { 54104391debSArnaldo Carvalho de Melo unsigned int offset = old; 54204391debSArnaldo Carvalho de Melo unsigned int len = min(sizeof(*event), size), cpy; 543a65cb4b9SJiri Olsa void *dst = md->event_copy; 54404391debSArnaldo Carvalho de Melo 54504391debSArnaldo Carvalho de Melo do { 54604391debSArnaldo Carvalho de Melo cpy = min(md->mask + 1 - (offset & md->mask), len); 54704391debSArnaldo Carvalho de Melo memcpy(dst, &data[offset & md->mask], cpy); 54804391debSArnaldo Carvalho de Melo offset += cpy; 54904391debSArnaldo Carvalho de Melo dst += cpy; 55004391debSArnaldo Carvalho de Melo len -= cpy; 55104391debSArnaldo Carvalho de Melo } while (len); 55204391debSArnaldo Carvalho de Melo 553a65cb4b9SJiri Olsa event = (union perf_event *) md->event_copy; 55404391debSArnaldo Carvalho de Melo } 55504391debSArnaldo Carvalho de Melo 55604391debSArnaldo Carvalho de Melo old += size; 55704391debSArnaldo Carvalho de Melo } 55804391debSArnaldo Carvalho de Melo 55904391debSArnaldo Carvalho de Melo md->prev = old; 5607bb41152SArnaldo Carvalho de Melo 5617bb41152SArnaldo Carvalho de Melo if (!evlist->overwrite) 5627bb41152SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 5637bb41152SArnaldo Carvalho de Melo 56404391debSArnaldo Carvalho de Melo return event; 56504391debSArnaldo Carvalho de Melo } 566f8a95309SArnaldo Carvalho de Melo 56793edcbd9SAdrian Hunter static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 56893edcbd9SAdrian Hunter { 56993edcbd9SAdrian Hunter if (evlist->mmap[idx].base != NULL) { 57093edcbd9SAdrian Hunter munmap(evlist->mmap[idx].base, evlist->mmap_len); 57193edcbd9SAdrian Hunter evlist->mmap[idx].base = NULL; 57293edcbd9SAdrian Hunter } 57393edcbd9SAdrian Hunter } 57493edcbd9SAdrian Hunter 5757e2ed097SArnaldo Carvalho de Melo void perf_evlist__munmap(struct perf_evlist *evlist) 576f8a95309SArnaldo Carvalho de Melo { 577aece948fSArnaldo Carvalho de Melo int i; 578f8a95309SArnaldo Carvalho de Melo 57993edcbd9SAdrian Hunter for (i = 0; i < evlist->nr_mmaps; i++) 58093edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, i); 581aece948fSArnaldo Carvalho de Melo 582aece948fSArnaldo Carvalho de Melo free(evlist->mmap); 583aece948fSArnaldo Carvalho de Melo evlist->mmap = NULL; 584f8a95309SArnaldo Carvalho de Melo } 585f8a95309SArnaldo Carvalho de Melo 586806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 587f8a95309SArnaldo Carvalho de Melo { 588a14bb7a6SArnaldo Carvalho de Melo evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 589ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(evlist->cpus)) 590b3a319d5SNamhyung Kim evlist->nr_mmaps = thread_map__nr(evlist->threads); 591aece948fSArnaldo Carvalho de Melo evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 592f8a95309SArnaldo Carvalho de Melo return evlist->mmap != NULL ? 0 : -ENOMEM; 593f8a95309SArnaldo Carvalho de Melo } 594f8a95309SArnaldo Carvalho de Melo 595bccdaba0SArnaldo Carvalho de Melo static int __perf_evlist__mmap(struct perf_evlist *evlist, 596aece948fSArnaldo Carvalho de Melo int idx, int prot, int mask, int fd) 597f8a95309SArnaldo Carvalho de Melo { 598aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].prev = 0; 599aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].mask = mask; 600aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 601f8a95309SArnaldo Carvalho de Melo MAP_SHARED, fd, 0); 602301b195dSNelson Elhage if (evlist->mmap[idx].base == MAP_FAILED) { 603301b195dSNelson Elhage evlist->mmap[idx].base = NULL; 604f8a95309SArnaldo Carvalho de Melo return -1; 605301b195dSNelson Elhage } 606f8a95309SArnaldo Carvalho de Melo 607f8a95309SArnaldo Carvalho de Melo perf_evlist__add_pollfd(evlist, fd); 608f8a95309SArnaldo Carvalho de Melo return 0; 609f8a95309SArnaldo Carvalho de Melo } 610f8a95309SArnaldo Carvalho de Melo 61104e21314SAdrian Hunter static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 61204e21314SAdrian Hunter int prot, int mask, int cpu, int thread, 61304e21314SAdrian Hunter int *output) 614aece948fSArnaldo Carvalho de Melo { 615aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 61604e21314SAdrian Hunter 61704e21314SAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) { 61804e21314SAdrian Hunter int fd = FD(evsel, cpu, thread); 61904e21314SAdrian Hunter 62004e21314SAdrian Hunter if (*output == -1) { 62104e21314SAdrian Hunter *output = fd; 62204e21314SAdrian Hunter if (__perf_evlist__mmap(evlist, idx, prot, mask, 62304e21314SAdrian Hunter *output) < 0) 62404e21314SAdrian Hunter return -1; 62504e21314SAdrian Hunter } else { 62604e21314SAdrian Hunter if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 62704e21314SAdrian Hunter return -1; 62804e21314SAdrian Hunter } 62904e21314SAdrian Hunter 63004e21314SAdrian Hunter if ((evsel->attr.read_format & PERF_FORMAT_ID) && 63104e21314SAdrian Hunter perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 63204e21314SAdrian Hunter return -1; 63304e21314SAdrian Hunter } 63404e21314SAdrian Hunter 63504e21314SAdrian Hunter return 0; 63604e21314SAdrian Hunter } 63704e21314SAdrian Hunter 63804e21314SAdrian Hunter static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, 63904e21314SAdrian Hunter int mask) 64004e21314SAdrian Hunter { 641aece948fSArnaldo Carvalho de Melo int cpu, thread; 642b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 643b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 644aece948fSArnaldo Carvalho de Melo 645e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per cpu\n"); 646b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 647aece948fSArnaldo Carvalho de Melo int output = -1; 648aece948fSArnaldo Carvalho de Melo 649b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 65004e21314SAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask, 65104e21314SAdrian Hunter cpu, thread, &output)) 652aece948fSArnaldo Carvalho de Melo goto out_unmap; 653aece948fSArnaldo Carvalho de Melo } 654aece948fSArnaldo Carvalho de Melo } 655aece948fSArnaldo Carvalho de Melo 656aece948fSArnaldo Carvalho de Melo return 0; 657aece948fSArnaldo Carvalho de Melo 658aece948fSArnaldo Carvalho de Melo out_unmap: 65993edcbd9SAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) 66093edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, cpu); 661aece948fSArnaldo Carvalho de Melo return -1; 662aece948fSArnaldo Carvalho de Melo } 663aece948fSArnaldo Carvalho de Melo 66404e21314SAdrian Hunter static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, 66504e21314SAdrian Hunter int mask) 666aece948fSArnaldo Carvalho de Melo { 667aece948fSArnaldo Carvalho de Melo int thread; 668b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 669aece948fSArnaldo Carvalho de Melo 670e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per thread\n"); 671b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 672aece948fSArnaldo Carvalho de Melo int output = -1; 673aece948fSArnaldo Carvalho de Melo 67404e21314SAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0, 67504e21314SAdrian Hunter thread, &output)) 676aece948fSArnaldo Carvalho de Melo goto out_unmap; 677aece948fSArnaldo Carvalho de Melo } 678aece948fSArnaldo Carvalho de Melo 679aece948fSArnaldo Carvalho de Melo return 0; 680aece948fSArnaldo Carvalho de Melo 681aece948fSArnaldo Carvalho de Melo out_unmap: 68293edcbd9SAdrian Hunter for (thread = 0; thread < nr_threads; thread++) 68393edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, thread); 684aece948fSArnaldo Carvalho de Melo return -1; 685aece948fSArnaldo Carvalho de Melo } 686aece948fSArnaldo Carvalho de Melo 687994a1f78SJiri Olsa static size_t perf_evlist__mmap_size(unsigned long pages) 688994a1f78SJiri Olsa { 689994a1f78SJiri Olsa /* 512 kiB: default amount of unprivileged mlocked memory */ 690994a1f78SJiri Olsa if (pages == UINT_MAX) 691994a1f78SJiri Olsa pages = (512 * 1024) / page_size; 692994a1f78SJiri Olsa else if (!is_power_of_2(pages)) 693994a1f78SJiri Olsa return 0; 694994a1f78SJiri Olsa 695994a1f78SJiri Olsa return (pages + 1) * page_size; 696994a1f78SJiri Olsa } 697994a1f78SJiri Olsa 698994a1f78SJiri Olsa int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, 699994a1f78SJiri Olsa int unset __maybe_unused) 700994a1f78SJiri Olsa { 7012fbe4abeSAdrian Hunter unsigned int *mmap_pages = opt->value; 7022fbe4abeSAdrian Hunter unsigned long pages, val; 703994a1f78SJiri Olsa size_t size; 70427050f53SJiri Olsa static struct parse_tag tags[] = { 70527050f53SJiri Olsa { .tag = 'B', .mult = 1 }, 70627050f53SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 70727050f53SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 70827050f53SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 70927050f53SJiri Olsa { .tag = 0 }, 71027050f53SJiri Olsa }; 711994a1f78SJiri Olsa 71227050f53SJiri Olsa val = parse_tag_value(str, tags); 7132fbe4abeSAdrian Hunter if (val != (unsigned long) -1) { 71427050f53SJiri Olsa /* we got file size value */ 71527050f53SJiri Olsa pages = PERF_ALIGN(val, page_size) / page_size; 7162fbe4abeSAdrian Hunter if (pages < (1UL << 31) && !is_power_of_2(pages)) { 71727050f53SJiri Olsa pages = next_pow2(pages); 7182fbe4abeSAdrian Hunter pr_info("rounding mmap pages size to %lu (%lu pages)\n", 71927050f53SJiri Olsa pages * page_size, pages); 72027050f53SJiri Olsa } 72127050f53SJiri Olsa } else { 72227050f53SJiri Olsa /* we got pages count value */ 72327050f53SJiri Olsa char *eptr; 724994a1f78SJiri Olsa pages = strtoul(str, &eptr, 10); 725994a1f78SJiri Olsa if (*eptr != '\0') { 726994a1f78SJiri Olsa pr_err("failed to parse --mmap_pages/-m value\n"); 727994a1f78SJiri Olsa return -1; 728994a1f78SJiri Olsa } 72927050f53SJiri Olsa } 730994a1f78SJiri Olsa 7312fbe4abeSAdrian Hunter if (pages > UINT_MAX || pages > SIZE_MAX / page_size) { 7322fbe4abeSAdrian Hunter pr_err("--mmap_pages/-m value too big\n"); 7332fbe4abeSAdrian Hunter return -1; 7342fbe4abeSAdrian Hunter } 7352fbe4abeSAdrian Hunter 736994a1f78SJiri Olsa size = perf_evlist__mmap_size(pages); 737994a1f78SJiri Olsa if (!size) { 738994a1f78SJiri Olsa pr_err("--mmap_pages/-m value must be a power of two."); 739994a1f78SJiri Olsa return -1; 740994a1f78SJiri Olsa } 741994a1f78SJiri Olsa 742994a1f78SJiri Olsa *mmap_pages = pages; 743994a1f78SJiri Olsa return 0; 744994a1f78SJiri Olsa } 745994a1f78SJiri Olsa 746c83fa7f2SAdrian Hunter /** 747c83fa7f2SAdrian Hunter * perf_evlist__mmap - Create mmaps to receive events. 748c83fa7f2SAdrian Hunter * @evlist: list of events 749c83fa7f2SAdrian Hunter * @pages: map length in pages 750c83fa7f2SAdrian Hunter * @overwrite: overwrite older events? 751f8a95309SArnaldo Carvalho de Melo * 752c83fa7f2SAdrian Hunter * If @overwrite is %false the user needs to signal event consumption using 753c83fa7f2SAdrian Hunter * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this 754c83fa7f2SAdrian Hunter * automatically. 755f8a95309SArnaldo Carvalho de Melo * 756c83fa7f2SAdrian Hunter * Return: %0 on success, negative error code otherwise. 757f8a95309SArnaldo Carvalho de Melo */ 75850a682ceSArnaldo Carvalho de Melo int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 75950a682ceSArnaldo Carvalho de Melo bool overwrite) 760f8a95309SArnaldo Carvalho de Melo { 761aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 7627e2ed097SArnaldo Carvalho de Melo const struct cpu_map *cpus = evlist->cpus; 7637e2ed097SArnaldo Carvalho de Melo const struct thread_map *threads = evlist->threads; 76450a682ceSArnaldo Carvalho de Melo int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 76550a682ceSArnaldo Carvalho de Melo 7667e2ed097SArnaldo Carvalho de Melo if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 767f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 768f8a95309SArnaldo Carvalho de Melo 7697e2ed097SArnaldo Carvalho de Melo if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 770f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 771f8a95309SArnaldo Carvalho de Melo 772f8a95309SArnaldo Carvalho de Melo evlist->overwrite = overwrite; 773994a1f78SJiri Olsa evlist->mmap_len = perf_evlist__mmap_size(pages); 7742af68ef5SAdrian Hunter pr_debug("mmap size %zuB\n", evlist->mmap_len); 775994a1f78SJiri Olsa mask = evlist->mmap_len - page_size - 1; 776f8a95309SArnaldo Carvalho de Melo 777f8a95309SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 778f8a95309SArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 779a91e5431SArnaldo Carvalho de Melo evsel->sample_id == NULL && 780a14bb7a6SArnaldo Carvalho de Melo perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 781f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 782f8a95309SArnaldo Carvalho de Melo } 783f8a95309SArnaldo Carvalho de Melo 784ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(cpus)) 785aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_thread(evlist, prot, mask); 786f8a95309SArnaldo Carvalho de Melo 787aece948fSArnaldo Carvalho de Melo return perf_evlist__mmap_per_cpu(evlist, prot, mask); 788f8a95309SArnaldo Carvalho de Melo } 7897e2ed097SArnaldo Carvalho de Melo 790b809ac10SNamhyung Kim int perf_evlist__create_maps(struct perf_evlist *evlist, 791b809ac10SNamhyung Kim struct perf_target *target) 7927e2ed097SArnaldo Carvalho de Melo { 793b809ac10SNamhyung Kim evlist->threads = thread_map__new_str(target->pid, target->tid, 794b809ac10SNamhyung Kim target->uid); 7957e2ed097SArnaldo Carvalho de Melo 7967e2ed097SArnaldo Carvalho de Melo if (evlist->threads == NULL) 7977e2ed097SArnaldo Carvalho de Melo return -1; 7987e2ed097SArnaldo Carvalho de Melo 799879d77d0SNamhyung Kim if (perf_target__has_task(target)) 800d67356e7SNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 801d1cb9fceSNamhyung Kim else if (!perf_target__has_cpu(target) && !target->uses_mmap) 802d1cb9fceSNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 803879d77d0SNamhyung Kim else 804879d77d0SNamhyung Kim evlist->cpus = cpu_map__new(target->cpu_list); 8057e2ed097SArnaldo Carvalho de Melo 8067e2ed097SArnaldo Carvalho de Melo if (evlist->cpus == NULL) 8077e2ed097SArnaldo Carvalho de Melo goto out_delete_threads; 8087e2ed097SArnaldo Carvalho de Melo 8097e2ed097SArnaldo Carvalho de Melo return 0; 8107e2ed097SArnaldo Carvalho de Melo 8117e2ed097SArnaldo Carvalho de Melo out_delete_threads: 8127e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 8137e2ed097SArnaldo Carvalho de Melo return -1; 8147e2ed097SArnaldo Carvalho de Melo } 8157e2ed097SArnaldo Carvalho de Melo 8167e2ed097SArnaldo Carvalho de Melo void perf_evlist__delete_maps(struct perf_evlist *evlist) 8177e2ed097SArnaldo Carvalho de Melo { 8187e2ed097SArnaldo Carvalho de Melo cpu_map__delete(evlist->cpus); 8197e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 8207e2ed097SArnaldo Carvalho de Melo evlist->cpus = NULL; 8217e2ed097SArnaldo Carvalho de Melo evlist->threads = NULL; 8227e2ed097SArnaldo Carvalho de Melo } 8230a102479SFrederic Weisbecker 8241491a632SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist) 8250a102479SFrederic Weisbecker { 8260a102479SFrederic Weisbecker struct perf_evsel *evsel; 827745cefc5SArnaldo Carvalho de Melo int err = 0; 828745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 829b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 8300a102479SFrederic Weisbecker 8310a102479SFrederic Weisbecker list_for_each_entry(evsel, &evlist->entries, node) { 832745cefc5SArnaldo Carvalho de Melo if (evsel->filter == NULL) 8330a102479SFrederic Weisbecker continue; 834745cefc5SArnaldo Carvalho de Melo 835745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 8360a102479SFrederic Weisbecker if (err) 837745cefc5SArnaldo Carvalho de Melo break; 8380a102479SFrederic Weisbecker } 8390a102479SFrederic Weisbecker 840745cefc5SArnaldo Carvalho de Melo return err; 841745cefc5SArnaldo Carvalho de Melo } 842745cefc5SArnaldo Carvalho de Melo 843745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) 844745cefc5SArnaldo Carvalho de Melo { 845745cefc5SArnaldo Carvalho de Melo struct perf_evsel *evsel; 846745cefc5SArnaldo Carvalho de Melo int err = 0; 847745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 848b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 849745cefc5SArnaldo Carvalho de Melo 850745cefc5SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 851745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); 852745cefc5SArnaldo Carvalho de Melo if (err) 853745cefc5SArnaldo Carvalho de Melo break; 854745cefc5SArnaldo Carvalho de Melo } 855745cefc5SArnaldo Carvalho de Melo 856745cefc5SArnaldo Carvalho de Melo return err; 8570a102479SFrederic Weisbecker } 85874429964SFrederic Weisbecker 8590c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 86074429964SFrederic Weisbecker { 86175562573SAdrian Hunter struct perf_evsel *pos; 862c2a70653SArnaldo Carvalho de Melo 86375562573SAdrian Hunter if (evlist->nr_entries == 1) 86475562573SAdrian Hunter return true; 86575562573SAdrian Hunter 86675562573SAdrian Hunter if (evlist->id_pos < 0 || evlist->is_pos < 0) 86775562573SAdrian Hunter return false; 86875562573SAdrian Hunter 86975562573SAdrian Hunter list_for_each_entry(pos, &evlist->entries, node) { 87075562573SAdrian Hunter if (pos->id_pos != evlist->id_pos || 87175562573SAdrian Hunter pos->is_pos != evlist->is_pos) 872c2a70653SArnaldo Carvalho de Melo return false; 87374429964SFrederic Weisbecker } 87474429964SFrederic Weisbecker 875c2a70653SArnaldo Carvalho de Melo return true; 876c2a70653SArnaldo Carvalho de Melo } 877c2a70653SArnaldo Carvalho de Melo 87875562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) 879c2a70653SArnaldo Carvalho de Melo { 88075562573SAdrian Hunter struct perf_evsel *evsel; 88175562573SAdrian Hunter 88275562573SAdrian Hunter if (evlist->combined_sample_type) 88375562573SAdrian Hunter return evlist->combined_sample_type; 88475562573SAdrian Hunter 88575562573SAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) 88675562573SAdrian Hunter evlist->combined_sample_type |= evsel->attr.sample_type; 88775562573SAdrian Hunter 88875562573SAdrian Hunter return evlist->combined_sample_type; 88975562573SAdrian Hunter } 89075562573SAdrian Hunter 89175562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) 89275562573SAdrian Hunter { 89375562573SAdrian Hunter evlist->combined_sample_type = 0; 89475562573SAdrian Hunter return __perf_evlist__combined_sample_type(evlist); 895c2a70653SArnaldo Carvalho de Melo } 896c2a70653SArnaldo Carvalho de Melo 8979ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist) 8989ede473cSJiri Olsa { 8999ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 9009ede473cSJiri Olsa u64 read_format = first->attr.read_format; 9019ede473cSJiri Olsa u64 sample_type = first->attr.sample_type; 9029ede473cSJiri Olsa 9039ede473cSJiri Olsa list_for_each_entry_continue(pos, &evlist->entries, node) { 9049ede473cSJiri Olsa if (read_format != pos->attr.read_format) 9059ede473cSJiri Olsa return false; 9069ede473cSJiri Olsa } 9079ede473cSJiri Olsa 9089ede473cSJiri Olsa /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */ 9099ede473cSJiri Olsa if ((sample_type & PERF_SAMPLE_READ) && 9109ede473cSJiri Olsa !(read_format & PERF_FORMAT_ID)) { 9119ede473cSJiri Olsa return false; 9129ede473cSJiri Olsa } 9139ede473cSJiri Olsa 9149ede473cSJiri Olsa return true; 9159ede473cSJiri Olsa } 9169ede473cSJiri Olsa 9179ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist) 9189ede473cSJiri Olsa { 9199ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist); 9209ede473cSJiri Olsa return first->attr.read_format; 9219ede473cSJiri Olsa } 9229ede473cSJiri Olsa 9230c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) 92481e36bffSArnaldo Carvalho de Melo { 9250c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 92681e36bffSArnaldo Carvalho de Melo struct perf_sample *data; 92781e36bffSArnaldo Carvalho de Melo u64 sample_type; 92881e36bffSArnaldo Carvalho de Melo u16 size = 0; 92981e36bffSArnaldo Carvalho de Melo 93081e36bffSArnaldo Carvalho de Melo if (!first->attr.sample_id_all) 93181e36bffSArnaldo Carvalho de Melo goto out; 93281e36bffSArnaldo Carvalho de Melo 93381e36bffSArnaldo Carvalho de Melo sample_type = first->attr.sample_type; 93481e36bffSArnaldo Carvalho de Melo 93581e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TID) 93681e36bffSArnaldo Carvalho de Melo size += sizeof(data->tid) * 2; 93781e36bffSArnaldo Carvalho de Melo 93881e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TIME) 93981e36bffSArnaldo Carvalho de Melo size += sizeof(data->time); 94081e36bffSArnaldo Carvalho de Melo 94181e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_ID) 94281e36bffSArnaldo Carvalho de Melo size += sizeof(data->id); 94381e36bffSArnaldo Carvalho de Melo 94481e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_STREAM_ID) 94581e36bffSArnaldo Carvalho de Melo size += sizeof(data->stream_id); 94681e36bffSArnaldo Carvalho de Melo 94781e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_CPU) 94881e36bffSArnaldo Carvalho de Melo size += sizeof(data->cpu) * 2; 94975562573SAdrian Hunter 95075562573SAdrian Hunter if (sample_type & PERF_SAMPLE_IDENTIFIER) 95175562573SAdrian Hunter size += sizeof(data->id); 95281e36bffSArnaldo Carvalho de Melo out: 95381e36bffSArnaldo Carvalho de Melo return size; 95481e36bffSArnaldo Carvalho de Melo } 95581e36bffSArnaldo Carvalho de Melo 9560c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) 957c2a70653SArnaldo Carvalho de Melo { 9580c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 959c2a70653SArnaldo Carvalho de Melo 960c2a70653SArnaldo Carvalho de Melo list_for_each_entry_continue(pos, &evlist->entries, node) { 961c2a70653SArnaldo Carvalho de Melo if (first->attr.sample_id_all != pos->attr.sample_id_all) 962c2a70653SArnaldo Carvalho de Melo return false; 963c2a70653SArnaldo Carvalho de Melo } 964c2a70653SArnaldo Carvalho de Melo 965c2a70653SArnaldo Carvalho de Melo return true; 96674429964SFrederic Weisbecker } 96774429964SFrederic Weisbecker 9680c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist) 96974429964SFrederic Weisbecker { 9700c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 971c2a70653SArnaldo Carvalho de Melo return first->attr.sample_id_all; 97274429964SFrederic Weisbecker } 97381cce8deSArnaldo Carvalho de Melo 97481cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist, 97581cce8deSArnaldo Carvalho de Melo struct perf_evsel *evsel) 97681cce8deSArnaldo Carvalho de Melo { 97781cce8deSArnaldo Carvalho de Melo evlist->selected = evsel; 97881cce8deSArnaldo Carvalho de Melo } 979727ab04eSArnaldo Carvalho de Melo 980a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist) 981a74b4b66SNamhyung Kim { 982a74b4b66SNamhyung Kim struct perf_evsel *evsel; 983a74b4b66SNamhyung Kim int ncpus = cpu_map__nr(evlist->cpus); 984a74b4b66SNamhyung Kim int nthreads = thread_map__nr(evlist->threads); 985a74b4b66SNamhyung Kim 986a74b4b66SNamhyung Kim list_for_each_entry_reverse(evsel, &evlist->entries, node) 987a74b4b66SNamhyung Kim perf_evsel__close(evsel, ncpus, nthreads); 988a74b4b66SNamhyung Kim } 989a74b4b66SNamhyung Kim 9906a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist) 991727ab04eSArnaldo Carvalho de Melo { 9926a4bb04cSJiri Olsa struct perf_evsel *evsel; 993a74b4b66SNamhyung Kim int err; 994727ab04eSArnaldo Carvalho de Melo 995733cd2feSAdrian Hunter perf_evlist__update_id_pos(evlist); 996733cd2feSAdrian Hunter 997727ab04eSArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 9986a4bb04cSJiri Olsa err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 999727ab04eSArnaldo Carvalho de Melo if (err < 0) 1000727ab04eSArnaldo Carvalho de Melo goto out_err; 1001727ab04eSArnaldo Carvalho de Melo } 1002727ab04eSArnaldo Carvalho de Melo 1003727ab04eSArnaldo Carvalho de Melo return 0; 1004727ab04eSArnaldo Carvalho de Melo out_err: 1005a74b4b66SNamhyung Kim perf_evlist__close(evlist); 100641c21a68SNamhyung Kim errno = -err; 1007727ab04eSArnaldo Carvalho de Melo return err; 1008727ab04eSArnaldo Carvalho de Melo } 100935b9d88eSArnaldo Carvalho de Melo 101035b9d88eSArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, 10116ef73ec4SNamhyung Kim struct perf_target *target, 101255e162eaSNamhyung Kim const char *argv[], bool pipe_output, 101355e162eaSNamhyung Kim bool want_signal) 101435b9d88eSArnaldo Carvalho de Melo { 101535b9d88eSArnaldo Carvalho de Melo int child_ready_pipe[2], go_pipe[2]; 101635b9d88eSArnaldo Carvalho de Melo char bf; 101735b9d88eSArnaldo Carvalho de Melo 101835b9d88eSArnaldo Carvalho de Melo if (pipe(child_ready_pipe) < 0) { 101935b9d88eSArnaldo Carvalho de Melo perror("failed to create 'ready' pipe"); 102035b9d88eSArnaldo Carvalho de Melo return -1; 102135b9d88eSArnaldo Carvalho de Melo } 102235b9d88eSArnaldo Carvalho de Melo 102335b9d88eSArnaldo Carvalho de Melo if (pipe(go_pipe) < 0) { 102435b9d88eSArnaldo Carvalho de Melo perror("failed to create 'go' pipe"); 102535b9d88eSArnaldo Carvalho de Melo goto out_close_ready_pipe; 102635b9d88eSArnaldo Carvalho de Melo } 102735b9d88eSArnaldo Carvalho de Melo 102835b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = fork(); 102935b9d88eSArnaldo Carvalho de Melo if (evlist->workload.pid < 0) { 103035b9d88eSArnaldo Carvalho de Melo perror("failed to fork"); 103135b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 103235b9d88eSArnaldo Carvalho de Melo } 103335b9d88eSArnaldo Carvalho de Melo 103435b9d88eSArnaldo Carvalho de Melo if (!evlist->workload.pid) { 1035119fa3c9SNamhyung Kim if (pipe_output) 103635b9d88eSArnaldo Carvalho de Melo dup2(2, 1); 103735b9d88eSArnaldo Carvalho de Melo 10380817df08SDavid Ahern signal(SIGTERM, SIG_DFL); 10390817df08SDavid Ahern 104035b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 104135b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 104235b9d88eSArnaldo Carvalho de Melo fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 104335b9d88eSArnaldo Carvalho de Melo 104435b9d88eSArnaldo Carvalho de Melo /* 104535b9d88eSArnaldo Carvalho de Melo * Tell the parent we're ready to go 104635b9d88eSArnaldo Carvalho de Melo */ 104735b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 104835b9d88eSArnaldo Carvalho de Melo 104935b9d88eSArnaldo Carvalho de Melo /* 105035b9d88eSArnaldo Carvalho de Melo * Wait until the parent tells us to go. 105135b9d88eSArnaldo Carvalho de Melo */ 105235b9d88eSArnaldo Carvalho de Melo if (read(go_pipe[0], &bf, 1) == -1) 105335b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 105435b9d88eSArnaldo Carvalho de Melo 105535b9d88eSArnaldo Carvalho de Melo execvp(argv[0], (char **)argv); 105635b9d88eSArnaldo Carvalho de Melo 105735b9d88eSArnaldo Carvalho de Melo perror(argv[0]); 105855e162eaSNamhyung Kim if (want_signal) 105935b9d88eSArnaldo Carvalho de Melo kill(getppid(), SIGUSR1); 106035b9d88eSArnaldo Carvalho de Melo exit(-1); 106135b9d88eSArnaldo Carvalho de Melo } 106235b9d88eSArnaldo Carvalho de Melo 10636ef73ec4SNamhyung Kim if (perf_target__none(target)) 106435b9d88eSArnaldo Carvalho de Melo evlist->threads->map[0] = evlist->workload.pid; 106535b9d88eSArnaldo Carvalho de Melo 106635b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 106735b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 106835b9d88eSArnaldo Carvalho de Melo /* 106935b9d88eSArnaldo Carvalho de Melo * wait for child to settle 107035b9d88eSArnaldo Carvalho de Melo */ 107135b9d88eSArnaldo Carvalho de Melo if (read(child_ready_pipe[0], &bf, 1) == -1) { 107235b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 107335b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 107435b9d88eSArnaldo Carvalho de Melo } 107535b9d88eSArnaldo Carvalho de Melo 1076bcf3145fSNamhyung Kim fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC); 107735b9d88eSArnaldo Carvalho de Melo evlist->workload.cork_fd = go_pipe[1]; 107835b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 107935b9d88eSArnaldo Carvalho de Melo return 0; 108035b9d88eSArnaldo Carvalho de Melo 108135b9d88eSArnaldo Carvalho de Melo out_close_pipes: 108235b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 108335b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 108435b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe: 108535b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 108635b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 108735b9d88eSArnaldo Carvalho de Melo return -1; 108835b9d88eSArnaldo Carvalho de Melo } 108935b9d88eSArnaldo Carvalho de Melo 109035b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist) 109135b9d88eSArnaldo Carvalho de Melo { 109235b9d88eSArnaldo Carvalho de Melo if (evlist->workload.cork_fd > 0) { 1093b3824404SDavid Ahern char bf = 0; 1094bcf3145fSNamhyung Kim int ret; 109535b9d88eSArnaldo Carvalho de Melo /* 109635b9d88eSArnaldo Carvalho de Melo * Remove the cork, let it rip! 109735b9d88eSArnaldo Carvalho de Melo */ 1098bcf3145fSNamhyung Kim ret = write(evlist->workload.cork_fd, &bf, 1); 1099bcf3145fSNamhyung Kim if (ret < 0) 1100bcf3145fSNamhyung Kim perror("enable to write to pipe"); 1101bcf3145fSNamhyung Kim 1102bcf3145fSNamhyung Kim close(evlist->workload.cork_fd); 1103bcf3145fSNamhyung Kim return ret; 110435b9d88eSArnaldo Carvalho de Melo } 110535b9d88eSArnaldo Carvalho de Melo 110635b9d88eSArnaldo Carvalho de Melo return 0; 110735b9d88eSArnaldo Carvalho de Melo } 1108cb0b29e0SArnaldo Carvalho de Melo 1109a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 11100807d2d8SArnaldo Carvalho de Melo struct perf_sample *sample) 1111cb0b29e0SArnaldo Carvalho de Melo { 111275562573SAdrian Hunter struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); 111375562573SAdrian Hunter 111475562573SAdrian Hunter if (!evsel) 111575562573SAdrian Hunter return -EFAULT; 11160807d2d8SArnaldo Carvalho de Melo return perf_evsel__parse_sample(evsel, event, sample); 1117cb0b29e0SArnaldo Carvalho de Melo } 111878f067b3SArnaldo Carvalho de Melo 111978f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) 112078f067b3SArnaldo Carvalho de Melo { 112178f067b3SArnaldo Carvalho de Melo struct perf_evsel *evsel; 112278f067b3SArnaldo Carvalho de Melo size_t printed = 0; 112378f067b3SArnaldo Carvalho de Melo 112478f067b3SArnaldo Carvalho de Melo list_for_each_entry(evsel, &evlist->entries, node) { 112578f067b3SArnaldo Carvalho de Melo printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 112678f067b3SArnaldo Carvalho de Melo perf_evsel__name(evsel)); 112778f067b3SArnaldo Carvalho de Melo } 112878f067b3SArnaldo Carvalho de Melo 112978f067b3SArnaldo Carvalho de Melo return printed + fprintf(fp, "\n");; 113078f067b3SArnaldo Carvalho de Melo } 11316ef068cbSArnaldo Carvalho de Melo 11326ef068cbSArnaldo Carvalho de Melo int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, 11336ef068cbSArnaldo Carvalho de Melo int err, char *buf, size_t size) 11346ef068cbSArnaldo Carvalho de Melo { 11356ef068cbSArnaldo Carvalho de Melo char sbuf[128]; 11366ef068cbSArnaldo Carvalho de Melo 11376ef068cbSArnaldo Carvalho de Melo switch (err) { 11386ef068cbSArnaldo Carvalho de Melo case ENOENT: 11396ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", 11406ef068cbSArnaldo Carvalho de Melo "Error:\tUnable to find debugfs\n" 11416ef068cbSArnaldo Carvalho de Melo "Hint:\tWas your kernel was compiled with debugfs support?\n" 11426ef068cbSArnaldo Carvalho de Melo "Hint:\tIs the debugfs filesystem mounted?\n" 11436ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); 11446ef068cbSArnaldo Carvalho de Melo break; 11456ef068cbSArnaldo Carvalho de Melo case EACCES: 11466ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, 11476ef068cbSArnaldo Carvalho de Melo "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" 11486ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", 11496ef068cbSArnaldo Carvalho de Melo debugfs_mountpoint, debugfs_mountpoint); 11506ef068cbSArnaldo Carvalho de Melo break; 11516ef068cbSArnaldo Carvalho de Melo default: 11526ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf))); 11536ef068cbSArnaldo Carvalho de Melo break; 11546ef068cbSArnaldo Carvalho de Melo } 11556ef068cbSArnaldo Carvalho de Melo 11566ef068cbSArnaldo Carvalho de Melo return 0; 11576ef068cbSArnaldo Carvalho de Melo } 1158a8f23d8fSArnaldo Carvalho de Melo 1159a8f23d8fSArnaldo Carvalho de Melo int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, 1160a8f23d8fSArnaldo Carvalho de Melo int err, char *buf, size_t size) 1161a8f23d8fSArnaldo Carvalho de Melo { 1162a8f23d8fSArnaldo Carvalho de Melo int printed, value; 1163a8f23d8fSArnaldo Carvalho de Melo char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1164a8f23d8fSArnaldo Carvalho de Melo 1165a8f23d8fSArnaldo Carvalho de Melo switch (err) { 1166a8f23d8fSArnaldo Carvalho de Melo case EACCES: 1167a8f23d8fSArnaldo Carvalho de Melo case EPERM: 1168a8f23d8fSArnaldo Carvalho de Melo printed = scnprintf(buf, size, 1169a8f23d8fSArnaldo Carvalho de Melo "Error:\t%s.\n" 1170a8f23d8fSArnaldo Carvalho de Melo "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1171a8f23d8fSArnaldo Carvalho de Melo 1172a8f23d8fSArnaldo Carvalho de Melo if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) 1173a8f23d8fSArnaldo Carvalho de Melo break; 1174a8f23d8fSArnaldo Carvalho de Melo 1175a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1176a8f23d8fSArnaldo Carvalho de Melo 1177a8f23d8fSArnaldo Carvalho de Melo if (value >= 2) { 1178a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1179a8f23d8fSArnaldo Carvalho de Melo "For your workloads it needs to be <= 1\nHint:\t"); 1180a8f23d8fSArnaldo Carvalho de Melo } 1181a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1182a8f23d8fSArnaldo Carvalho de Melo "For system wide tracing it needs to be set to -1"); 1183a8f23d8fSArnaldo Carvalho de Melo 1184a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1185a8f23d8fSArnaldo Carvalho de Melo ".\nHint:\tThe current value is %d.", value); 1186a8f23d8fSArnaldo Carvalho de Melo break; 1187a8f23d8fSArnaldo Carvalho de Melo default: 1188a8f23d8fSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", emsg); 1189a8f23d8fSArnaldo Carvalho de Melo break; 1190a8f23d8fSArnaldo Carvalho de Melo } 1191a8f23d8fSArnaldo Carvalho de Melo 1192a8f23d8fSArnaldo Carvalho de Melo return 0; 1193a8f23d8fSArnaldo Carvalho de Melo } 1194