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 28e4b356b5SArnaldo Carvalho de Melo static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 29e4b356b5SArnaldo Carvalho de Melo static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 30e4b356b5SArnaldo Carvalho de Melo 31f8a95309SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 32a91e5431SArnaldo Carvalho de Melo #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 33f8a95309SArnaldo Carvalho de Melo 347e2ed097SArnaldo Carvalho de Melo void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 357e2ed097SArnaldo Carvalho de Melo struct thread_map *threads) 36361c99a6SArnaldo Carvalho de Melo { 3770db7533SArnaldo Carvalho de Melo int i; 3870db7533SArnaldo Carvalho de Melo 3970db7533SArnaldo Carvalho de Melo for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) 4070db7533SArnaldo Carvalho de Melo INIT_HLIST_HEAD(&evlist->heads[i]); 41361c99a6SArnaldo Carvalho de Melo INIT_LIST_HEAD(&evlist->entries); 427e2ed097SArnaldo Carvalho de Melo perf_evlist__set_maps(evlist, cpus, threads); 431b85337dSArnaldo Carvalho de Melo fdarray__init(&evlist->pollfd, 64); 4435b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = -1; 45361c99a6SArnaldo Carvalho de Melo } 46361c99a6SArnaldo Carvalho de Melo 47334fe7a3SNamhyung Kim struct perf_evlist *perf_evlist__new(void) 48ef1d1af2SArnaldo Carvalho de Melo { 49ef1d1af2SArnaldo Carvalho de Melo struct perf_evlist *evlist = zalloc(sizeof(*evlist)); 50ef1d1af2SArnaldo Carvalho de Melo 51ef1d1af2SArnaldo Carvalho de Melo if (evlist != NULL) 52334fe7a3SNamhyung Kim perf_evlist__init(evlist, NULL, NULL); 53ef1d1af2SArnaldo Carvalho de Melo 54361c99a6SArnaldo Carvalho de Melo return evlist; 55361c99a6SArnaldo Carvalho de Melo } 56361c99a6SArnaldo Carvalho de Melo 57b22d54b0SJiri Olsa struct perf_evlist *perf_evlist__new_default(void) 58b22d54b0SJiri Olsa { 59b22d54b0SJiri Olsa struct perf_evlist *evlist = perf_evlist__new(); 60b22d54b0SJiri Olsa 61b22d54b0SJiri Olsa if (evlist && perf_evlist__add_default(evlist)) { 62b22d54b0SJiri Olsa perf_evlist__delete(evlist); 63b22d54b0SJiri Olsa evlist = NULL; 64b22d54b0SJiri Olsa } 65b22d54b0SJiri Olsa 66b22d54b0SJiri Olsa return evlist; 67b22d54b0SJiri Olsa } 68b22d54b0SJiri Olsa 6975562573SAdrian Hunter /** 7075562573SAdrian Hunter * perf_evlist__set_id_pos - set the positions of event ids. 7175562573SAdrian Hunter * @evlist: selected event list 7275562573SAdrian Hunter * 7375562573SAdrian Hunter * Events with compatible sample types all have the same id_pos 7475562573SAdrian Hunter * and is_pos. For convenience, put a copy on evlist. 7575562573SAdrian Hunter */ 7675562573SAdrian Hunter void perf_evlist__set_id_pos(struct perf_evlist *evlist) 7775562573SAdrian Hunter { 7875562573SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 7975562573SAdrian Hunter 8075562573SAdrian Hunter evlist->id_pos = first->id_pos; 8175562573SAdrian Hunter evlist->is_pos = first->is_pos; 8275562573SAdrian Hunter } 8375562573SAdrian Hunter 84733cd2feSAdrian Hunter static void perf_evlist__update_id_pos(struct perf_evlist *evlist) 85733cd2feSAdrian Hunter { 86733cd2feSAdrian Hunter struct perf_evsel *evsel; 87733cd2feSAdrian Hunter 880050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) 89733cd2feSAdrian Hunter perf_evsel__calc_id_pos(evsel); 90733cd2feSAdrian Hunter 91733cd2feSAdrian Hunter perf_evlist__set_id_pos(evlist); 92733cd2feSAdrian Hunter } 93733cd2feSAdrian Hunter 94361c99a6SArnaldo Carvalho de Melo static void perf_evlist__purge(struct perf_evlist *evlist) 95361c99a6SArnaldo Carvalho de Melo { 96361c99a6SArnaldo Carvalho de Melo struct perf_evsel *pos, *n; 97361c99a6SArnaldo Carvalho de Melo 980050f7aaSArnaldo Carvalho de Melo evlist__for_each_safe(evlist, n, pos) { 99361c99a6SArnaldo Carvalho de Melo list_del_init(&pos->node); 100361c99a6SArnaldo Carvalho de Melo perf_evsel__delete(pos); 101361c99a6SArnaldo Carvalho de Melo } 102361c99a6SArnaldo Carvalho de Melo 103361c99a6SArnaldo Carvalho de Melo evlist->nr_entries = 0; 104361c99a6SArnaldo Carvalho de Melo } 105361c99a6SArnaldo Carvalho de Melo 106ef1d1af2SArnaldo Carvalho de Melo void perf_evlist__exit(struct perf_evlist *evlist) 107ef1d1af2SArnaldo Carvalho de Melo { 10804662523SArnaldo Carvalho de Melo zfree(&evlist->mmap); 1091b85337dSArnaldo Carvalho de Melo fdarray__exit(&evlist->pollfd); 110ef1d1af2SArnaldo Carvalho de Melo } 111ef1d1af2SArnaldo Carvalho de Melo 112361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist) 113361c99a6SArnaldo Carvalho de Melo { 114983874d1SArnaldo Carvalho de Melo perf_evlist__munmap(evlist); 115f26e1c7cSArnaldo Carvalho de Melo perf_evlist__close(evlist); 11603ad9747SArnaldo Carvalho de Melo cpu_map__delete(evlist->cpus); 11703ad9747SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 11803ad9747SArnaldo Carvalho de Melo evlist->cpus = NULL; 11903ad9747SArnaldo Carvalho de Melo evlist->threads = NULL; 120361c99a6SArnaldo Carvalho de Melo perf_evlist__purge(evlist); 121ef1d1af2SArnaldo Carvalho de Melo perf_evlist__exit(evlist); 122361c99a6SArnaldo Carvalho de Melo free(evlist); 123361c99a6SArnaldo Carvalho de Melo } 124361c99a6SArnaldo Carvalho de Melo 125361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 126361c99a6SArnaldo Carvalho de Melo { 127361c99a6SArnaldo Carvalho de Melo list_add_tail(&entry->node, &evlist->entries); 128ef503831SArnaldo Carvalho de Melo entry->idx = evlist->nr_entries; 12960b0896cSAdrian Hunter entry->tracking = !entry->idx; 130ef503831SArnaldo Carvalho de Melo 13175562573SAdrian Hunter if (!evlist->nr_entries++) 13275562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 133361c99a6SArnaldo Carvalho de Melo } 134361c99a6SArnaldo Carvalho de Melo 1350529bc1fSJiri Olsa void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 13650d08e47SArnaldo Carvalho de Melo struct list_head *list, 13750d08e47SArnaldo Carvalho de Melo int nr_entries) 13850d08e47SArnaldo Carvalho de Melo { 13975562573SAdrian Hunter bool set_id_pos = !evlist->nr_entries; 14075562573SAdrian Hunter 14150d08e47SArnaldo Carvalho de Melo list_splice_tail(list, &evlist->entries); 14250d08e47SArnaldo Carvalho de Melo evlist->nr_entries += nr_entries; 14375562573SAdrian Hunter if (set_id_pos) 14475562573SAdrian Hunter perf_evlist__set_id_pos(evlist); 14550d08e47SArnaldo Carvalho de Melo } 14650d08e47SArnaldo Carvalho de Melo 14763dab225SArnaldo Carvalho de Melo void __perf_evlist__set_leader(struct list_head *list) 14863dab225SArnaldo Carvalho de Melo { 14963dab225SArnaldo Carvalho de Melo struct perf_evsel *evsel, *leader; 15063dab225SArnaldo Carvalho de Melo 15163dab225SArnaldo Carvalho de Melo leader = list_entry(list->next, struct perf_evsel, node); 15297f63e4aSNamhyung Kim evsel = list_entry(list->prev, struct perf_evsel, node); 15397f63e4aSNamhyung Kim 15497f63e4aSNamhyung Kim leader->nr_members = evsel->idx - leader->idx + 1; 15563dab225SArnaldo Carvalho de Melo 1560050f7aaSArnaldo Carvalho de Melo __evlist__for_each(list, evsel) { 15763dab225SArnaldo Carvalho de Melo evsel->leader = leader; 15863dab225SArnaldo Carvalho de Melo } 15963dab225SArnaldo Carvalho de Melo } 16063dab225SArnaldo Carvalho de Melo 16163dab225SArnaldo Carvalho de Melo void perf_evlist__set_leader(struct perf_evlist *evlist) 1626a4bb04cSJiri Olsa { 16397f63e4aSNamhyung Kim if (evlist->nr_entries) { 16497f63e4aSNamhyung Kim evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; 16563dab225SArnaldo Carvalho de Melo __perf_evlist__set_leader(&evlist->entries); 1666a4bb04cSJiri Olsa } 16797f63e4aSNamhyung Kim } 1686a4bb04cSJiri Olsa 169361c99a6SArnaldo Carvalho de Melo int perf_evlist__add_default(struct perf_evlist *evlist) 170361c99a6SArnaldo Carvalho de Melo { 171361c99a6SArnaldo Carvalho de Melo struct perf_event_attr attr = { 172361c99a6SArnaldo Carvalho de Melo .type = PERF_TYPE_HARDWARE, 173361c99a6SArnaldo Carvalho de Melo .config = PERF_COUNT_HW_CPU_CYCLES, 174361c99a6SArnaldo Carvalho de Melo }; 1751aed2671SJoerg Roedel struct perf_evsel *evsel; 176361c99a6SArnaldo Carvalho de Melo 1771aed2671SJoerg Roedel event_attr_init(&attr); 1781aed2671SJoerg Roedel 179ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new(&attr); 180361c99a6SArnaldo Carvalho de Melo if (evsel == NULL) 181cc2d86b0SStephane Eranian goto error; 182cc2d86b0SStephane Eranian 183cc2d86b0SStephane Eranian /* use strdup() because free(evsel) assumes name is allocated */ 184cc2d86b0SStephane Eranian evsel->name = strdup("cycles"); 185cc2d86b0SStephane Eranian if (!evsel->name) 186cc2d86b0SStephane Eranian goto error_free; 187361c99a6SArnaldo Carvalho de Melo 188361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 189361c99a6SArnaldo Carvalho de Melo return 0; 190cc2d86b0SStephane Eranian error_free: 191cc2d86b0SStephane Eranian perf_evsel__delete(evsel); 192cc2d86b0SStephane Eranian error: 193cc2d86b0SStephane Eranian return -ENOMEM; 194361c99a6SArnaldo Carvalho de Melo } 1955c581041SArnaldo Carvalho de Melo 196e60fc847SArnaldo Carvalho de Melo static int perf_evlist__add_attrs(struct perf_evlist *evlist, 19750d08e47SArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 19850d08e47SArnaldo Carvalho de Melo { 19950d08e47SArnaldo Carvalho de Melo struct perf_evsel *evsel, *n; 20050d08e47SArnaldo Carvalho de Melo LIST_HEAD(head); 20150d08e47SArnaldo Carvalho de Melo size_t i; 20250d08e47SArnaldo Carvalho de Melo 20350d08e47SArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) { 204ef503831SArnaldo Carvalho de Melo evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); 20550d08e47SArnaldo Carvalho de Melo if (evsel == NULL) 20650d08e47SArnaldo Carvalho de Melo goto out_delete_partial_list; 20750d08e47SArnaldo Carvalho de Melo list_add_tail(&evsel->node, &head); 20850d08e47SArnaldo Carvalho de Melo } 20950d08e47SArnaldo Carvalho de Melo 21050d08e47SArnaldo Carvalho de Melo perf_evlist__splice_list_tail(evlist, &head, nr_attrs); 21150d08e47SArnaldo Carvalho de Melo 21250d08e47SArnaldo Carvalho de Melo return 0; 21350d08e47SArnaldo Carvalho de Melo 21450d08e47SArnaldo Carvalho de Melo out_delete_partial_list: 2150050f7aaSArnaldo Carvalho de Melo __evlist__for_each_safe(&head, n, evsel) 21650d08e47SArnaldo Carvalho de Melo perf_evsel__delete(evsel); 21750d08e47SArnaldo Carvalho de Melo return -1; 21850d08e47SArnaldo Carvalho de Melo } 21950d08e47SArnaldo Carvalho de Melo 22079695e1bSArnaldo Carvalho de Melo int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 22179695e1bSArnaldo Carvalho de Melo struct perf_event_attr *attrs, size_t nr_attrs) 22279695e1bSArnaldo Carvalho de Melo { 22379695e1bSArnaldo Carvalho de Melo size_t i; 22479695e1bSArnaldo Carvalho de Melo 22579695e1bSArnaldo Carvalho de Melo for (i = 0; i < nr_attrs; i++) 22679695e1bSArnaldo Carvalho de Melo event_attr_init(attrs + i); 22779695e1bSArnaldo Carvalho de Melo 22879695e1bSArnaldo Carvalho de Melo return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 22979695e1bSArnaldo Carvalho de Melo } 23079695e1bSArnaldo Carvalho de Melo 231da378962SArnaldo Carvalho de Melo struct perf_evsel * 232ee29be62SArnaldo Carvalho de Melo perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 233ee29be62SArnaldo Carvalho de Melo { 234ee29be62SArnaldo Carvalho de Melo struct perf_evsel *evsel; 235ee29be62SArnaldo Carvalho de Melo 2360050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 237ee29be62SArnaldo Carvalho de Melo if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 238ee29be62SArnaldo Carvalho de Melo (int)evsel->attr.config == id) 239ee29be62SArnaldo Carvalho de Melo return evsel; 240ee29be62SArnaldo Carvalho de Melo } 241ee29be62SArnaldo Carvalho de Melo 242ee29be62SArnaldo Carvalho de Melo return NULL; 243ee29be62SArnaldo Carvalho de Melo } 244ee29be62SArnaldo Carvalho de Melo 245a2f2804aSDavid Ahern struct perf_evsel * 246a2f2804aSDavid Ahern perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, 247a2f2804aSDavid Ahern const char *name) 248a2f2804aSDavid Ahern { 249a2f2804aSDavid Ahern struct perf_evsel *evsel; 250a2f2804aSDavid Ahern 2510050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 252a2f2804aSDavid Ahern if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && 253a2f2804aSDavid Ahern (strcmp(evsel->name, name) == 0)) 254a2f2804aSDavid Ahern return evsel; 255a2f2804aSDavid Ahern } 256a2f2804aSDavid Ahern 257a2f2804aSDavid Ahern return NULL; 258a2f2804aSDavid Ahern } 259a2f2804aSDavid Ahern 26039876e7dSArnaldo Carvalho de Melo int perf_evlist__add_newtp(struct perf_evlist *evlist, 26139876e7dSArnaldo Carvalho de Melo const char *sys, const char *name, void *handler) 26239876e7dSArnaldo Carvalho de Melo { 263ef503831SArnaldo Carvalho de Melo struct perf_evsel *evsel = perf_evsel__newtp(sys, name); 26439876e7dSArnaldo Carvalho de Melo 26539876e7dSArnaldo Carvalho de Melo if (evsel == NULL) 26639876e7dSArnaldo Carvalho de Melo return -1; 26739876e7dSArnaldo Carvalho de Melo 268744a9719SArnaldo Carvalho de Melo evsel->handler = handler; 26939876e7dSArnaldo Carvalho de Melo perf_evlist__add(evlist, evsel); 27039876e7dSArnaldo Carvalho de Melo return 0; 27139876e7dSArnaldo Carvalho de Melo } 27239876e7dSArnaldo Carvalho de Melo 273bf8e8f4bSAdrian Hunter static int perf_evlist__nr_threads(struct perf_evlist *evlist, 274bf8e8f4bSAdrian Hunter struct perf_evsel *evsel) 275bf8e8f4bSAdrian Hunter { 276bf8e8f4bSAdrian Hunter if (evsel->system_wide) 277bf8e8f4bSAdrian Hunter return 1; 278bf8e8f4bSAdrian Hunter else 279bf8e8f4bSAdrian Hunter return thread_map__nr(evlist->threads); 280bf8e8f4bSAdrian Hunter } 281bf8e8f4bSAdrian Hunter 2824152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist) 2834152ab37SArnaldo Carvalho de Melo { 2844152ab37SArnaldo Carvalho de Melo int cpu, thread; 2854152ab37SArnaldo Carvalho de Melo struct perf_evsel *pos; 286b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 287bf8e8f4bSAdrian Hunter int nr_threads; 2884152ab37SArnaldo Carvalho de Melo 289b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 2900050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 291395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 2923fe4430dSJiri Olsa continue; 293bf8e8f4bSAdrian Hunter nr_threads = perf_evlist__nr_threads(evlist, pos); 294b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 29555da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 29655da8005SNamhyung Kim PERF_EVENT_IOC_DISABLE, 0); 2974152ab37SArnaldo Carvalho de Melo } 2984152ab37SArnaldo Carvalho de Melo } 2994152ab37SArnaldo Carvalho de Melo } 3004152ab37SArnaldo Carvalho de Melo 301764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist) 302764e16a3SDavid Ahern { 303764e16a3SDavid Ahern int cpu, thread; 304764e16a3SDavid Ahern struct perf_evsel *pos; 305b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 306bf8e8f4bSAdrian Hunter int nr_threads; 307764e16a3SDavid Ahern 308b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 3090050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 310395c3070SAdrian Hunter if (!perf_evsel__is_group_leader(pos) || !pos->fd) 3113fe4430dSJiri Olsa continue; 312bf8e8f4bSAdrian Hunter nr_threads = perf_evlist__nr_threads(evlist, pos); 313b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) 31455da8005SNamhyung Kim ioctl(FD(pos, cpu, thread), 31555da8005SNamhyung Kim PERF_EVENT_IOC_ENABLE, 0); 316764e16a3SDavid Ahern } 317764e16a3SDavid Ahern } 318764e16a3SDavid Ahern } 319764e16a3SDavid Ahern 320395c3070SAdrian Hunter int perf_evlist__disable_event(struct perf_evlist *evlist, 321395c3070SAdrian Hunter struct perf_evsel *evsel) 322395c3070SAdrian Hunter { 323395c3070SAdrian Hunter int cpu, thread, err; 324bf8e8f4bSAdrian Hunter int nr_cpus = cpu_map__nr(evlist->cpus); 325bf8e8f4bSAdrian Hunter int nr_threads = perf_evlist__nr_threads(evlist, evsel); 326395c3070SAdrian Hunter 327395c3070SAdrian Hunter if (!evsel->fd) 328395c3070SAdrian Hunter return 0; 329395c3070SAdrian Hunter 330bf8e8f4bSAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) { 331bf8e8f4bSAdrian Hunter for (thread = 0; thread < nr_threads; thread++) { 332395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 333395c3070SAdrian Hunter PERF_EVENT_IOC_DISABLE, 0); 334395c3070SAdrian Hunter if (err) 335395c3070SAdrian Hunter return err; 336395c3070SAdrian Hunter } 337395c3070SAdrian Hunter } 338395c3070SAdrian Hunter return 0; 339395c3070SAdrian Hunter } 340395c3070SAdrian Hunter 341395c3070SAdrian Hunter int perf_evlist__enable_event(struct perf_evlist *evlist, 342395c3070SAdrian Hunter struct perf_evsel *evsel) 343395c3070SAdrian Hunter { 344395c3070SAdrian Hunter int cpu, thread, err; 345bf8e8f4bSAdrian Hunter int nr_cpus = cpu_map__nr(evlist->cpus); 346bf8e8f4bSAdrian Hunter int nr_threads = perf_evlist__nr_threads(evlist, evsel); 347395c3070SAdrian Hunter 348395c3070SAdrian Hunter if (!evsel->fd) 349395c3070SAdrian Hunter return -EINVAL; 350395c3070SAdrian Hunter 351bf8e8f4bSAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) { 352bf8e8f4bSAdrian Hunter for (thread = 0; thread < nr_threads; thread++) { 353395c3070SAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 354395c3070SAdrian Hunter PERF_EVENT_IOC_ENABLE, 0); 355395c3070SAdrian Hunter if (err) 356395c3070SAdrian Hunter return err; 357395c3070SAdrian Hunter } 358395c3070SAdrian Hunter } 359395c3070SAdrian Hunter return 0; 360395c3070SAdrian Hunter } 361395c3070SAdrian Hunter 3621c65056cSAdrian Hunter static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, 3631c65056cSAdrian Hunter struct perf_evsel *evsel, int cpu) 3641c65056cSAdrian Hunter { 3651c65056cSAdrian Hunter int thread, err; 3661c65056cSAdrian Hunter int nr_threads = perf_evlist__nr_threads(evlist, evsel); 3671c65056cSAdrian Hunter 3681c65056cSAdrian Hunter if (!evsel->fd) 3691c65056cSAdrian Hunter return -EINVAL; 3701c65056cSAdrian Hunter 3711c65056cSAdrian Hunter for (thread = 0; thread < nr_threads; thread++) { 3721c65056cSAdrian Hunter err = ioctl(FD(evsel, cpu, thread), 3731c65056cSAdrian Hunter PERF_EVENT_IOC_ENABLE, 0); 3741c65056cSAdrian Hunter if (err) 3751c65056cSAdrian Hunter return err; 3761c65056cSAdrian Hunter } 3771c65056cSAdrian Hunter return 0; 3781c65056cSAdrian Hunter } 3791c65056cSAdrian Hunter 3801c65056cSAdrian Hunter static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, 3811c65056cSAdrian Hunter struct perf_evsel *evsel, 3821c65056cSAdrian Hunter int thread) 3831c65056cSAdrian Hunter { 3841c65056cSAdrian Hunter int cpu, err; 3851c65056cSAdrian Hunter int nr_cpus = cpu_map__nr(evlist->cpus); 3861c65056cSAdrian Hunter 3871c65056cSAdrian Hunter if (!evsel->fd) 3881c65056cSAdrian Hunter return -EINVAL; 3891c65056cSAdrian Hunter 3901c65056cSAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) { 3911c65056cSAdrian Hunter err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0); 3921c65056cSAdrian Hunter if (err) 3931c65056cSAdrian Hunter return err; 3941c65056cSAdrian Hunter } 3951c65056cSAdrian Hunter return 0; 3961c65056cSAdrian Hunter } 3971c65056cSAdrian Hunter 3981c65056cSAdrian Hunter int perf_evlist__enable_event_idx(struct perf_evlist *evlist, 3991c65056cSAdrian Hunter struct perf_evsel *evsel, int idx) 4001c65056cSAdrian Hunter { 4011c65056cSAdrian Hunter bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus); 4021c65056cSAdrian Hunter 4031c65056cSAdrian Hunter if (per_cpu_mmaps) 4041c65056cSAdrian Hunter return perf_evlist__enable_event_cpu(evlist, evsel, idx); 4051c65056cSAdrian Hunter else 4061c65056cSAdrian Hunter return perf_evlist__enable_event_thread(evlist, evsel, idx); 4071c65056cSAdrian Hunter } 4081c65056cSAdrian Hunter 409ad6765ddSArnaldo Carvalho de Melo int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 4105c581041SArnaldo Carvalho de Melo { 411b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 412b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 413bf8e8f4bSAdrian Hunter int nfds = 0; 414bf8e8f4bSAdrian Hunter struct perf_evsel *evsel; 415bf8e8f4bSAdrian Hunter 416bf8e8f4bSAdrian Hunter list_for_each_entry(evsel, &evlist->entries, node) { 417bf8e8f4bSAdrian Hunter if (evsel->system_wide) 418bf8e8f4bSAdrian Hunter nfds += nr_cpus; 419bf8e8f4bSAdrian Hunter else 420bf8e8f4bSAdrian Hunter nfds += nr_cpus * nr_threads; 421bf8e8f4bSAdrian Hunter } 422bf8e8f4bSAdrian Hunter 4231b85337dSArnaldo Carvalho de Melo if (fdarray__available_entries(&evlist->pollfd) < nfds && 4241b85337dSArnaldo Carvalho de Melo fdarray__grow(&evlist->pollfd, nfds) < 0) 425ad6765ddSArnaldo Carvalho de Melo return -ENOMEM; 426ad6765ddSArnaldo Carvalho de Melo 427ad6765ddSArnaldo Carvalho de Melo return 0; 4285c581041SArnaldo Carvalho de Melo } 42970082dd9SArnaldo Carvalho de Melo 430e4b356b5SArnaldo Carvalho de Melo static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx) 431e4b356b5SArnaldo Carvalho de Melo { 432e4b356b5SArnaldo Carvalho de Melo int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP); 433e4b356b5SArnaldo Carvalho de Melo /* 434e4b356b5SArnaldo Carvalho de Melo * Save the idx so that when we filter out fds POLLHUP'ed we can 435e4b356b5SArnaldo Carvalho de Melo * close the associated evlist->mmap[] entry. 436e4b356b5SArnaldo Carvalho de Melo */ 437e4b356b5SArnaldo Carvalho de Melo if (pos >= 0) { 438e4b356b5SArnaldo Carvalho de Melo evlist->pollfd.priv[pos].idx = idx; 439e4b356b5SArnaldo Carvalho de Melo 440e4b356b5SArnaldo Carvalho de Melo fcntl(fd, F_SETFL, O_NONBLOCK); 441e4b356b5SArnaldo Carvalho de Melo } 442e4b356b5SArnaldo Carvalho de Melo 443e4b356b5SArnaldo Carvalho de Melo return pos; 444e4b356b5SArnaldo Carvalho de Melo } 445e4b356b5SArnaldo Carvalho de Melo 446ad6765ddSArnaldo Carvalho de Melo int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 44770082dd9SArnaldo Carvalho de Melo { 448e4b356b5SArnaldo Carvalho de Melo return __perf_evlist__add_pollfd(evlist, fd, -1); 449e4b356b5SArnaldo Carvalho de Melo } 4501b85337dSArnaldo Carvalho de Melo 451e4b356b5SArnaldo Carvalho de Melo static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd) 452e4b356b5SArnaldo Carvalho de Melo { 453e4b356b5SArnaldo Carvalho de Melo struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); 454e4b356b5SArnaldo Carvalho de Melo 455e4b356b5SArnaldo Carvalho de Melo perf_evlist__mmap_put(evlist, fda->priv[fd].idx); 45670082dd9SArnaldo Carvalho de Melo } 45770db7533SArnaldo Carvalho de Melo 4581ddec7f0SArnaldo Carvalho de Melo int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) 4591ddec7f0SArnaldo Carvalho de Melo { 460e4b356b5SArnaldo Carvalho de Melo return fdarray__filter(&evlist->pollfd, revents_and_mask, 461e4b356b5SArnaldo Carvalho de Melo perf_evlist__munmap_filtered); 4621ddec7f0SArnaldo Carvalho de Melo } 4631ddec7f0SArnaldo Carvalho de Melo 464f66a889dSArnaldo Carvalho de Melo int perf_evlist__poll(struct perf_evlist *evlist, int timeout) 465f66a889dSArnaldo Carvalho de Melo { 4661b85337dSArnaldo Carvalho de Melo return fdarray__poll(&evlist->pollfd, timeout); 467f66a889dSArnaldo Carvalho de Melo } 468f66a889dSArnaldo Carvalho de Melo 469a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist, 470a91e5431SArnaldo Carvalho de Melo struct perf_evsel *evsel, 4713d3b5e95SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 4723d3b5e95SArnaldo Carvalho de Melo { 4733d3b5e95SArnaldo Carvalho de Melo int hash; 4743d3b5e95SArnaldo Carvalho de Melo struct perf_sample_id *sid = SID(evsel, cpu, thread); 4753d3b5e95SArnaldo Carvalho de Melo 4763d3b5e95SArnaldo Carvalho de Melo sid->id = id; 4773d3b5e95SArnaldo Carvalho de Melo sid->evsel = evsel; 4783d3b5e95SArnaldo Carvalho de Melo hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); 4793d3b5e95SArnaldo Carvalho de Melo hlist_add_head(&sid->node, &evlist->heads[hash]); 4803d3b5e95SArnaldo Carvalho de Melo } 4813d3b5e95SArnaldo Carvalho de Melo 482a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 483a91e5431SArnaldo Carvalho de Melo int cpu, int thread, u64 id) 484a91e5431SArnaldo Carvalho de Melo { 485a91e5431SArnaldo Carvalho de Melo perf_evlist__id_hash(evlist, evsel, cpu, thread, id); 486a91e5431SArnaldo Carvalho de Melo evsel->id[evsel->ids++] = id; 487a91e5431SArnaldo Carvalho de Melo } 488a91e5431SArnaldo Carvalho de Melo 489a91e5431SArnaldo Carvalho de Melo static int perf_evlist__id_add_fd(struct perf_evlist *evlist, 4903d3b5e95SArnaldo Carvalho de Melo struct perf_evsel *evsel, 491f8a95309SArnaldo Carvalho de Melo int cpu, int thread, int fd) 492f8a95309SArnaldo Carvalho de Melo { 493f8a95309SArnaldo Carvalho de Melo u64 read_data[4] = { 0, }; 4943d3b5e95SArnaldo Carvalho de Melo int id_idx = 1; /* The first entry is the counter value */ 495e2b5abe0SJiri Olsa u64 id; 496e2b5abe0SJiri Olsa int ret; 497e2b5abe0SJiri Olsa 498e2b5abe0SJiri Olsa ret = ioctl(fd, PERF_EVENT_IOC_ID, &id); 499e2b5abe0SJiri Olsa if (!ret) 500e2b5abe0SJiri Olsa goto add; 501e2b5abe0SJiri Olsa 502e2b5abe0SJiri Olsa if (errno != ENOTTY) 503e2b5abe0SJiri Olsa return -1; 504e2b5abe0SJiri Olsa 505e2b5abe0SJiri Olsa /* Legacy way to get event id.. All hail to old kernels! */ 506f8a95309SArnaldo Carvalho de Melo 507c4861afeSJiri Olsa /* 508c4861afeSJiri Olsa * This way does not work with group format read, so bail 509c4861afeSJiri Olsa * out in that case. 510c4861afeSJiri Olsa */ 511c4861afeSJiri Olsa if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP) 512c4861afeSJiri Olsa return -1; 513c4861afeSJiri Olsa 514f8a95309SArnaldo Carvalho de Melo if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 515f8a95309SArnaldo Carvalho de Melo read(fd, &read_data, sizeof(read_data)) == -1) 516f8a95309SArnaldo Carvalho de Melo return -1; 517f8a95309SArnaldo Carvalho de Melo 518f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 519f8a95309SArnaldo Carvalho de Melo ++id_idx; 520f8a95309SArnaldo Carvalho de Melo if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 521f8a95309SArnaldo Carvalho de Melo ++id_idx; 522f8a95309SArnaldo Carvalho de Melo 523e2b5abe0SJiri Olsa id = read_data[id_idx]; 524e2b5abe0SJiri Olsa 525e2b5abe0SJiri Olsa add: 526e2b5abe0SJiri Olsa perf_evlist__id_add(evlist, evsel, cpu, thread, id); 527f8a95309SArnaldo Carvalho de Melo return 0; 528f8a95309SArnaldo Carvalho de Melo } 529f8a95309SArnaldo Carvalho de Melo 530932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 53170db7533SArnaldo Carvalho de Melo { 53270db7533SArnaldo Carvalho de Melo struct hlist_head *head; 53370db7533SArnaldo Carvalho de Melo struct perf_sample_id *sid; 53470db7533SArnaldo Carvalho de Melo int hash; 53570db7533SArnaldo Carvalho de Melo 53670db7533SArnaldo Carvalho de Melo hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 53770db7533SArnaldo Carvalho de Melo head = &evlist->heads[hash]; 53870db7533SArnaldo Carvalho de Melo 539b67bfe0dSSasha Levin hlist_for_each_entry(sid, head, node) 54070db7533SArnaldo Carvalho de Melo if (sid->id == id) 541932a3594SJiri Olsa return sid; 542932a3594SJiri Olsa 543932a3594SJiri Olsa return NULL; 544932a3594SJiri Olsa } 545932a3594SJiri Olsa 546932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 547932a3594SJiri Olsa { 548932a3594SJiri Olsa struct perf_sample_id *sid; 549932a3594SJiri Olsa 550932a3594SJiri Olsa if (evlist->nr_entries == 1) 551932a3594SJiri Olsa return perf_evlist__first(evlist); 552932a3594SJiri Olsa 553932a3594SJiri Olsa sid = perf_evlist__id2sid(evlist, id); 554932a3594SJiri Olsa if (sid) 55570db7533SArnaldo Carvalho de Melo return sid->evsel; 55630e68bccSNamhyung Kim 55730e68bccSNamhyung Kim if (!perf_evlist__sample_id_all(evlist)) 5580c21f736SArnaldo Carvalho de Melo return perf_evlist__first(evlist); 55930e68bccSNamhyung Kim 56070db7533SArnaldo Carvalho de Melo return NULL; 56170db7533SArnaldo Carvalho de Melo } 56204391debSArnaldo Carvalho de Melo 56375562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist, 56475562573SAdrian Hunter union perf_event *event, u64 *id) 56575562573SAdrian Hunter { 56675562573SAdrian Hunter const u64 *array = event->sample.array; 56775562573SAdrian Hunter ssize_t n; 56875562573SAdrian Hunter 56975562573SAdrian Hunter n = (event->header.size - sizeof(event->header)) >> 3; 57075562573SAdrian Hunter 57175562573SAdrian Hunter if (event->header.type == PERF_RECORD_SAMPLE) { 57275562573SAdrian Hunter if (evlist->id_pos >= n) 57375562573SAdrian Hunter return -1; 57475562573SAdrian Hunter *id = array[evlist->id_pos]; 57575562573SAdrian Hunter } else { 57675562573SAdrian Hunter if (evlist->is_pos > n) 57775562573SAdrian Hunter return -1; 57875562573SAdrian Hunter n -= evlist->is_pos; 57975562573SAdrian Hunter *id = array[n]; 58075562573SAdrian Hunter } 58175562573SAdrian Hunter return 0; 58275562573SAdrian Hunter } 58375562573SAdrian Hunter 58475562573SAdrian Hunter static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 58575562573SAdrian Hunter union perf_event *event) 58675562573SAdrian Hunter { 58798be6966SAdrian Hunter struct perf_evsel *first = perf_evlist__first(evlist); 58875562573SAdrian Hunter struct hlist_head *head; 58975562573SAdrian Hunter struct perf_sample_id *sid; 59075562573SAdrian Hunter int hash; 59175562573SAdrian Hunter u64 id; 59275562573SAdrian Hunter 59375562573SAdrian Hunter if (evlist->nr_entries == 1) 59498be6966SAdrian Hunter return first; 59598be6966SAdrian Hunter 59698be6966SAdrian Hunter if (!first->attr.sample_id_all && 59798be6966SAdrian Hunter event->header.type != PERF_RECORD_SAMPLE) 59898be6966SAdrian Hunter return first; 59975562573SAdrian Hunter 60075562573SAdrian Hunter if (perf_evlist__event2id(evlist, event, &id)) 60175562573SAdrian Hunter return NULL; 60275562573SAdrian Hunter 60375562573SAdrian Hunter /* Synthesized events have an id of zero */ 60475562573SAdrian Hunter if (!id) 60598be6966SAdrian Hunter return first; 60675562573SAdrian Hunter 60775562573SAdrian Hunter hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 60875562573SAdrian Hunter head = &evlist->heads[hash]; 60975562573SAdrian Hunter 61075562573SAdrian Hunter hlist_for_each_entry(sid, head, node) { 61175562573SAdrian Hunter if (sid->id == id) 61275562573SAdrian Hunter return sid->evsel; 61375562573SAdrian Hunter } 61475562573SAdrian Hunter return NULL; 61575562573SAdrian Hunter } 61675562573SAdrian Hunter 617aece948fSArnaldo Carvalho de Melo union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 61804391debSArnaldo Carvalho de Melo { 619aece948fSArnaldo Carvalho de Melo struct perf_mmap *md = &evlist->mmap[idx]; 62004391debSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 62104391debSArnaldo Carvalho de Melo unsigned int old = md->prev; 62204391debSArnaldo Carvalho de Melo unsigned char *data = md->base + page_size; 6238115d60cSArnaldo Carvalho de Melo union perf_event *event = NULL; 62404391debSArnaldo Carvalho de Melo 6257bb41152SArnaldo Carvalho de Melo if (evlist->overwrite) { 62604391debSArnaldo Carvalho de Melo /* 62704391debSArnaldo Carvalho de Melo * If we're further behind than half the buffer, there's a chance 62804391debSArnaldo Carvalho de Melo * the writer will bite our tail and mess up the samples under us. 62904391debSArnaldo Carvalho de Melo * 63004391debSArnaldo Carvalho de Melo * If we somehow ended up ahead of the head, we got messed up. 63104391debSArnaldo Carvalho de Melo * 63204391debSArnaldo Carvalho de Melo * In either case, truncate and restart at head. 63304391debSArnaldo Carvalho de Melo */ 6347bb41152SArnaldo Carvalho de Melo int diff = head - old; 63504391debSArnaldo Carvalho de Melo if (diff > md->mask / 2 || diff < 0) { 63604391debSArnaldo Carvalho de Melo fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 63704391debSArnaldo Carvalho de Melo 63804391debSArnaldo Carvalho de Melo /* 63904391debSArnaldo Carvalho de Melo * head points to a known good entry, start there. 64004391debSArnaldo Carvalho de Melo */ 64104391debSArnaldo Carvalho de Melo old = head; 64204391debSArnaldo Carvalho de Melo } 6437bb41152SArnaldo Carvalho de Melo } 64404391debSArnaldo Carvalho de Melo 64504391debSArnaldo Carvalho de Melo if (old != head) { 64604391debSArnaldo Carvalho de Melo size_t size; 64704391debSArnaldo Carvalho de Melo 6488115d60cSArnaldo Carvalho de Melo event = (union perf_event *)&data[old & md->mask]; 64904391debSArnaldo Carvalho de Melo size = event->header.size; 65004391debSArnaldo Carvalho de Melo 65104391debSArnaldo Carvalho de Melo /* 65204391debSArnaldo Carvalho de Melo * Event straddles the mmap boundary -- header should always 65304391debSArnaldo Carvalho de Melo * be inside due to u64 alignment of output. 65404391debSArnaldo Carvalho de Melo */ 65504391debSArnaldo Carvalho de Melo if ((old & md->mask) + size != ((old + size) & md->mask)) { 65604391debSArnaldo Carvalho de Melo unsigned int offset = old; 65704391debSArnaldo Carvalho de Melo unsigned int len = min(sizeof(*event), size), cpy; 658a65cb4b9SJiri Olsa void *dst = md->event_copy; 65904391debSArnaldo Carvalho de Melo 66004391debSArnaldo Carvalho de Melo do { 66104391debSArnaldo Carvalho de Melo cpy = min(md->mask + 1 - (offset & md->mask), len); 66204391debSArnaldo Carvalho de Melo memcpy(dst, &data[offset & md->mask], cpy); 66304391debSArnaldo Carvalho de Melo offset += cpy; 66404391debSArnaldo Carvalho de Melo dst += cpy; 66504391debSArnaldo Carvalho de Melo len -= cpy; 66604391debSArnaldo Carvalho de Melo } while (len); 66704391debSArnaldo Carvalho de Melo 668a65cb4b9SJiri Olsa event = (union perf_event *) md->event_copy; 66904391debSArnaldo Carvalho de Melo } 67004391debSArnaldo Carvalho de Melo 67104391debSArnaldo Carvalho de Melo old += size; 67204391debSArnaldo Carvalho de Melo } 67304391debSArnaldo Carvalho de Melo 67404391debSArnaldo Carvalho de Melo md->prev = old; 6757bb41152SArnaldo Carvalho de Melo 67604391debSArnaldo Carvalho de Melo return event; 67704391debSArnaldo Carvalho de Melo } 678f8a95309SArnaldo Carvalho de Melo 67982396986SArnaldo Carvalho de Melo static bool perf_mmap__empty(struct perf_mmap *md) 68082396986SArnaldo Carvalho de Melo { 68182396986SArnaldo Carvalho de Melo return perf_mmap__read_head(md) != md->prev; 68282396986SArnaldo Carvalho de Melo } 68382396986SArnaldo Carvalho de Melo 68482396986SArnaldo Carvalho de Melo static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 68582396986SArnaldo Carvalho de Melo { 68682396986SArnaldo Carvalho de Melo ++evlist->mmap[idx].refcnt; 68782396986SArnaldo Carvalho de Melo } 68882396986SArnaldo Carvalho de Melo 68982396986SArnaldo Carvalho de Melo static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) 69082396986SArnaldo Carvalho de Melo { 69182396986SArnaldo Carvalho de Melo BUG_ON(evlist->mmap[idx].refcnt == 0); 69282396986SArnaldo Carvalho de Melo 69382396986SArnaldo Carvalho de Melo if (--evlist->mmap[idx].refcnt == 0) 69482396986SArnaldo Carvalho de Melo __perf_evlist__munmap(evlist, idx); 69582396986SArnaldo Carvalho de Melo } 69682396986SArnaldo Carvalho de Melo 6978e50d384SZhouyi Zhou void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 6988e50d384SZhouyi Zhou { 6998e50d384SZhouyi Zhou struct perf_mmap *md = &evlist->mmap[idx]; 70082396986SArnaldo Carvalho de Melo 70182396986SArnaldo Carvalho de Melo if (!evlist->overwrite) { 7028e50d384SZhouyi Zhou unsigned int old = md->prev; 7038e50d384SZhouyi Zhou 7048e50d384SZhouyi Zhou perf_mmap__write_tail(md, old); 7058e50d384SZhouyi Zhou } 70682396986SArnaldo Carvalho de Melo 70782396986SArnaldo Carvalho de Melo if (md->refcnt == 1 && perf_mmap__empty(md)) 70882396986SArnaldo Carvalho de Melo perf_evlist__mmap_put(evlist, idx); 7098e50d384SZhouyi Zhou } 7108e50d384SZhouyi Zhou 71193edcbd9SAdrian Hunter static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 71293edcbd9SAdrian Hunter { 71393edcbd9SAdrian Hunter if (evlist->mmap[idx].base != NULL) { 71493edcbd9SAdrian Hunter munmap(evlist->mmap[idx].base, evlist->mmap_len); 71593edcbd9SAdrian Hunter evlist->mmap[idx].base = NULL; 71682396986SArnaldo Carvalho de Melo evlist->mmap[idx].refcnt = 0; 71793edcbd9SAdrian Hunter } 71893edcbd9SAdrian Hunter } 71993edcbd9SAdrian Hunter 7207e2ed097SArnaldo Carvalho de Melo void perf_evlist__munmap(struct perf_evlist *evlist) 721f8a95309SArnaldo Carvalho de Melo { 722aece948fSArnaldo Carvalho de Melo int i; 723f8a95309SArnaldo Carvalho de Melo 724983874d1SArnaldo Carvalho de Melo if (evlist->mmap == NULL) 725983874d1SArnaldo Carvalho de Melo return; 726983874d1SArnaldo Carvalho de Melo 72793edcbd9SAdrian Hunter for (i = 0; i < evlist->nr_mmaps; i++) 72893edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, i); 729aece948fSArnaldo Carvalho de Melo 73004662523SArnaldo Carvalho de Melo zfree(&evlist->mmap); 731f8a95309SArnaldo Carvalho de Melo } 732f8a95309SArnaldo Carvalho de Melo 733806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 734f8a95309SArnaldo Carvalho de Melo { 735a14bb7a6SArnaldo Carvalho de Melo evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 736ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(evlist->cpus)) 737b3a319d5SNamhyung Kim evlist->nr_mmaps = thread_map__nr(evlist->threads); 738aece948fSArnaldo Carvalho de Melo evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 739f8a95309SArnaldo Carvalho de Melo return evlist->mmap != NULL ? 0 : -ENOMEM; 740f8a95309SArnaldo Carvalho de Melo } 741f8a95309SArnaldo Carvalho de Melo 742a8a8f3ebSAdrian Hunter struct mmap_params { 743a8a8f3ebSAdrian Hunter int prot; 744a8a8f3ebSAdrian Hunter int mask; 745a8a8f3ebSAdrian Hunter }; 746a8a8f3ebSAdrian Hunter 747a8a8f3ebSAdrian Hunter static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 748a8a8f3ebSAdrian Hunter struct mmap_params *mp, int fd) 749f8a95309SArnaldo Carvalho de Melo { 75082396986SArnaldo Carvalho de Melo /* 75182396986SArnaldo Carvalho de Melo * The last one will be done at perf_evlist__mmap_consume(), so that we 75282396986SArnaldo Carvalho de Melo * make sure we don't prevent tools from consuming every last event in 75382396986SArnaldo Carvalho de Melo * the ring buffer. 75482396986SArnaldo Carvalho de Melo * 75582396986SArnaldo Carvalho de Melo * I.e. we can get the POLLHUP meaning that the fd doesn't exist 75682396986SArnaldo Carvalho de Melo * anymore, but the last events for it are still in the ring buffer, 75782396986SArnaldo Carvalho de Melo * waiting to be consumed. 75882396986SArnaldo Carvalho de Melo * 75982396986SArnaldo Carvalho de Melo * Tools can chose to ignore this at their own discretion, but the 76082396986SArnaldo Carvalho de Melo * evlist layer can't just drop it when filtering events in 76182396986SArnaldo Carvalho de Melo * perf_evlist__filter_pollfd(). 76282396986SArnaldo Carvalho de Melo */ 76382396986SArnaldo Carvalho de Melo evlist->mmap[idx].refcnt = 2; 764aece948fSArnaldo Carvalho de Melo evlist->mmap[idx].prev = 0; 765a8a8f3ebSAdrian Hunter evlist->mmap[idx].mask = mp->mask; 766a8a8f3ebSAdrian Hunter evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 767f8a95309SArnaldo Carvalho de Melo MAP_SHARED, fd, 0); 768301b195dSNelson Elhage if (evlist->mmap[idx].base == MAP_FAILED) { 76902635965SAdrian Hunter pr_debug2("failed to mmap perf event ring buffer, error %d\n", 77002635965SAdrian Hunter errno); 771301b195dSNelson Elhage evlist->mmap[idx].base = NULL; 772f8a95309SArnaldo Carvalho de Melo return -1; 773301b195dSNelson Elhage } 774ad6765ddSArnaldo Carvalho de Melo 775f8a95309SArnaldo Carvalho de Melo return 0; 776f8a95309SArnaldo Carvalho de Melo } 777f8a95309SArnaldo Carvalho de Melo 77804e21314SAdrian Hunter static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 779a8a8f3ebSAdrian Hunter struct mmap_params *mp, int cpu, 780a8a8f3ebSAdrian Hunter int thread, int *output) 781aece948fSArnaldo Carvalho de Melo { 782aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 78304e21314SAdrian Hunter 7840050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 785bf8e8f4bSAdrian Hunter int fd; 786bf8e8f4bSAdrian Hunter 787bf8e8f4bSAdrian Hunter if (evsel->system_wide && thread) 788bf8e8f4bSAdrian Hunter continue; 789bf8e8f4bSAdrian Hunter 790bf8e8f4bSAdrian Hunter fd = FD(evsel, cpu, thread); 79104e21314SAdrian Hunter 79204e21314SAdrian Hunter if (*output == -1) { 79304e21314SAdrian Hunter *output = fd; 794a8a8f3ebSAdrian Hunter if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) 79504e21314SAdrian Hunter return -1; 79604e21314SAdrian Hunter } else { 79704e21314SAdrian Hunter if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 79804e21314SAdrian Hunter return -1; 79982396986SArnaldo Carvalho de Melo 80082396986SArnaldo Carvalho de Melo perf_evlist__mmap_get(evlist, idx); 80104e21314SAdrian Hunter } 80204e21314SAdrian Hunter 803e4b356b5SArnaldo Carvalho de Melo if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { 80482396986SArnaldo Carvalho de Melo perf_evlist__mmap_put(evlist, idx); 805ad6765ddSArnaldo Carvalho de Melo return -1; 80682396986SArnaldo Carvalho de Melo } 807033fa713SArnaldo Carvalho de Melo 80804e21314SAdrian Hunter if ((evsel->attr.read_format & PERF_FORMAT_ID) && 80904e21314SAdrian Hunter perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 81004e21314SAdrian Hunter return -1; 81104e21314SAdrian Hunter } 81204e21314SAdrian Hunter 81304e21314SAdrian Hunter return 0; 81404e21314SAdrian Hunter } 81504e21314SAdrian Hunter 816a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, 817a8a8f3ebSAdrian Hunter struct mmap_params *mp) 81804e21314SAdrian Hunter { 819aece948fSArnaldo Carvalho de Melo int cpu, thread; 820b3a319d5SNamhyung Kim int nr_cpus = cpu_map__nr(evlist->cpus); 821b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 822aece948fSArnaldo Carvalho de Melo 823e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per cpu\n"); 824b3a319d5SNamhyung Kim for (cpu = 0; cpu < nr_cpus; cpu++) { 825aece948fSArnaldo Carvalho de Melo int output = -1; 826aece948fSArnaldo Carvalho de Melo 827b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 828a8a8f3ebSAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 829a8a8f3ebSAdrian Hunter thread, &output)) 830aece948fSArnaldo Carvalho de Melo goto out_unmap; 831aece948fSArnaldo Carvalho de Melo } 832aece948fSArnaldo Carvalho de Melo } 833aece948fSArnaldo Carvalho de Melo 834aece948fSArnaldo Carvalho de Melo return 0; 835aece948fSArnaldo Carvalho de Melo 836aece948fSArnaldo Carvalho de Melo out_unmap: 83793edcbd9SAdrian Hunter for (cpu = 0; cpu < nr_cpus; cpu++) 83893edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, cpu); 839aece948fSArnaldo Carvalho de Melo return -1; 840aece948fSArnaldo Carvalho de Melo } 841aece948fSArnaldo Carvalho de Melo 842a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, 843a8a8f3ebSAdrian Hunter struct mmap_params *mp) 844aece948fSArnaldo Carvalho de Melo { 845aece948fSArnaldo Carvalho de Melo int thread; 846b3a319d5SNamhyung Kim int nr_threads = thread_map__nr(evlist->threads); 847aece948fSArnaldo Carvalho de Melo 848e3e1a54fSAdrian Hunter pr_debug2("perf event ring buffer mmapped per thread\n"); 849b3a319d5SNamhyung Kim for (thread = 0; thread < nr_threads; thread++) { 850aece948fSArnaldo Carvalho de Melo int output = -1; 851aece948fSArnaldo Carvalho de Melo 852a8a8f3ebSAdrian Hunter if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 853a8a8f3ebSAdrian Hunter &output)) 854aece948fSArnaldo Carvalho de Melo goto out_unmap; 855aece948fSArnaldo Carvalho de Melo } 856aece948fSArnaldo Carvalho de Melo 857aece948fSArnaldo Carvalho de Melo return 0; 858aece948fSArnaldo Carvalho de Melo 859aece948fSArnaldo Carvalho de Melo out_unmap: 86093edcbd9SAdrian Hunter for (thread = 0; thread < nr_threads; thread++) 86193edcbd9SAdrian Hunter __perf_evlist__munmap(evlist, thread); 862aece948fSArnaldo Carvalho de Melo return -1; 863aece948fSArnaldo Carvalho de Melo } 864aece948fSArnaldo Carvalho de Melo 865994a1f78SJiri Olsa static size_t perf_evlist__mmap_size(unsigned long pages) 866994a1f78SJiri Olsa { 867994a1f78SJiri Olsa /* 512 kiB: default amount of unprivileged mlocked memory */ 868994a1f78SJiri Olsa if (pages == UINT_MAX) 869994a1f78SJiri Olsa pages = (512 * 1024) / page_size; 870994a1f78SJiri Olsa else if (!is_power_of_2(pages)) 871994a1f78SJiri Olsa return 0; 872994a1f78SJiri Olsa 873994a1f78SJiri Olsa return (pages + 1) * page_size; 874994a1f78SJiri Olsa } 875994a1f78SJiri Olsa 87633c2dcfdSDavid Ahern static long parse_pages_arg(const char *str, unsigned long min, 87733c2dcfdSDavid Ahern unsigned long max) 878994a1f78SJiri Olsa { 8792fbe4abeSAdrian Hunter unsigned long pages, val; 88027050f53SJiri Olsa static struct parse_tag tags[] = { 88127050f53SJiri Olsa { .tag = 'B', .mult = 1 }, 88227050f53SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 88327050f53SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 88427050f53SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 88527050f53SJiri Olsa { .tag = 0 }, 88627050f53SJiri Olsa }; 887994a1f78SJiri Olsa 8888973504bSDavid Ahern if (str == NULL) 88933c2dcfdSDavid Ahern return -EINVAL; 8908973504bSDavid Ahern 89127050f53SJiri Olsa val = parse_tag_value(str, tags); 8922fbe4abeSAdrian Hunter if (val != (unsigned long) -1) { 89327050f53SJiri Olsa /* we got file size value */ 89427050f53SJiri Olsa pages = PERF_ALIGN(val, page_size) / page_size; 89527050f53SJiri Olsa } else { 89627050f53SJiri Olsa /* we got pages count value */ 89727050f53SJiri Olsa char *eptr; 898994a1f78SJiri Olsa pages = strtoul(str, &eptr, 10); 89933c2dcfdSDavid Ahern if (*eptr != '\0') 90033c2dcfdSDavid Ahern return -EINVAL; 90127050f53SJiri Olsa } 902994a1f78SJiri Olsa 9032bcab6c1SAdrian Hunter if (pages == 0 && min == 0) { 90433c2dcfdSDavid Ahern /* leave number of pages at 0 */ 9051dbfa938SAdrian Hunter } else if (!is_power_of_2(pages)) { 90633c2dcfdSDavid Ahern /* round pages up to next power of 2 */ 9071dbfa938SAdrian Hunter pages = next_pow2_l(pages); 9081dbfa938SAdrian Hunter if (!pages) 9091dbfa938SAdrian Hunter return -EINVAL; 9109639837eSDavid Ahern pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 9119639837eSDavid Ahern pages * page_size, pages); 9122fbe4abeSAdrian Hunter } 9132fbe4abeSAdrian Hunter 91433c2dcfdSDavid Ahern if (pages > max) 91533c2dcfdSDavid Ahern return -EINVAL; 91633c2dcfdSDavid Ahern 91733c2dcfdSDavid Ahern return pages; 91833c2dcfdSDavid Ahern } 91933c2dcfdSDavid Ahern 92033c2dcfdSDavid Ahern int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, 92133c2dcfdSDavid Ahern int unset __maybe_unused) 92233c2dcfdSDavid Ahern { 92333c2dcfdSDavid Ahern unsigned int *mmap_pages = opt->value; 92433c2dcfdSDavid Ahern unsigned long max = UINT_MAX; 92533c2dcfdSDavid Ahern long pages; 92633c2dcfdSDavid Ahern 927f5ae9c42SAdrian Hunter if (max > SIZE_MAX / page_size) 92833c2dcfdSDavid Ahern max = SIZE_MAX / page_size; 92933c2dcfdSDavid Ahern 93033c2dcfdSDavid Ahern pages = parse_pages_arg(str, 1, max); 93133c2dcfdSDavid Ahern if (pages < 0) { 93233c2dcfdSDavid Ahern pr_err("Invalid argument for --mmap_pages/-m\n"); 933994a1f78SJiri Olsa return -1; 934994a1f78SJiri Olsa } 935994a1f78SJiri Olsa 936994a1f78SJiri Olsa *mmap_pages = pages; 937994a1f78SJiri Olsa return 0; 938994a1f78SJiri Olsa } 939994a1f78SJiri Olsa 940c83fa7f2SAdrian Hunter /** 941c83fa7f2SAdrian Hunter * perf_evlist__mmap - Create mmaps to receive events. 942c83fa7f2SAdrian Hunter * @evlist: list of events 943c83fa7f2SAdrian Hunter * @pages: map length in pages 944c83fa7f2SAdrian Hunter * @overwrite: overwrite older events? 945f8a95309SArnaldo Carvalho de Melo * 946c83fa7f2SAdrian Hunter * If @overwrite is %false the user needs to signal event consumption using 947c83fa7f2SAdrian Hunter * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this 948c83fa7f2SAdrian Hunter * automatically. 949f8a95309SArnaldo Carvalho de Melo * 950c83fa7f2SAdrian Hunter * Return: %0 on success, negative error code otherwise. 951f8a95309SArnaldo Carvalho de Melo */ 95250a682ceSArnaldo Carvalho de Melo int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 95350a682ceSArnaldo Carvalho de Melo bool overwrite) 954f8a95309SArnaldo Carvalho de Melo { 955aece948fSArnaldo Carvalho de Melo struct perf_evsel *evsel; 9567e2ed097SArnaldo Carvalho de Melo const struct cpu_map *cpus = evlist->cpus; 9577e2ed097SArnaldo Carvalho de Melo const struct thread_map *threads = evlist->threads; 958a8a8f3ebSAdrian Hunter struct mmap_params mp = { 959a8a8f3ebSAdrian Hunter .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), 960a8a8f3ebSAdrian Hunter }; 96150a682ceSArnaldo Carvalho de Melo 9627e2ed097SArnaldo Carvalho de Melo if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 963f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 964f8a95309SArnaldo Carvalho de Melo 9651b85337dSArnaldo Carvalho de Melo if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 966f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 967f8a95309SArnaldo Carvalho de Melo 968f8a95309SArnaldo Carvalho de Melo evlist->overwrite = overwrite; 969994a1f78SJiri Olsa evlist->mmap_len = perf_evlist__mmap_size(pages); 9702af68ef5SAdrian Hunter pr_debug("mmap size %zuB\n", evlist->mmap_len); 971a8a8f3ebSAdrian Hunter mp.mask = evlist->mmap_len - page_size - 1; 972f8a95309SArnaldo Carvalho de Melo 9730050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 974f8a95309SArnaldo Carvalho de Melo if ((evsel->attr.read_format & PERF_FORMAT_ID) && 975a91e5431SArnaldo Carvalho de Melo evsel->sample_id == NULL && 976a14bb7a6SArnaldo Carvalho de Melo perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 977f8a95309SArnaldo Carvalho de Melo return -ENOMEM; 978f8a95309SArnaldo Carvalho de Melo } 979f8a95309SArnaldo Carvalho de Melo 980ec1e7e43SSukadev Bhattiprolu if (cpu_map__empty(cpus)) 981a8a8f3ebSAdrian Hunter return perf_evlist__mmap_per_thread(evlist, &mp); 982f8a95309SArnaldo Carvalho de Melo 983a8a8f3ebSAdrian Hunter return perf_evlist__mmap_per_cpu(evlist, &mp); 984f8a95309SArnaldo Carvalho de Melo } 9857e2ed097SArnaldo Carvalho de Melo 986602ad878SArnaldo Carvalho de Melo int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 9877e2ed097SArnaldo Carvalho de Melo { 988b809ac10SNamhyung Kim evlist->threads = thread_map__new_str(target->pid, target->tid, 989b809ac10SNamhyung Kim target->uid); 9907e2ed097SArnaldo Carvalho de Melo 9917e2ed097SArnaldo Carvalho de Melo if (evlist->threads == NULL) 9927e2ed097SArnaldo Carvalho de Melo return -1; 9937e2ed097SArnaldo Carvalho de Melo 9949c105fbcSDongsheng Yang if (target__uses_dummy_map(target)) 995d1cb9fceSNamhyung Kim evlist->cpus = cpu_map__dummy_new(); 996879d77d0SNamhyung Kim else 997879d77d0SNamhyung Kim evlist->cpus = cpu_map__new(target->cpu_list); 9987e2ed097SArnaldo Carvalho de Melo 9997e2ed097SArnaldo Carvalho de Melo if (evlist->cpus == NULL) 10007e2ed097SArnaldo Carvalho de Melo goto out_delete_threads; 10017e2ed097SArnaldo Carvalho de Melo 10027e2ed097SArnaldo Carvalho de Melo return 0; 10037e2ed097SArnaldo Carvalho de Melo 10047e2ed097SArnaldo Carvalho de Melo out_delete_threads: 10057e2ed097SArnaldo Carvalho de Melo thread_map__delete(evlist->threads); 10067e2ed097SArnaldo Carvalho de Melo return -1; 10077e2ed097SArnaldo Carvalho de Melo } 10087e2ed097SArnaldo Carvalho de Melo 10091491a632SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist) 10100a102479SFrederic Weisbecker { 10110a102479SFrederic Weisbecker struct perf_evsel *evsel; 1012745cefc5SArnaldo Carvalho de Melo int err = 0; 1013745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 1014b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 10150a102479SFrederic Weisbecker 10160050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 1017745cefc5SArnaldo Carvalho de Melo if (evsel->filter == NULL) 10180a102479SFrederic Weisbecker continue; 1019745cefc5SArnaldo Carvalho de Melo 1020745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 10210a102479SFrederic Weisbecker if (err) 1022745cefc5SArnaldo Carvalho de Melo break; 10230a102479SFrederic Weisbecker } 10240a102479SFrederic Weisbecker 1025745cefc5SArnaldo Carvalho de Melo return err; 1026745cefc5SArnaldo Carvalho de Melo } 1027745cefc5SArnaldo Carvalho de Melo 1028745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) 1029745cefc5SArnaldo Carvalho de Melo { 1030745cefc5SArnaldo Carvalho de Melo struct perf_evsel *evsel; 1031745cefc5SArnaldo Carvalho de Melo int err = 0; 1032745cefc5SArnaldo Carvalho de Melo const int ncpus = cpu_map__nr(evlist->cpus), 1033b3a319d5SNamhyung Kim nthreads = thread_map__nr(evlist->threads); 1034745cefc5SArnaldo Carvalho de Melo 10350050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 1036745cefc5SArnaldo Carvalho de Melo err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); 1037745cefc5SArnaldo Carvalho de Melo if (err) 1038745cefc5SArnaldo Carvalho de Melo break; 1039745cefc5SArnaldo Carvalho de Melo } 1040745cefc5SArnaldo Carvalho de Melo 1041745cefc5SArnaldo Carvalho de Melo return err; 10420a102479SFrederic Weisbecker } 104374429964SFrederic Weisbecker 10440c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 104574429964SFrederic Weisbecker { 104675562573SAdrian Hunter struct perf_evsel *pos; 1047c2a70653SArnaldo Carvalho de Melo 104875562573SAdrian Hunter if (evlist->nr_entries == 1) 104975562573SAdrian Hunter return true; 105075562573SAdrian Hunter 105175562573SAdrian Hunter if (evlist->id_pos < 0 || evlist->is_pos < 0) 105275562573SAdrian Hunter return false; 105375562573SAdrian Hunter 10540050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 105575562573SAdrian Hunter if (pos->id_pos != evlist->id_pos || 105675562573SAdrian Hunter pos->is_pos != evlist->is_pos) 1057c2a70653SArnaldo Carvalho de Melo return false; 105874429964SFrederic Weisbecker } 105974429964SFrederic Weisbecker 1060c2a70653SArnaldo Carvalho de Melo return true; 1061c2a70653SArnaldo Carvalho de Melo } 1062c2a70653SArnaldo Carvalho de Melo 106375562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) 1064c2a70653SArnaldo Carvalho de Melo { 106575562573SAdrian Hunter struct perf_evsel *evsel; 106675562573SAdrian Hunter 106775562573SAdrian Hunter if (evlist->combined_sample_type) 106875562573SAdrian Hunter return evlist->combined_sample_type; 106975562573SAdrian Hunter 10700050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) 107175562573SAdrian Hunter evlist->combined_sample_type |= evsel->attr.sample_type; 107275562573SAdrian Hunter 107375562573SAdrian Hunter return evlist->combined_sample_type; 107475562573SAdrian Hunter } 107575562573SAdrian Hunter 107675562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist) 107775562573SAdrian Hunter { 107875562573SAdrian Hunter evlist->combined_sample_type = 0; 107975562573SAdrian Hunter return __perf_evlist__combined_sample_type(evlist); 1080c2a70653SArnaldo Carvalho de Melo } 1081c2a70653SArnaldo Carvalho de Melo 10829ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist) 10839ede473cSJiri Olsa { 10849ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 10859ede473cSJiri Olsa u64 read_format = first->attr.read_format; 10869ede473cSJiri Olsa u64 sample_type = first->attr.sample_type; 10879ede473cSJiri Olsa 10880050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 10899ede473cSJiri Olsa if (read_format != pos->attr.read_format) 10909ede473cSJiri Olsa return false; 10919ede473cSJiri Olsa } 10929ede473cSJiri Olsa 10939ede473cSJiri Olsa /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */ 10949ede473cSJiri Olsa if ((sample_type & PERF_SAMPLE_READ) && 10959ede473cSJiri Olsa !(read_format & PERF_FORMAT_ID)) { 10969ede473cSJiri Olsa return false; 10979ede473cSJiri Olsa } 10989ede473cSJiri Olsa 10999ede473cSJiri Olsa return true; 11009ede473cSJiri Olsa } 11019ede473cSJiri Olsa 11029ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist) 11039ede473cSJiri Olsa { 11049ede473cSJiri Olsa struct perf_evsel *first = perf_evlist__first(evlist); 11059ede473cSJiri Olsa return first->attr.read_format; 11069ede473cSJiri Olsa } 11079ede473cSJiri Olsa 11080c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) 110981e36bffSArnaldo Carvalho de Melo { 11100c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 111181e36bffSArnaldo Carvalho de Melo struct perf_sample *data; 111281e36bffSArnaldo Carvalho de Melo u64 sample_type; 111381e36bffSArnaldo Carvalho de Melo u16 size = 0; 111481e36bffSArnaldo Carvalho de Melo 111581e36bffSArnaldo Carvalho de Melo if (!first->attr.sample_id_all) 111681e36bffSArnaldo Carvalho de Melo goto out; 111781e36bffSArnaldo Carvalho de Melo 111881e36bffSArnaldo Carvalho de Melo sample_type = first->attr.sample_type; 111981e36bffSArnaldo Carvalho de Melo 112081e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TID) 112181e36bffSArnaldo Carvalho de Melo size += sizeof(data->tid) * 2; 112281e36bffSArnaldo Carvalho de Melo 112381e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_TIME) 112481e36bffSArnaldo Carvalho de Melo size += sizeof(data->time); 112581e36bffSArnaldo Carvalho de Melo 112681e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_ID) 112781e36bffSArnaldo Carvalho de Melo size += sizeof(data->id); 112881e36bffSArnaldo Carvalho de Melo 112981e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_STREAM_ID) 113081e36bffSArnaldo Carvalho de Melo size += sizeof(data->stream_id); 113181e36bffSArnaldo Carvalho de Melo 113281e36bffSArnaldo Carvalho de Melo if (sample_type & PERF_SAMPLE_CPU) 113381e36bffSArnaldo Carvalho de Melo size += sizeof(data->cpu) * 2; 113475562573SAdrian Hunter 113575562573SAdrian Hunter if (sample_type & PERF_SAMPLE_IDENTIFIER) 113675562573SAdrian Hunter size += sizeof(data->id); 113781e36bffSArnaldo Carvalho de Melo out: 113881e36bffSArnaldo Carvalho de Melo return size; 113981e36bffSArnaldo Carvalho de Melo } 114081e36bffSArnaldo Carvalho de Melo 11410c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) 1142c2a70653SArnaldo Carvalho de Melo { 11430c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 1144c2a70653SArnaldo Carvalho de Melo 11450050f7aaSArnaldo Carvalho de Melo evlist__for_each_continue(evlist, pos) { 1146c2a70653SArnaldo Carvalho de Melo if (first->attr.sample_id_all != pos->attr.sample_id_all) 1147c2a70653SArnaldo Carvalho de Melo return false; 1148c2a70653SArnaldo Carvalho de Melo } 1149c2a70653SArnaldo Carvalho de Melo 1150c2a70653SArnaldo Carvalho de Melo return true; 115174429964SFrederic Weisbecker } 115274429964SFrederic Weisbecker 11530c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist) 115474429964SFrederic Weisbecker { 11550c21f736SArnaldo Carvalho de Melo struct perf_evsel *first = perf_evlist__first(evlist); 1156c2a70653SArnaldo Carvalho de Melo return first->attr.sample_id_all; 115774429964SFrederic Weisbecker } 115881cce8deSArnaldo Carvalho de Melo 115981cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist, 116081cce8deSArnaldo Carvalho de Melo struct perf_evsel *evsel) 116181cce8deSArnaldo Carvalho de Melo { 116281cce8deSArnaldo Carvalho de Melo evlist->selected = evsel; 116381cce8deSArnaldo Carvalho de Melo } 1164727ab04eSArnaldo Carvalho de Melo 1165a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist) 1166a74b4b66SNamhyung Kim { 1167a74b4b66SNamhyung Kim struct perf_evsel *evsel; 1168a74b4b66SNamhyung Kim int ncpus = cpu_map__nr(evlist->cpus); 1169a74b4b66SNamhyung Kim int nthreads = thread_map__nr(evlist->threads); 11708ad9219eSStephane Eranian int n; 1171a74b4b66SNamhyung Kim 11728ad9219eSStephane Eranian evlist__for_each_reverse(evlist, evsel) { 11738ad9219eSStephane Eranian n = evsel->cpus ? evsel->cpus->nr : ncpus; 11748ad9219eSStephane Eranian perf_evsel__close(evsel, n, nthreads); 11758ad9219eSStephane Eranian } 1176a74b4b66SNamhyung Kim } 1177a74b4b66SNamhyung Kim 11786a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist) 1179727ab04eSArnaldo Carvalho de Melo { 11806a4bb04cSJiri Olsa struct perf_evsel *evsel; 1181a74b4b66SNamhyung Kim int err; 1182727ab04eSArnaldo Carvalho de Melo 1183733cd2feSAdrian Hunter perf_evlist__update_id_pos(evlist); 1184733cd2feSAdrian Hunter 11850050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 11866a4bb04cSJiri Olsa err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1187727ab04eSArnaldo Carvalho de Melo if (err < 0) 1188727ab04eSArnaldo Carvalho de Melo goto out_err; 1189727ab04eSArnaldo Carvalho de Melo } 1190727ab04eSArnaldo Carvalho de Melo 1191727ab04eSArnaldo Carvalho de Melo return 0; 1192727ab04eSArnaldo Carvalho de Melo out_err: 1193a74b4b66SNamhyung Kim perf_evlist__close(evlist); 119441c21a68SNamhyung Kim errno = -err; 1195727ab04eSArnaldo Carvalho de Melo return err; 1196727ab04eSArnaldo Carvalho de Melo } 119735b9d88eSArnaldo Carvalho de Melo 1198602ad878SArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, 119955e162eaSNamhyung Kim const char *argv[], bool pipe_output, 1200735f7e0bSArnaldo Carvalho de Melo void (*exec_error)(int signo, siginfo_t *info, void *ucontext)) 120135b9d88eSArnaldo Carvalho de Melo { 120235b9d88eSArnaldo Carvalho de Melo int child_ready_pipe[2], go_pipe[2]; 120335b9d88eSArnaldo Carvalho de Melo char bf; 120435b9d88eSArnaldo Carvalho de Melo 120535b9d88eSArnaldo Carvalho de Melo if (pipe(child_ready_pipe) < 0) { 120635b9d88eSArnaldo Carvalho de Melo perror("failed to create 'ready' pipe"); 120735b9d88eSArnaldo Carvalho de Melo return -1; 120835b9d88eSArnaldo Carvalho de Melo } 120935b9d88eSArnaldo Carvalho de Melo 121035b9d88eSArnaldo Carvalho de Melo if (pipe(go_pipe) < 0) { 121135b9d88eSArnaldo Carvalho de Melo perror("failed to create 'go' pipe"); 121235b9d88eSArnaldo Carvalho de Melo goto out_close_ready_pipe; 121335b9d88eSArnaldo Carvalho de Melo } 121435b9d88eSArnaldo Carvalho de Melo 121535b9d88eSArnaldo Carvalho de Melo evlist->workload.pid = fork(); 121635b9d88eSArnaldo Carvalho de Melo if (evlist->workload.pid < 0) { 121735b9d88eSArnaldo Carvalho de Melo perror("failed to fork"); 121835b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 121935b9d88eSArnaldo Carvalho de Melo } 122035b9d88eSArnaldo Carvalho de Melo 122135b9d88eSArnaldo Carvalho de Melo if (!evlist->workload.pid) { 12225f1c4225SArnaldo Carvalho de Melo int ret; 12235f1c4225SArnaldo Carvalho de Melo 1224119fa3c9SNamhyung Kim if (pipe_output) 122535b9d88eSArnaldo Carvalho de Melo dup2(2, 1); 122635b9d88eSArnaldo Carvalho de Melo 12270817df08SDavid Ahern signal(SIGTERM, SIG_DFL); 12280817df08SDavid Ahern 122935b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 123035b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 123135b9d88eSArnaldo Carvalho de Melo fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 123235b9d88eSArnaldo Carvalho de Melo 123335b9d88eSArnaldo Carvalho de Melo /* 123435b9d88eSArnaldo Carvalho de Melo * Tell the parent we're ready to go 123535b9d88eSArnaldo Carvalho de Melo */ 123635b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 123735b9d88eSArnaldo Carvalho de Melo 123835b9d88eSArnaldo Carvalho de Melo /* 123935b9d88eSArnaldo Carvalho de Melo * Wait until the parent tells us to go. 124035b9d88eSArnaldo Carvalho de Melo */ 12415f1c4225SArnaldo Carvalho de Melo ret = read(go_pipe[0], &bf, 1); 12425f1c4225SArnaldo Carvalho de Melo /* 12435f1c4225SArnaldo Carvalho de Melo * The parent will ask for the execvp() to be performed by 12445f1c4225SArnaldo Carvalho de Melo * writing exactly one byte, in workload.cork_fd, usually via 12455f1c4225SArnaldo Carvalho de Melo * perf_evlist__start_workload(). 12465f1c4225SArnaldo Carvalho de Melo * 12475f1c4225SArnaldo Carvalho de Melo * For cancelling the workload without actuallin running it, 12485f1c4225SArnaldo Carvalho de Melo * the parent will just close workload.cork_fd, without writing 12495f1c4225SArnaldo Carvalho de Melo * anything, i.e. read will return zero and we just exit() 12505f1c4225SArnaldo Carvalho de Melo * here. 12515f1c4225SArnaldo Carvalho de Melo */ 12525f1c4225SArnaldo Carvalho de Melo if (ret != 1) { 12535f1c4225SArnaldo Carvalho de Melo if (ret == -1) 125435b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 12555f1c4225SArnaldo Carvalho de Melo exit(ret); 12565f1c4225SArnaldo Carvalho de Melo } 125735b9d88eSArnaldo Carvalho de Melo 125835b9d88eSArnaldo Carvalho de Melo execvp(argv[0], (char **)argv); 125935b9d88eSArnaldo Carvalho de Melo 1260735f7e0bSArnaldo Carvalho de Melo if (exec_error) { 1261f33cbe72SArnaldo Carvalho de Melo union sigval val; 1262f33cbe72SArnaldo Carvalho de Melo 1263f33cbe72SArnaldo Carvalho de Melo val.sival_int = errno; 1264f33cbe72SArnaldo Carvalho de Melo if (sigqueue(getppid(), SIGUSR1, val)) 126535b9d88eSArnaldo Carvalho de Melo perror(argv[0]); 1266f33cbe72SArnaldo Carvalho de Melo } else 1267f33cbe72SArnaldo Carvalho de Melo perror(argv[0]); 126835b9d88eSArnaldo Carvalho de Melo exit(-1); 126935b9d88eSArnaldo Carvalho de Melo } 127035b9d88eSArnaldo Carvalho de Melo 1271735f7e0bSArnaldo Carvalho de Melo if (exec_error) { 1272735f7e0bSArnaldo Carvalho de Melo struct sigaction act = { 1273735f7e0bSArnaldo Carvalho de Melo .sa_flags = SA_SIGINFO, 1274735f7e0bSArnaldo Carvalho de Melo .sa_sigaction = exec_error, 1275735f7e0bSArnaldo Carvalho de Melo }; 1276735f7e0bSArnaldo Carvalho de Melo sigaction(SIGUSR1, &act, NULL); 1277735f7e0bSArnaldo Carvalho de Melo } 1278735f7e0bSArnaldo Carvalho de Melo 1279602ad878SArnaldo Carvalho de Melo if (target__none(target)) 128035b9d88eSArnaldo Carvalho de Melo evlist->threads->map[0] = evlist->workload.pid; 128135b9d88eSArnaldo Carvalho de Melo 128235b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 128335b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 128435b9d88eSArnaldo Carvalho de Melo /* 128535b9d88eSArnaldo Carvalho de Melo * wait for child to settle 128635b9d88eSArnaldo Carvalho de Melo */ 128735b9d88eSArnaldo Carvalho de Melo if (read(child_ready_pipe[0], &bf, 1) == -1) { 128835b9d88eSArnaldo Carvalho de Melo perror("unable to read pipe"); 128935b9d88eSArnaldo Carvalho de Melo goto out_close_pipes; 129035b9d88eSArnaldo Carvalho de Melo } 129135b9d88eSArnaldo Carvalho de Melo 1292bcf3145fSNamhyung Kim fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC); 129335b9d88eSArnaldo Carvalho de Melo evlist->workload.cork_fd = go_pipe[1]; 129435b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 129535b9d88eSArnaldo Carvalho de Melo return 0; 129635b9d88eSArnaldo Carvalho de Melo 129735b9d88eSArnaldo Carvalho de Melo out_close_pipes: 129835b9d88eSArnaldo Carvalho de Melo close(go_pipe[0]); 129935b9d88eSArnaldo Carvalho de Melo close(go_pipe[1]); 130035b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe: 130135b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[0]); 130235b9d88eSArnaldo Carvalho de Melo close(child_ready_pipe[1]); 130335b9d88eSArnaldo Carvalho de Melo return -1; 130435b9d88eSArnaldo Carvalho de Melo } 130535b9d88eSArnaldo Carvalho de Melo 130635b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist) 130735b9d88eSArnaldo Carvalho de Melo { 130835b9d88eSArnaldo Carvalho de Melo if (evlist->workload.cork_fd > 0) { 1309b3824404SDavid Ahern char bf = 0; 1310bcf3145fSNamhyung Kim int ret; 131135b9d88eSArnaldo Carvalho de Melo /* 131235b9d88eSArnaldo Carvalho de Melo * Remove the cork, let it rip! 131335b9d88eSArnaldo Carvalho de Melo */ 1314bcf3145fSNamhyung Kim ret = write(evlist->workload.cork_fd, &bf, 1); 1315bcf3145fSNamhyung Kim if (ret < 0) 1316bcf3145fSNamhyung Kim perror("enable to write to pipe"); 1317bcf3145fSNamhyung Kim 1318bcf3145fSNamhyung Kim close(evlist->workload.cork_fd); 1319bcf3145fSNamhyung Kim return ret; 132035b9d88eSArnaldo Carvalho de Melo } 132135b9d88eSArnaldo Carvalho de Melo 132235b9d88eSArnaldo Carvalho de Melo return 0; 132335b9d88eSArnaldo Carvalho de Melo } 1324cb0b29e0SArnaldo Carvalho de Melo 1325a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 13260807d2d8SArnaldo Carvalho de Melo struct perf_sample *sample) 1327cb0b29e0SArnaldo Carvalho de Melo { 132875562573SAdrian Hunter struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); 132975562573SAdrian Hunter 133075562573SAdrian Hunter if (!evsel) 133175562573SAdrian Hunter return -EFAULT; 13320807d2d8SArnaldo Carvalho de Melo return perf_evsel__parse_sample(evsel, event, sample); 1333cb0b29e0SArnaldo Carvalho de Melo } 133478f067b3SArnaldo Carvalho de Melo 133578f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) 133678f067b3SArnaldo Carvalho de Melo { 133778f067b3SArnaldo Carvalho de Melo struct perf_evsel *evsel; 133878f067b3SArnaldo Carvalho de Melo size_t printed = 0; 133978f067b3SArnaldo Carvalho de Melo 13400050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, evsel) { 134178f067b3SArnaldo Carvalho de Melo printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 134278f067b3SArnaldo Carvalho de Melo perf_evsel__name(evsel)); 134378f067b3SArnaldo Carvalho de Melo } 134478f067b3SArnaldo Carvalho de Melo 1345b2222139SDavidlohr Bueso return printed + fprintf(fp, "\n"); 134678f067b3SArnaldo Carvalho de Melo } 13476ef068cbSArnaldo Carvalho de Melo 13486ef068cbSArnaldo Carvalho de Melo int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, 13496ef068cbSArnaldo Carvalho de Melo int err, char *buf, size_t size) 13506ef068cbSArnaldo Carvalho de Melo { 13516ef068cbSArnaldo Carvalho de Melo char sbuf[128]; 13526ef068cbSArnaldo Carvalho de Melo 13536ef068cbSArnaldo Carvalho de Melo switch (err) { 13546ef068cbSArnaldo Carvalho de Melo case ENOENT: 13556ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", 13566ef068cbSArnaldo Carvalho de Melo "Error:\tUnable to find debugfs\n" 13576ef068cbSArnaldo Carvalho de Melo "Hint:\tWas your kernel was compiled with debugfs support?\n" 13586ef068cbSArnaldo Carvalho de Melo "Hint:\tIs the debugfs filesystem mounted?\n" 13596ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); 13606ef068cbSArnaldo Carvalho de Melo break; 13616ef068cbSArnaldo Carvalho de Melo case EACCES: 13626ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, 13636ef068cbSArnaldo Carvalho de Melo "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" 13646ef068cbSArnaldo Carvalho de Melo "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", 13656ef068cbSArnaldo Carvalho de Melo debugfs_mountpoint, debugfs_mountpoint); 13666ef068cbSArnaldo Carvalho de Melo break; 13676ef068cbSArnaldo Carvalho de Melo default: 13686ef068cbSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf))); 13696ef068cbSArnaldo Carvalho de Melo break; 13706ef068cbSArnaldo Carvalho de Melo } 13716ef068cbSArnaldo Carvalho de Melo 13726ef068cbSArnaldo Carvalho de Melo return 0; 13736ef068cbSArnaldo Carvalho de Melo } 1374a8f23d8fSArnaldo Carvalho de Melo 1375a8f23d8fSArnaldo Carvalho de Melo int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, 1376a8f23d8fSArnaldo Carvalho de Melo int err, char *buf, size_t size) 1377a8f23d8fSArnaldo Carvalho de Melo { 1378a8f23d8fSArnaldo Carvalho de Melo int printed, value; 13796e81c74cSMasami Hiramatsu char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1380a8f23d8fSArnaldo Carvalho de Melo 1381a8f23d8fSArnaldo Carvalho de Melo switch (err) { 1382a8f23d8fSArnaldo Carvalho de Melo case EACCES: 1383a8f23d8fSArnaldo Carvalho de Melo case EPERM: 1384a8f23d8fSArnaldo Carvalho de Melo printed = scnprintf(buf, size, 1385a8f23d8fSArnaldo Carvalho de Melo "Error:\t%s.\n" 1386a8f23d8fSArnaldo Carvalho de Melo "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1387a8f23d8fSArnaldo Carvalho de Melo 13881a47245dSAdrian Hunter value = perf_event_paranoid(); 1389a8f23d8fSArnaldo Carvalho de Melo 1390a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1391a8f23d8fSArnaldo Carvalho de Melo 1392a8f23d8fSArnaldo Carvalho de Melo if (value >= 2) { 1393a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 1394a8f23d8fSArnaldo Carvalho de Melo "For your workloads it needs to be <= 1\nHint:\t"); 1395a8f23d8fSArnaldo Carvalho de Melo } 1396a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 13975229e366SArnaldo Carvalho de Melo "For system wide tracing it needs to be set to -1.\n"); 1398a8f23d8fSArnaldo Carvalho de Melo 1399a8f23d8fSArnaldo Carvalho de Melo printed += scnprintf(buf + printed, size - printed, 14005229e366SArnaldo Carvalho de Melo "Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n" 14015229e366SArnaldo Carvalho de Melo "Hint:\tThe current value is %d.", value); 1402a8f23d8fSArnaldo Carvalho de Melo break; 1403a8f23d8fSArnaldo Carvalho de Melo default: 1404a8f23d8fSArnaldo Carvalho de Melo scnprintf(buf, size, "%s", emsg); 1405a8f23d8fSArnaldo Carvalho de Melo break; 1406a8f23d8fSArnaldo Carvalho de Melo } 1407a8f23d8fSArnaldo Carvalho de Melo 1408a8f23d8fSArnaldo Carvalho de Melo return 0; 1409a8f23d8fSArnaldo Carvalho de Melo } 1410a025e4f0SAdrian Hunter 1411a025e4f0SAdrian Hunter void perf_evlist__to_front(struct perf_evlist *evlist, 1412a025e4f0SAdrian Hunter struct perf_evsel *move_evsel) 1413a025e4f0SAdrian Hunter { 1414a025e4f0SAdrian Hunter struct perf_evsel *evsel, *n; 1415a025e4f0SAdrian Hunter LIST_HEAD(move); 1416a025e4f0SAdrian Hunter 1417a025e4f0SAdrian Hunter if (move_evsel == perf_evlist__first(evlist)) 1418a025e4f0SAdrian Hunter return; 1419a025e4f0SAdrian Hunter 14200050f7aaSArnaldo Carvalho de Melo evlist__for_each_safe(evlist, n, evsel) { 1421a025e4f0SAdrian Hunter if (evsel->leader == move_evsel->leader) 1422a025e4f0SAdrian Hunter list_move_tail(&evsel->node, &move); 1423a025e4f0SAdrian Hunter } 1424a025e4f0SAdrian Hunter 1425a025e4f0SAdrian Hunter list_splice(&move, &evlist->entries); 1426a025e4f0SAdrian Hunter } 142760b0896cSAdrian Hunter 142860b0896cSAdrian Hunter void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 142960b0896cSAdrian Hunter struct perf_evsel *tracking_evsel) 143060b0896cSAdrian Hunter { 143160b0896cSAdrian Hunter struct perf_evsel *evsel; 143260b0896cSAdrian Hunter 143360b0896cSAdrian Hunter if (tracking_evsel->tracking) 143460b0896cSAdrian Hunter return; 143560b0896cSAdrian Hunter 143660b0896cSAdrian Hunter evlist__for_each(evlist, evsel) { 143760b0896cSAdrian Hunter if (evsel != tracking_evsel) 143860b0896cSAdrian Hunter evsel->tracking = false; 143960b0896cSAdrian Hunter } 144060b0896cSAdrian Hunter 144160b0896cSAdrian Hunter tracking_evsel->tracking = true; 144260b0896cSAdrian Hunter } 1443