xref: /openbmc/linux/tools/perf/util/evlist.c (revision 4768230a)
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"
10956fa571SArnaldo Carvalho de Melo #include <api/fs/fs.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>
270389cd1fSArnaldo Carvalho de Melo #include <linux/log2.h>
288dd2a131SJiri Olsa #include <linux/err.h>
2970db7533SArnaldo Carvalho de Melo 
30e4b356b5SArnaldo Carvalho de Melo static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
31e4b356b5SArnaldo Carvalho de Melo static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
32e4b356b5SArnaldo Carvalho de Melo 
33f8a95309SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34a91e5431SArnaldo Carvalho de Melo #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
35f8a95309SArnaldo Carvalho de Melo 
367e2ed097SArnaldo Carvalho de Melo void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
377e2ed097SArnaldo Carvalho de Melo 		       struct thread_map *threads)
38361c99a6SArnaldo Carvalho de Melo {
3970db7533SArnaldo Carvalho de Melo 	int i;
4070db7533SArnaldo Carvalho de Melo 
4170db7533SArnaldo Carvalho de Melo 	for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
4270db7533SArnaldo Carvalho de Melo 		INIT_HLIST_HEAD(&evlist->heads[i]);
43361c99a6SArnaldo Carvalho de Melo 	INIT_LIST_HEAD(&evlist->entries);
447e2ed097SArnaldo Carvalho de Melo 	perf_evlist__set_maps(evlist, cpus, threads);
451b85337dSArnaldo Carvalho de Melo 	fdarray__init(&evlist->pollfd, 64);
4635b9d88eSArnaldo Carvalho de Melo 	evlist->workload.pid = -1;
47361c99a6SArnaldo Carvalho de Melo }
48361c99a6SArnaldo Carvalho de Melo 
49334fe7a3SNamhyung Kim struct perf_evlist *perf_evlist__new(void)
50ef1d1af2SArnaldo Carvalho de Melo {
51ef1d1af2SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = zalloc(sizeof(*evlist));
52ef1d1af2SArnaldo Carvalho de Melo 
53ef1d1af2SArnaldo Carvalho de Melo 	if (evlist != NULL)
54334fe7a3SNamhyung Kim 		perf_evlist__init(evlist, NULL, NULL);
55ef1d1af2SArnaldo Carvalho de Melo 
56361c99a6SArnaldo Carvalho de Melo 	return evlist;
57361c99a6SArnaldo Carvalho de Melo }
58361c99a6SArnaldo Carvalho de Melo 
59b22d54b0SJiri Olsa struct perf_evlist *perf_evlist__new_default(void)
60b22d54b0SJiri Olsa {
61b22d54b0SJiri Olsa 	struct perf_evlist *evlist = perf_evlist__new();
62b22d54b0SJiri Olsa 
63b22d54b0SJiri Olsa 	if (evlist && perf_evlist__add_default(evlist)) {
64b22d54b0SJiri Olsa 		perf_evlist__delete(evlist);
65b22d54b0SJiri Olsa 		evlist = NULL;
66b22d54b0SJiri Olsa 	}
67b22d54b0SJiri Olsa 
68b22d54b0SJiri Olsa 	return evlist;
69b22d54b0SJiri Olsa }
70b22d54b0SJiri Olsa 
7175562573SAdrian Hunter /**
7275562573SAdrian Hunter  * perf_evlist__set_id_pos - set the positions of event ids.
7375562573SAdrian Hunter  * @evlist: selected event list
7475562573SAdrian Hunter  *
7575562573SAdrian Hunter  * Events with compatible sample types all have the same id_pos
7675562573SAdrian Hunter  * and is_pos.  For convenience, put a copy on evlist.
7775562573SAdrian Hunter  */
7875562573SAdrian Hunter void perf_evlist__set_id_pos(struct perf_evlist *evlist)
7975562573SAdrian Hunter {
8075562573SAdrian Hunter 	struct perf_evsel *first = perf_evlist__first(evlist);
8175562573SAdrian Hunter 
8275562573SAdrian Hunter 	evlist->id_pos = first->id_pos;
8375562573SAdrian Hunter 	evlist->is_pos = first->is_pos;
8475562573SAdrian Hunter }
8575562573SAdrian Hunter 
86733cd2feSAdrian Hunter static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
87733cd2feSAdrian Hunter {
88733cd2feSAdrian Hunter 	struct perf_evsel *evsel;
89733cd2feSAdrian Hunter 
900050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel)
91733cd2feSAdrian Hunter 		perf_evsel__calc_id_pos(evsel);
92733cd2feSAdrian Hunter 
93733cd2feSAdrian Hunter 	perf_evlist__set_id_pos(evlist);
94733cd2feSAdrian Hunter }
95733cd2feSAdrian Hunter 
96361c99a6SArnaldo Carvalho de Melo static void perf_evlist__purge(struct perf_evlist *evlist)
97361c99a6SArnaldo Carvalho de Melo {
98361c99a6SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *n;
99361c99a6SArnaldo Carvalho de Melo 
1000050f7aaSArnaldo Carvalho de Melo 	evlist__for_each_safe(evlist, n, pos) {
101361c99a6SArnaldo Carvalho de Melo 		list_del_init(&pos->node);
102d49e4695SArnaldo Carvalho de Melo 		pos->evlist = NULL;
103361c99a6SArnaldo Carvalho de Melo 		perf_evsel__delete(pos);
104361c99a6SArnaldo Carvalho de Melo 	}
105361c99a6SArnaldo Carvalho de Melo 
106361c99a6SArnaldo Carvalho de Melo 	evlist->nr_entries = 0;
107361c99a6SArnaldo Carvalho de Melo }
108361c99a6SArnaldo Carvalho de Melo 
109ef1d1af2SArnaldo Carvalho de Melo void perf_evlist__exit(struct perf_evlist *evlist)
110ef1d1af2SArnaldo Carvalho de Melo {
11104662523SArnaldo Carvalho de Melo 	zfree(&evlist->mmap);
1121b85337dSArnaldo Carvalho de Melo 	fdarray__exit(&evlist->pollfd);
113ef1d1af2SArnaldo Carvalho de Melo }
114ef1d1af2SArnaldo Carvalho de Melo 
115361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist)
116361c99a6SArnaldo Carvalho de Melo {
117983874d1SArnaldo Carvalho de Melo 	perf_evlist__munmap(evlist);
118f26e1c7cSArnaldo Carvalho de Melo 	perf_evlist__close(evlist);
119f30a79b0SJiri Olsa 	cpu_map__put(evlist->cpus);
120186fbb74SJiri Olsa 	thread_map__put(evlist->threads);
12103ad9747SArnaldo Carvalho de Melo 	evlist->cpus = NULL;
12203ad9747SArnaldo Carvalho de Melo 	evlist->threads = NULL;
123361c99a6SArnaldo Carvalho de Melo 	perf_evlist__purge(evlist);
124ef1d1af2SArnaldo Carvalho de Melo 	perf_evlist__exit(evlist);
125361c99a6SArnaldo Carvalho de Melo 	free(evlist);
126361c99a6SArnaldo Carvalho de Melo }
127361c99a6SArnaldo Carvalho de Melo 
128adc0c3e8SAdrian Hunter static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
129adc0c3e8SAdrian Hunter 					  struct perf_evsel *evsel)
130adc0c3e8SAdrian Hunter {
131adc0c3e8SAdrian Hunter 	/*
132adc0c3e8SAdrian Hunter 	 * We already have cpus for evsel (via PMU sysfs) so
133adc0c3e8SAdrian Hunter 	 * keep it, if there's no target cpu list defined.
134adc0c3e8SAdrian Hunter 	 */
135adc0c3e8SAdrian Hunter 	if (!evsel->own_cpus || evlist->has_user_cpus) {
136adc0c3e8SAdrian Hunter 		cpu_map__put(evsel->cpus);
137adc0c3e8SAdrian Hunter 		evsel->cpus = cpu_map__get(evlist->cpus);
138adc0c3e8SAdrian Hunter 	} else if (evsel->cpus != evsel->own_cpus) {
139adc0c3e8SAdrian Hunter 		cpu_map__put(evsel->cpus);
140adc0c3e8SAdrian Hunter 		evsel->cpus = cpu_map__get(evsel->own_cpus);
141adc0c3e8SAdrian Hunter 	}
142adc0c3e8SAdrian Hunter 
143adc0c3e8SAdrian Hunter 	thread_map__put(evsel->threads);
144adc0c3e8SAdrian Hunter 	evsel->threads = thread_map__get(evlist->threads);
145adc0c3e8SAdrian Hunter }
146adc0c3e8SAdrian Hunter 
147adc0c3e8SAdrian Hunter static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
148adc0c3e8SAdrian Hunter {
149adc0c3e8SAdrian Hunter 	struct perf_evsel *evsel;
150adc0c3e8SAdrian Hunter 
151adc0c3e8SAdrian Hunter 	evlist__for_each(evlist, evsel)
152adc0c3e8SAdrian Hunter 		__perf_evlist__propagate_maps(evlist, evsel);
153adc0c3e8SAdrian Hunter }
154adc0c3e8SAdrian Hunter 
155361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
156361c99a6SArnaldo Carvalho de Melo {
157d49e4695SArnaldo Carvalho de Melo 	entry->evlist = evlist;
158361c99a6SArnaldo Carvalho de Melo 	list_add_tail(&entry->node, &evlist->entries);
159ef503831SArnaldo Carvalho de Melo 	entry->idx = evlist->nr_entries;
16060b0896cSAdrian Hunter 	entry->tracking = !entry->idx;
161ef503831SArnaldo Carvalho de Melo 
16275562573SAdrian Hunter 	if (!evlist->nr_entries++)
16375562573SAdrian Hunter 		perf_evlist__set_id_pos(evlist);
16444c42d71SAdrian Hunter 
16544c42d71SAdrian Hunter 	__perf_evlist__propagate_maps(evlist, entry);
166361c99a6SArnaldo Carvalho de Melo }
167361c99a6SArnaldo Carvalho de Melo 
1684768230aSAdrian Hunter void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
1694768230aSAdrian Hunter {
1704768230aSAdrian Hunter 	evsel->evlist = NULL;
1714768230aSAdrian Hunter 	list_del_init(&evsel->node);
1724768230aSAdrian Hunter 	evlist->nr_entries -= 1;
1734768230aSAdrian Hunter }
1744768230aSAdrian Hunter 
1750529bc1fSJiri Olsa void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
176f114d6efSAdrian Hunter 				   struct list_head *list)
17750d08e47SArnaldo Carvalho de Melo {
178f114d6efSAdrian Hunter 	struct perf_evsel *evsel, *temp;
17975562573SAdrian Hunter 
180f114d6efSAdrian Hunter 	__evlist__for_each_safe(list, temp, evsel) {
181f114d6efSAdrian Hunter 		list_del_init(&evsel->node);
182f114d6efSAdrian Hunter 		perf_evlist__add(evlist, evsel);
183f114d6efSAdrian Hunter 	}
18450d08e47SArnaldo Carvalho de Melo }
18550d08e47SArnaldo Carvalho de Melo 
18663dab225SArnaldo Carvalho de Melo void __perf_evlist__set_leader(struct list_head *list)
18763dab225SArnaldo Carvalho de Melo {
18863dab225SArnaldo Carvalho de Melo 	struct perf_evsel *evsel, *leader;
18963dab225SArnaldo Carvalho de Melo 
19063dab225SArnaldo Carvalho de Melo 	leader = list_entry(list->next, struct perf_evsel, node);
19197f63e4aSNamhyung Kim 	evsel = list_entry(list->prev, struct perf_evsel, node);
19297f63e4aSNamhyung Kim 
19397f63e4aSNamhyung Kim 	leader->nr_members = evsel->idx - leader->idx + 1;
19463dab225SArnaldo Carvalho de Melo 
1950050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each(list, evsel) {
19663dab225SArnaldo Carvalho de Melo 		evsel->leader = leader;
19763dab225SArnaldo Carvalho de Melo 	}
19863dab225SArnaldo Carvalho de Melo }
19963dab225SArnaldo Carvalho de Melo 
20063dab225SArnaldo Carvalho de Melo void perf_evlist__set_leader(struct perf_evlist *evlist)
2016a4bb04cSJiri Olsa {
20297f63e4aSNamhyung Kim 	if (evlist->nr_entries) {
20397f63e4aSNamhyung Kim 		evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
20463dab225SArnaldo Carvalho de Melo 		__perf_evlist__set_leader(&evlist->entries);
2056a4bb04cSJiri Olsa 	}
20697f63e4aSNamhyung Kim }
2076a4bb04cSJiri Olsa 
208361c99a6SArnaldo Carvalho de Melo int perf_evlist__add_default(struct perf_evlist *evlist)
209361c99a6SArnaldo Carvalho de Melo {
210361c99a6SArnaldo Carvalho de Melo 	struct perf_event_attr attr = {
211361c99a6SArnaldo Carvalho de Melo 		.type = PERF_TYPE_HARDWARE,
212361c99a6SArnaldo Carvalho de Melo 		.config = PERF_COUNT_HW_CPU_CYCLES,
213361c99a6SArnaldo Carvalho de Melo 	};
2141aed2671SJoerg Roedel 	struct perf_evsel *evsel;
215361c99a6SArnaldo Carvalho de Melo 
2161aed2671SJoerg Roedel 	event_attr_init(&attr);
2171aed2671SJoerg Roedel 
218ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__new(&attr);
219361c99a6SArnaldo Carvalho de Melo 	if (evsel == NULL)
220cc2d86b0SStephane Eranian 		goto error;
221cc2d86b0SStephane Eranian 
222cc2d86b0SStephane Eranian 	/* use strdup() because free(evsel) assumes name is allocated */
223cc2d86b0SStephane Eranian 	evsel->name = strdup("cycles");
224cc2d86b0SStephane Eranian 	if (!evsel->name)
225cc2d86b0SStephane Eranian 		goto error_free;
226361c99a6SArnaldo Carvalho de Melo 
227361c99a6SArnaldo Carvalho de Melo 	perf_evlist__add(evlist, evsel);
228361c99a6SArnaldo Carvalho de Melo 	return 0;
229cc2d86b0SStephane Eranian error_free:
230cc2d86b0SStephane Eranian 	perf_evsel__delete(evsel);
231cc2d86b0SStephane Eranian error:
232cc2d86b0SStephane Eranian 	return -ENOMEM;
233361c99a6SArnaldo Carvalho de Melo }
2345c581041SArnaldo Carvalho de Melo 
235e60fc847SArnaldo Carvalho de Melo static int perf_evlist__add_attrs(struct perf_evlist *evlist,
23650d08e47SArnaldo Carvalho de Melo 				  struct perf_event_attr *attrs, size_t nr_attrs)
23750d08e47SArnaldo Carvalho de Melo {
23850d08e47SArnaldo Carvalho de Melo 	struct perf_evsel *evsel, *n;
23950d08e47SArnaldo Carvalho de Melo 	LIST_HEAD(head);
24050d08e47SArnaldo Carvalho de Melo 	size_t i;
24150d08e47SArnaldo Carvalho de Melo 
24250d08e47SArnaldo Carvalho de Melo 	for (i = 0; i < nr_attrs; i++) {
243ef503831SArnaldo Carvalho de Melo 		evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i);
24450d08e47SArnaldo Carvalho de Melo 		if (evsel == NULL)
24550d08e47SArnaldo Carvalho de Melo 			goto out_delete_partial_list;
24650d08e47SArnaldo Carvalho de Melo 		list_add_tail(&evsel->node, &head);
24750d08e47SArnaldo Carvalho de Melo 	}
24850d08e47SArnaldo Carvalho de Melo 
249f114d6efSAdrian Hunter 	perf_evlist__splice_list_tail(evlist, &head);
25050d08e47SArnaldo Carvalho de Melo 
25150d08e47SArnaldo Carvalho de Melo 	return 0;
25250d08e47SArnaldo Carvalho de Melo 
25350d08e47SArnaldo Carvalho de Melo out_delete_partial_list:
2540050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each_safe(&head, n, evsel)
25550d08e47SArnaldo Carvalho de Melo 		perf_evsel__delete(evsel);
25650d08e47SArnaldo Carvalho de Melo 	return -1;
25750d08e47SArnaldo Carvalho de Melo }
25850d08e47SArnaldo Carvalho de Melo 
25979695e1bSArnaldo Carvalho de Melo int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
26079695e1bSArnaldo Carvalho de Melo 				     struct perf_event_attr *attrs, size_t nr_attrs)
26179695e1bSArnaldo Carvalho de Melo {
26279695e1bSArnaldo Carvalho de Melo 	size_t i;
26379695e1bSArnaldo Carvalho de Melo 
26479695e1bSArnaldo Carvalho de Melo 	for (i = 0; i < nr_attrs; i++)
26579695e1bSArnaldo Carvalho de Melo 		event_attr_init(attrs + i);
26679695e1bSArnaldo Carvalho de Melo 
26779695e1bSArnaldo Carvalho de Melo 	return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
26879695e1bSArnaldo Carvalho de Melo }
26979695e1bSArnaldo Carvalho de Melo 
270da378962SArnaldo Carvalho de Melo struct perf_evsel *
271ee29be62SArnaldo Carvalho de Melo perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
272ee29be62SArnaldo Carvalho de Melo {
273ee29be62SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
274ee29be62SArnaldo Carvalho de Melo 
2750050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
276ee29be62SArnaldo Carvalho de Melo 		if (evsel->attr.type   == PERF_TYPE_TRACEPOINT &&
277ee29be62SArnaldo Carvalho de Melo 		    (int)evsel->attr.config == id)
278ee29be62SArnaldo Carvalho de Melo 			return evsel;
279ee29be62SArnaldo Carvalho de Melo 	}
280ee29be62SArnaldo Carvalho de Melo 
281ee29be62SArnaldo Carvalho de Melo 	return NULL;
282ee29be62SArnaldo Carvalho de Melo }
283ee29be62SArnaldo Carvalho de Melo 
284a2f2804aSDavid Ahern struct perf_evsel *
285a2f2804aSDavid Ahern perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
286a2f2804aSDavid Ahern 				     const char *name)
287a2f2804aSDavid Ahern {
288a2f2804aSDavid Ahern 	struct perf_evsel *evsel;
289a2f2804aSDavid Ahern 
2900050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
291a2f2804aSDavid Ahern 		if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
292a2f2804aSDavid Ahern 		    (strcmp(evsel->name, name) == 0))
293a2f2804aSDavid Ahern 			return evsel;
294a2f2804aSDavid Ahern 	}
295a2f2804aSDavid Ahern 
296a2f2804aSDavid Ahern 	return NULL;
297a2f2804aSDavid Ahern }
298a2f2804aSDavid Ahern 
29939876e7dSArnaldo Carvalho de Melo int perf_evlist__add_newtp(struct perf_evlist *evlist,
30039876e7dSArnaldo Carvalho de Melo 			   const char *sys, const char *name, void *handler)
30139876e7dSArnaldo Carvalho de Melo {
302ef503831SArnaldo Carvalho de Melo 	struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
30339876e7dSArnaldo Carvalho de Melo 
3048dd2a131SJiri Olsa 	if (IS_ERR(evsel))
30539876e7dSArnaldo Carvalho de Melo 		return -1;
30639876e7dSArnaldo Carvalho de Melo 
307744a9719SArnaldo Carvalho de Melo 	evsel->handler = handler;
30839876e7dSArnaldo Carvalho de Melo 	perf_evlist__add(evlist, evsel);
30939876e7dSArnaldo Carvalho de Melo 	return 0;
31039876e7dSArnaldo Carvalho de Melo }
31139876e7dSArnaldo Carvalho de Melo 
312bf8e8f4bSAdrian Hunter static int perf_evlist__nr_threads(struct perf_evlist *evlist,
313bf8e8f4bSAdrian Hunter 				   struct perf_evsel *evsel)
314bf8e8f4bSAdrian Hunter {
315bf8e8f4bSAdrian Hunter 	if (evsel->system_wide)
316bf8e8f4bSAdrian Hunter 		return 1;
317bf8e8f4bSAdrian Hunter 	else
318bf8e8f4bSAdrian Hunter 		return thread_map__nr(evlist->threads);
319bf8e8f4bSAdrian Hunter }
320bf8e8f4bSAdrian Hunter 
3214152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist)
3224152ab37SArnaldo Carvalho de Melo {
3234152ab37SArnaldo Carvalho de Melo 	int cpu, thread;
3244152ab37SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
325b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
326bf8e8f4bSAdrian Hunter 	int nr_threads;
3274152ab37SArnaldo Carvalho de Melo 
328b3a319d5SNamhyung Kim 	for (cpu = 0; cpu < nr_cpus; cpu++) {
3290050f7aaSArnaldo Carvalho de Melo 		evlist__for_each(evlist, pos) {
330395c3070SAdrian Hunter 			if (!perf_evsel__is_group_leader(pos) || !pos->fd)
3313fe4430dSJiri Olsa 				continue;
332bf8e8f4bSAdrian Hunter 			nr_threads = perf_evlist__nr_threads(evlist, pos);
333b3a319d5SNamhyung Kim 			for (thread = 0; thread < nr_threads; thread++)
33455da8005SNamhyung Kim 				ioctl(FD(pos, cpu, thread),
33555da8005SNamhyung Kim 				      PERF_EVENT_IOC_DISABLE, 0);
3364152ab37SArnaldo Carvalho de Melo 		}
3374152ab37SArnaldo Carvalho de Melo 	}
3382b56bcfbSArnaldo Carvalho de Melo 
3392b56bcfbSArnaldo Carvalho de Melo 	evlist->enabled = false;
3404152ab37SArnaldo Carvalho de Melo }
3414152ab37SArnaldo Carvalho de Melo 
342764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist)
343764e16a3SDavid Ahern {
344764e16a3SDavid Ahern 	int cpu, thread;
345764e16a3SDavid Ahern 	struct perf_evsel *pos;
346b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
347bf8e8f4bSAdrian Hunter 	int nr_threads;
348764e16a3SDavid Ahern 
349b3a319d5SNamhyung Kim 	for (cpu = 0; cpu < nr_cpus; cpu++) {
3500050f7aaSArnaldo Carvalho de Melo 		evlist__for_each(evlist, pos) {
351395c3070SAdrian Hunter 			if (!perf_evsel__is_group_leader(pos) || !pos->fd)
3523fe4430dSJiri Olsa 				continue;
353bf8e8f4bSAdrian Hunter 			nr_threads = perf_evlist__nr_threads(evlist, pos);
354b3a319d5SNamhyung Kim 			for (thread = 0; thread < nr_threads; thread++)
35555da8005SNamhyung Kim 				ioctl(FD(pos, cpu, thread),
35655da8005SNamhyung Kim 				      PERF_EVENT_IOC_ENABLE, 0);
357764e16a3SDavid Ahern 		}
358764e16a3SDavid Ahern 	}
3592b56bcfbSArnaldo Carvalho de Melo 
3602b56bcfbSArnaldo Carvalho de Melo 	evlist->enabled = true;
3612b56bcfbSArnaldo Carvalho de Melo }
3622b56bcfbSArnaldo Carvalho de Melo 
3632b56bcfbSArnaldo Carvalho de Melo void perf_evlist__toggle_enable(struct perf_evlist *evlist)
3642b56bcfbSArnaldo Carvalho de Melo {
3652b56bcfbSArnaldo Carvalho de Melo 	(evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
366764e16a3SDavid Ahern }
367764e16a3SDavid Ahern 
368395c3070SAdrian Hunter int perf_evlist__disable_event(struct perf_evlist *evlist,
369395c3070SAdrian Hunter 			       struct perf_evsel *evsel)
370395c3070SAdrian Hunter {
371395c3070SAdrian Hunter 	int cpu, thread, err;
372bf8e8f4bSAdrian Hunter 	int nr_cpus = cpu_map__nr(evlist->cpus);
373bf8e8f4bSAdrian Hunter 	int nr_threads = perf_evlist__nr_threads(evlist, evsel);
374395c3070SAdrian Hunter 
375395c3070SAdrian Hunter 	if (!evsel->fd)
376395c3070SAdrian Hunter 		return 0;
377395c3070SAdrian Hunter 
378bf8e8f4bSAdrian Hunter 	for (cpu = 0; cpu < nr_cpus; cpu++) {
379bf8e8f4bSAdrian Hunter 		for (thread = 0; thread < nr_threads; thread++) {
380395c3070SAdrian Hunter 			err = ioctl(FD(evsel, cpu, thread),
381395c3070SAdrian Hunter 				    PERF_EVENT_IOC_DISABLE, 0);
382395c3070SAdrian Hunter 			if (err)
383395c3070SAdrian Hunter 				return err;
384395c3070SAdrian Hunter 		}
385395c3070SAdrian Hunter 	}
386395c3070SAdrian Hunter 	return 0;
387395c3070SAdrian Hunter }
388395c3070SAdrian Hunter 
389395c3070SAdrian Hunter int perf_evlist__enable_event(struct perf_evlist *evlist,
390395c3070SAdrian Hunter 			      struct perf_evsel *evsel)
391395c3070SAdrian Hunter {
392395c3070SAdrian Hunter 	int cpu, thread, err;
393bf8e8f4bSAdrian Hunter 	int nr_cpus = cpu_map__nr(evlist->cpus);
394bf8e8f4bSAdrian Hunter 	int nr_threads = perf_evlist__nr_threads(evlist, evsel);
395395c3070SAdrian Hunter 
396395c3070SAdrian Hunter 	if (!evsel->fd)
397395c3070SAdrian Hunter 		return -EINVAL;
398395c3070SAdrian Hunter 
399bf8e8f4bSAdrian Hunter 	for (cpu = 0; cpu < nr_cpus; cpu++) {
400bf8e8f4bSAdrian Hunter 		for (thread = 0; thread < nr_threads; thread++) {
401395c3070SAdrian Hunter 			err = ioctl(FD(evsel, cpu, thread),
402395c3070SAdrian Hunter 				    PERF_EVENT_IOC_ENABLE, 0);
403395c3070SAdrian Hunter 			if (err)
404395c3070SAdrian Hunter 				return err;
405395c3070SAdrian Hunter 		}
406395c3070SAdrian Hunter 	}
407395c3070SAdrian Hunter 	return 0;
408395c3070SAdrian Hunter }
409395c3070SAdrian Hunter 
4101c65056cSAdrian Hunter static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
4111c65056cSAdrian Hunter 					 struct perf_evsel *evsel, int cpu)
4121c65056cSAdrian Hunter {
4131c65056cSAdrian Hunter 	int thread, err;
4141c65056cSAdrian Hunter 	int nr_threads = perf_evlist__nr_threads(evlist, evsel);
4151c65056cSAdrian Hunter 
4161c65056cSAdrian Hunter 	if (!evsel->fd)
4171c65056cSAdrian Hunter 		return -EINVAL;
4181c65056cSAdrian Hunter 
4191c65056cSAdrian Hunter 	for (thread = 0; thread < nr_threads; thread++) {
4201c65056cSAdrian Hunter 		err = ioctl(FD(evsel, cpu, thread),
4211c65056cSAdrian Hunter 			    PERF_EVENT_IOC_ENABLE, 0);
4221c65056cSAdrian Hunter 		if (err)
4231c65056cSAdrian Hunter 			return err;
4241c65056cSAdrian Hunter 	}
4251c65056cSAdrian Hunter 	return 0;
4261c65056cSAdrian Hunter }
4271c65056cSAdrian Hunter 
4281c65056cSAdrian Hunter static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
4291c65056cSAdrian Hunter 					    struct perf_evsel *evsel,
4301c65056cSAdrian Hunter 					    int thread)
4311c65056cSAdrian Hunter {
4321c65056cSAdrian Hunter 	int cpu, err;
4331c65056cSAdrian Hunter 	int nr_cpus = cpu_map__nr(evlist->cpus);
4341c65056cSAdrian Hunter 
4351c65056cSAdrian Hunter 	if (!evsel->fd)
4361c65056cSAdrian Hunter 		return -EINVAL;
4371c65056cSAdrian Hunter 
4381c65056cSAdrian Hunter 	for (cpu = 0; cpu < nr_cpus; cpu++) {
4391c65056cSAdrian Hunter 		err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
4401c65056cSAdrian Hunter 		if (err)
4411c65056cSAdrian Hunter 			return err;
4421c65056cSAdrian Hunter 	}
4431c65056cSAdrian Hunter 	return 0;
4441c65056cSAdrian Hunter }
4451c65056cSAdrian Hunter 
4461c65056cSAdrian Hunter int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
4471c65056cSAdrian Hunter 				  struct perf_evsel *evsel, int idx)
4481c65056cSAdrian Hunter {
4491c65056cSAdrian Hunter 	bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
4501c65056cSAdrian Hunter 
4511c65056cSAdrian Hunter 	if (per_cpu_mmaps)
4521c65056cSAdrian Hunter 		return perf_evlist__enable_event_cpu(evlist, evsel, idx);
4531c65056cSAdrian Hunter 	else
4541c65056cSAdrian Hunter 		return perf_evlist__enable_event_thread(evlist, evsel, idx);
4551c65056cSAdrian Hunter }
4561c65056cSAdrian Hunter 
457ad6765ddSArnaldo Carvalho de Melo int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
4585c581041SArnaldo Carvalho de Melo {
459b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
460b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
461bf8e8f4bSAdrian Hunter 	int nfds = 0;
462bf8e8f4bSAdrian Hunter 	struct perf_evsel *evsel;
463bf8e8f4bSAdrian Hunter 
464cba9b847SArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
465bf8e8f4bSAdrian Hunter 		if (evsel->system_wide)
466bf8e8f4bSAdrian Hunter 			nfds += nr_cpus;
467bf8e8f4bSAdrian Hunter 		else
468bf8e8f4bSAdrian Hunter 			nfds += nr_cpus * nr_threads;
469bf8e8f4bSAdrian Hunter 	}
470bf8e8f4bSAdrian Hunter 
4711b85337dSArnaldo Carvalho de Melo 	if (fdarray__available_entries(&evlist->pollfd) < nfds &&
4721b85337dSArnaldo Carvalho de Melo 	    fdarray__grow(&evlist->pollfd, nfds) < 0)
473ad6765ddSArnaldo Carvalho de Melo 		return -ENOMEM;
474ad6765ddSArnaldo Carvalho de Melo 
475ad6765ddSArnaldo Carvalho de Melo 	return 0;
4765c581041SArnaldo Carvalho de Melo }
47770082dd9SArnaldo Carvalho de Melo 
478e4b356b5SArnaldo Carvalho de Melo static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
479e4b356b5SArnaldo Carvalho de Melo {
480e4b356b5SArnaldo Carvalho de Melo 	int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
481e4b356b5SArnaldo Carvalho de Melo 	/*
482e4b356b5SArnaldo Carvalho de Melo 	 * Save the idx so that when we filter out fds POLLHUP'ed we can
483e4b356b5SArnaldo Carvalho de Melo 	 * close the associated evlist->mmap[] entry.
484e4b356b5SArnaldo Carvalho de Melo 	 */
485e4b356b5SArnaldo Carvalho de Melo 	if (pos >= 0) {
486e4b356b5SArnaldo Carvalho de Melo 		evlist->pollfd.priv[pos].idx = idx;
487e4b356b5SArnaldo Carvalho de Melo 
488e4b356b5SArnaldo Carvalho de Melo 		fcntl(fd, F_SETFL, O_NONBLOCK);
489e4b356b5SArnaldo Carvalho de Melo 	}
490e4b356b5SArnaldo Carvalho de Melo 
491e4b356b5SArnaldo Carvalho de Melo 	return pos;
492e4b356b5SArnaldo Carvalho de Melo }
493e4b356b5SArnaldo Carvalho de Melo 
494ad6765ddSArnaldo Carvalho de Melo int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
49570082dd9SArnaldo Carvalho de Melo {
496e4b356b5SArnaldo Carvalho de Melo 	return __perf_evlist__add_pollfd(evlist, fd, -1);
497e4b356b5SArnaldo Carvalho de Melo }
4981b85337dSArnaldo Carvalho de Melo 
499e4b356b5SArnaldo Carvalho de Melo static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
500e4b356b5SArnaldo Carvalho de Melo {
501e4b356b5SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
502e4b356b5SArnaldo Carvalho de Melo 
503e4b356b5SArnaldo Carvalho de Melo 	perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
50470082dd9SArnaldo Carvalho de Melo }
50570db7533SArnaldo Carvalho de Melo 
5061ddec7f0SArnaldo Carvalho de Melo int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
5071ddec7f0SArnaldo Carvalho de Melo {
508e4b356b5SArnaldo Carvalho de Melo 	return fdarray__filter(&evlist->pollfd, revents_and_mask,
509e4b356b5SArnaldo Carvalho de Melo 			       perf_evlist__munmap_filtered);
5101ddec7f0SArnaldo Carvalho de Melo }
5111ddec7f0SArnaldo Carvalho de Melo 
512f66a889dSArnaldo Carvalho de Melo int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
513f66a889dSArnaldo Carvalho de Melo {
5141b85337dSArnaldo Carvalho de Melo 	return fdarray__poll(&evlist->pollfd, timeout);
515f66a889dSArnaldo Carvalho de Melo }
516f66a889dSArnaldo Carvalho de Melo 
517a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist,
518a91e5431SArnaldo Carvalho de Melo 				 struct perf_evsel *evsel,
5193d3b5e95SArnaldo Carvalho de Melo 				 int cpu, int thread, u64 id)
5203d3b5e95SArnaldo Carvalho de Melo {
5213d3b5e95SArnaldo Carvalho de Melo 	int hash;
5223d3b5e95SArnaldo Carvalho de Melo 	struct perf_sample_id *sid = SID(evsel, cpu, thread);
5233d3b5e95SArnaldo Carvalho de Melo 
5243d3b5e95SArnaldo Carvalho de Melo 	sid->id = id;
5253d3b5e95SArnaldo Carvalho de Melo 	sid->evsel = evsel;
5263d3b5e95SArnaldo Carvalho de Melo 	hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
5273d3b5e95SArnaldo Carvalho de Melo 	hlist_add_head(&sid->node, &evlist->heads[hash]);
5283d3b5e95SArnaldo Carvalho de Melo }
5293d3b5e95SArnaldo Carvalho de Melo 
530a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
531a91e5431SArnaldo Carvalho de Melo 			 int cpu, int thread, u64 id)
532a91e5431SArnaldo Carvalho de Melo {
533a91e5431SArnaldo Carvalho de Melo 	perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
534a91e5431SArnaldo Carvalho de Melo 	evsel->id[evsel->ids++] = id;
535a91e5431SArnaldo Carvalho de Melo }
536a91e5431SArnaldo Carvalho de Melo 
537a91e5431SArnaldo Carvalho de Melo static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
5383d3b5e95SArnaldo Carvalho de Melo 				  struct perf_evsel *evsel,
539f8a95309SArnaldo Carvalho de Melo 				  int cpu, int thread, int fd)
540f8a95309SArnaldo Carvalho de Melo {
541f8a95309SArnaldo Carvalho de Melo 	u64 read_data[4] = { 0, };
5423d3b5e95SArnaldo Carvalho de Melo 	int id_idx = 1; /* The first entry is the counter value */
543e2b5abe0SJiri Olsa 	u64 id;
544e2b5abe0SJiri Olsa 	int ret;
545e2b5abe0SJiri Olsa 
546e2b5abe0SJiri Olsa 	ret = ioctl(fd, PERF_EVENT_IOC_ID, &id);
547e2b5abe0SJiri Olsa 	if (!ret)
548e2b5abe0SJiri Olsa 		goto add;
549e2b5abe0SJiri Olsa 
550e2b5abe0SJiri Olsa 	if (errno != ENOTTY)
551e2b5abe0SJiri Olsa 		return -1;
552e2b5abe0SJiri Olsa 
553e2b5abe0SJiri Olsa 	/* Legacy way to get event id.. All hail to old kernels! */
554f8a95309SArnaldo Carvalho de Melo 
555c4861afeSJiri Olsa 	/*
556c4861afeSJiri Olsa 	 * This way does not work with group format read, so bail
557c4861afeSJiri Olsa 	 * out in that case.
558c4861afeSJiri Olsa 	 */
559c4861afeSJiri Olsa 	if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP)
560c4861afeSJiri Olsa 		return -1;
561c4861afeSJiri Olsa 
562f8a95309SArnaldo Carvalho de Melo 	if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
563f8a95309SArnaldo Carvalho de Melo 	    read(fd, &read_data, sizeof(read_data)) == -1)
564f8a95309SArnaldo Carvalho de Melo 		return -1;
565f8a95309SArnaldo Carvalho de Melo 
566f8a95309SArnaldo Carvalho de Melo 	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
567f8a95309SArnaldo Carvalho de Melo 		++id_idx;
568f8a95309SArnaldo Carvalho de Melo 	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
569f8a95309SArnaldo Carvalho de Melo 		++id_idx;
570f8a95309SArnaldo Carvalho de Melo 
571e2b5abe0SJiri Olsa 	id = read_data[id_idx];
572e2b5abe0SJiri Olsa 
573e2b5abe0SJiri Olsa  add:
574e2b5abe0SJiri Olsa 	perf_evlist__id_add(evlist, evsel, cpu, thread, id);
575f8a95309SArnaldo Carvalho de Melo 	return 0;
576f8a95309SArnaldo Carvalho de Melo }
577f8a95309SArnaldo Carvalho de Melo 
5783c659eedSAdrian Hunter static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
5793c659eedSAdrian Hunter 				     struct perf_evsel *evsel, int idx, int cpu,
5803c659eedSAdrian Hunter 				     int thread)
5813c659eedSAdrian Hunter {
5823c659eedSAdrian Hunter 	struct perf_sample_id *sid = SID(evsel, cpu, thread);
5833c659eedSAdrian Hunter 	sid->idx = idx;
5843c659eedSAdrian Hunter 	if (evlist->cpus && cpu >= 0)
5853c659eedSAdrian Hunter 		sid->cpu = evlist->cpus->map[cpu];
5863c659eedSAdrian Hunter 	else
5873c659eedSAdrian Hunter 		sid->cpu = -1;
5883c659eedSAdrian Hunter 	if (!evsel->system_wide && evlist->threads && thread >= 0)
589e13798c7SJiri Olsa 		sid->tid = thread_map__pid(evlist->threads, thread);
5903c659eedSAdrian Hunter 	else
5913c659eedSAdrian Hunter 		sid->tid = -1;
5923c659eedSAdrian Hunter }
5933c659eedSAdrian Hunter 
594932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
59570db7533SArnaldo Carvalho de Melo {
59670db7533SArnaldo Carvalho de Melo 	struct hlist_head *head;
59770db7533SArnaldo Carvalho de Melo 	struct perf_sample_id *sid;
59870db7533SArnaldo Carvalho de Melo 	int hash;
59970db7533SArnaldo Carvalho de Melo 
60070db7533SArnaldo Carvalho de Melo 	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
60170db7533SArnaldo Carvalho de Melo 	head = &evlist->heads[hash];
60270db7533SArnaldo Carvalho de Melo 
603b67bfe0dSSasha Levin 	hlist_for_each_entry(sid, head, node)
60470db7533SArnaldo Carvalho de Melo 		if (sid->id == id)
605932a3594SJiri Olsa 			return sid;
606932a3594SJiri Olsa 
607932a3594SJiri Olsa 	return NULL;
608932a3594SJiri Olsa }
609932a3594SJiri Olsa 
610932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
611932a3594SJiri Olsa {
612932a3594SJiri Olsa 	struct perf_sample_id *sid;
613932a3594SJiri Olsa 
61405169df5SAdrian Hunter 	if (evlist->nr_entries == 1 || !id)
615932a3594SJiri Olsa 		return perf_evlist__first(evlist);
616932a3594SJiri Olsa 
617932a3594SJiri Olsa 	sid = perf_evlist__id2sid(evlist, id);
618932a3594SJiri Olsa 	if (sid)
61970db7533SArnaldo Carvalho de Melo 		return sid->evsel;
62030e68bccSNamhyung Kim 
62130e68bccSNamhyung Kim 	if (!perf_evlist__sample_id_all(evlist))
6220c21f736SArnaldo Carvalho de Melo 		return perf_evlist__first(evlist);
62330e68bccSNamhyung Kim 
62470db7533SArnaldo Carvalho de Melo 	return NULL;
62570db7533SArnaldo Carvalho de Melo }
62604391debSArnaldo Carvalho de Melo 
627dddcf6abSAdrian Hunter struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
628dddcf6abSAdrian Hunter 						u64 id)
629dddcf6abSAdrian Hunter {
630dddcf6abSAdrian Hunter 	struct perf_sample_id *sid;
631dddcf6abSAdrian Hunter 
632dddcf6abSAdrian Hunter 	if (!id)
633dddcf6abSAdrian Hunter 		return NULL;
634dddcf6abSAdrian Hunter 
635dddcf6abSAdrian Hunter 	sid = perf_evlist__id2sid(evlist, id);
636dddcf6abSAdrian Hunter 	if (sid)
637dddcf6abSAdrian Hunter 		return sid->evsel;
638dddcf6abSAdrian Hunter 
639dddcf6abSAdrian Hunter 	return NULL;
640dddcf6abSAdrian Hunter }
641dddcf6abSAdrian Hunter 
64275562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist,
64375562573SAdrian Hunter 				 union perf_event *event, u64 *id)
64475562573SAdrian Hunter {
64575562573SAdrian Hunter 	const u64 *array = event->sample.array;
64675562573SAdrian Hunter 	ssize_t n;
64775562573SAdrian Hunter 
64875562573SAdrian Hunter 	n = (event->header.size - sizeof(event->header)) >> 3;
64975562573SAdrian Hunter 
65075562573SAdrian Hunter 	if (event->header.type == PERF_RECORD_SAMPLE) {
65175562573SAdrian Hunter 		if (evlist->id_pos >= n)
65275562573SAdrian Hunter 			return -1;
65375562573SAdrian Hunter 		*id = array[evlist->id_pos];
65475562573SAdrian Hunter 	} else {
65575562573SAdrian Hunter 		if (evlist->is_pos > n)
65675562573SAdrian Hunter 			return -1;
65775562573SAdrian Hunter 		n -= evlist->is_pos;
65875562573SAdrian Hunter 		*id = array[n];
65975562573SAdrian Hunter 	}
66075562573SAdrian Hunter 	return 0;
66175562573SAdrian Hunter }
66275562573SAdrian Hunter 
66375562573SAdrian Hunter static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
66475562573SAdrian Hunter 						   union perf_event *event)
66575562573SAdrian Hunter {
66698be6966SAdrian Hunter 	struct perf_evsel *first = perf_evlist__first(evlist);
66775562573SAdrian Hunter 	struct hlist_head *head;
66875562573SAdrian Hunter 	struct perf_sample_id *sid;
66975562573SAdrian Hunter 	int hash;
67075562573SAdrian Hunter 	u64 id;
67175562573SAdrian Hunter 
67275562573SAdrian Hunter 	if (evlist->nr_entries == 1)
67398be6966SAdrian Hunter 		return first;
67498be6966SAdrian Hunter 
67598be6966SAdrian Hunter 	if (!first->attr.sample_id_all &&
67698be6966SAdrian Hunter 	    event->header.type != PERF_RECORD_SAMPLE)
67798be6966SAdrian Hunter 		return first;
67875562573SAdrian Hunter 
67975562573SAdrian Hunter 	if (perf_evlist__event2id(evlist, event, &id))
68075562573SAdrian Hunter 		return NULL;
68175562573SAdrian Hunter 
68275562573SAdrian Hunter 	/* Synthesized events have an id of zero */
68375562573SAdrian Hunter 	if (!id)
68498be6966SAdrian Hunter 		return first;
68575562573SAdrian Hunter 
68675562573SAdrian Hunter 	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
68775562573SAdrian Hunter 	head = &evlist->heads[hash];
68875562573SAdrian Hunter 
68975562573SAdrian Hunter 	hlist_for_each_entry(sid, head, node) {
69075562573SAdrian Hunter 		if (sid->id == id)
69175562573SAdrian Hunter 			return sid->evsel;
69275562573SAdrian Hunter 	}
69375562573SAdrian Hunter 	return NULL;
69475562573SAdrian Hunter }
69575562573SAdrian Hunter 
696aece948fSArnaldo Carvalho de Melo union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
69704391debSArnaldo Carvalho de Melo {
698aece948fSArnaldo Carvalho de Melo 	struct perf_mmap *md = &evlist->mmap[idx];
6997951722dSSukadev Bhattiprolu 	u64 head;
7007b8283b5SDavid Ahern 	u64 old = md->prev;
70104391debSArnaldo Carvalho de Melo 	unsigned char *data = md->base + page_size;
7028115d60cSArnaldo Carvalho de Melo 	union perf_event *event = NULL;
70304391debSArnaldo Carvalho de Melo 
7047951722dSSukadev Bhattiprolu 	/*
7057951722dSSukadev Bhattiprolu 	 * Check if event was unmapped due to a POLLHUP/POLLERR.
7067951722dSSukadev Bhattiprolu 	 */
7077951722dSSukadev Bhattiprolu 	if (!atomic_read(&md->refcnt))
7087951722dSSukadev Bhattiprolu 		return NULL;
7097951722dSSukadev Bhattiprolu 
7107951722dSSukadev Bhattiprolu 	head = perf_mmap__read_head(md);
7117bb41152SArnaldo Carvalho de Melo 	if (evlist->overwrite) {
71204391debSArnaldo Carvalho de Melo 		/*
71304391debSArnaldo Carvalho de Melo 		 * If we're further behind than half the buffer, there's a chance
71404391debSArnaldo Carvalho de Melo 		 * the writer will bite our tail and mess up the samples under us.
71504391debSArnaldo Carvalho de Melo 		 *
71604391debSArnaldo Carvalho de Melo 		 * If we somehow ended up ahead of the head, we got messed up.
71704391debSArnaldo Carvalho de Melo 		 *
71804391debSArnaldo Carvalho de Melo 		 * In either case, truncate and restart at head.
71904391debSArnaldo Carvalho de Melo 		 */
7207bb41152SArnaldo Carvalho de Melo 		int diff = head - old;
72104391debSArnaldo Carvalho de Melo 		if (diff > md->mask / 2 || diff < 0) {
72204391debSArnaldo Carvalho de Melo 			fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
72304391debSArnaldo Carvalho de Melo 
72404391debSArnaldo Carvalho de Melo 			/*
72504391debSArnaldo Carvalho de Melo 			 * head points to a known good entry, start there.
72604391debSArnaldo Carvalho de Melo 			 */
72704391debSArnaldo Carvalho de Melo 			old = head;
72804391debSArnaldo Carvalho de Melo 		}
7297bb41152SArnaldo Carvalho de Melo 	}
73004391debSArnaldo Carvalho de Melo 
73104391debSArnaldo Carvalho de Melo 	if (old != head) {
73204391debSArnaldo Carvalho de Melo 		size_t size;
73304391debSArnaldo Carvalho de Melo 
7348115d60cSArnaldo Carvalho de Melo 		event = (union perf_event *)&data[old & md->mask];
73504391debSArnaldo Carvalho de Melo 		size = event->header.size;
73604391debSArnaldo Carvalho de Melo 
73704391debSArnaldo Carvalho de Melo 		/*
73804391debSArnaldo Carvalho de Melo 		 * Event straddles the mmap boundary -- header should always
73904391debSArnaldo Carvalho de Melo 		 * be inside due to u64 alignment of output.
74004391debSArnaldo Carvalho de Melo 		 */
74104391debSArnaldo Carvalho de Melo 		if ((old & md->mask) + size != ((old + size) & md->mask)) {
74204391debSArnaldo Carvalho de Melo 			unsigned int offset = old;
74304391debSArnaldo Carvalho de Melo 			unsigned int len = min(sizeof(*event), size), cpy;
744a65cb4b9SJiri Olsa 			void *dst = md->event_copy;
74504391debSArnaldo Carvalho de Melo 
74604391debSArnaldo Carvalho de Melo 			do {
74704391debSArnaldo Carvalho de Melo 				cpy = min(md->mask + 1 - (offset & md->mask), len);
74804391debSArnaldo Carvalho de Melo 				memcpy(dst, &data[offset & md->mask], cpy);
74904391debSArnaldo Carvalho de Melo 				offset += cpy;
75004391debSArnaldo Carvalho de Melo 				dst += cpy;
75104391debSArnaldo Carvalho de Melo 				len -= cpy;
75204391debSArnaldo Carvalho de Melo 			} while (len);
75304391debSArnaldo Carvalho de Melo 
754a65cb4b9SJiri Olsa 			event = (union perf_event *) md->event_copy;
75504391debSArnaldo Carvalho de Melo 		}
75604391debSArnaldo Carvalho de Melo 
75704391debSArnaldo Carvalho de Melo 		old += size;
75804391debSArnaldo Carvalho de Melo 	}
75904391debSArnaldo Carvalho de Melo 
76004391debSArnaldo Carvalho de Melo 	md->prev = old;
7617bb41152SArnaldo Carvalho de Melo 
76204391debSArnaldo Carvalho de Melo 	return event;
76304391debSArnaldo Carvalho de Melo }
764f8a95309SArnaldo Carvalho de Melo 
76582396986SArnaldo Carvalho de Melo static bool perf_mmap__empty(struct perf_mmap *md)
76682396986SArnaldo Carvalho de Melo {
767b72e74d1SAdrian Hunter 	return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
76882396986SArnaldo Carvalho de Melo }
76982396986SArnaldo Carvalho de Melo 
77082396986SArnaldo Carvalho de Melo static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
77182396986SArnaldo Carvalho de Melo {
7727143849aSArnaldo Carvalho de Melo 	atomic_inc(&evlist->mmap[idx].refcnt);
77382396986SArnaldo Carvalho de Melo }
77482396986SArnaldo Carvalho de Melo 
77582396986SArnaldo Carvalho de Melo static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
77682396986SArnaldo Carvalho de Melo {
7777143849aSArnaldo Carvalho de Melo 	BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0);
77882396986SArnaldo Carvalho de Melo 
7797143849aSArnaldo Carvalho de Melo 	if (atomic_dec_and_test(&evlist->mmap[idx].refcnt))
78082396986SArnaldo Carvalho de Melo 		__perf_evlist__munmap(evlist, idx);
78182396986SArnaldo Carvalho de Melo }
78282396986SArnaldo Carvalho de Melo 
7838e50d384SZhouyi Zhou void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
7848e50d384SZhouyi Zhou {
7858e50d384SZhouyi Zhou 	struct perf_mmap *md = &evlist->mmap[idx];
78682396986SArnaldo Carvalho de Melo 
78782396986SArnaldo Carvalho de Melo 	if (!evlist->overwrite) {
7887b8283b5SDavid Ahern 		u64 old = md->prev;
7898e50d384SZhouyi Zhou 
7908e50d384SZhouyi Zhou 		perf_mmap__write_tail(md, old);
7918e50d384SZhouyi Zhou 	}
79282396986SArnaldo Carvalho de Melo 
7937143849aSArnaldo Carvalho de Melo 	if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
79482396986SArnaldo Carvalho de Melo 		perf_evlist__mmap_put(evlist, idx);
7958e50d384SZhouyi Zhou }
7968e50d384SZhouyi Zhou 
797718c602dSAdrian Hunter int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
798718c602dSAdrian Hunter 			       struct auxtrace_mmap_params *mp __maybe_unused,
799718c602dSAdrian Hunter 			       void *userpg __maybe_unused,
800718c602dSAdrian Hunter 			       int fd __maybe_unused)
801718c602dSAdrian Hunter {
802718c602dSAdrian Hunter 	return 0;
803718c602dSAdrian Hunter }
804718c602dSAdrian Hunter 
805718c602dSAdrian Hunter void __weak auxtrace_mmap__munmap(struct auxtrace_mmap *mm __maybe_unused)
806718c602dSAdrian Hunter {
807718c602dSAdrian Hunter }
808718c602dSAdrian Hunter 
809718c602dSAdrian Hunter void __weak auxtrace_mmap_params__init(
810718c602dSAdrian Hunter 			struct auxtrace_mmap_params *mp __maybe_unused,
811718c602dSAdrian Hunter 			off_t auxtrace_offset __maybe_unused,
812718c602dSAdrian Hunter 			unsigned int auxtrace_pages __maybe_unused,
813718c602dSAdrian Hunter 			bool auxtrace_overwrite __maybe_unused)
814718c602dSAdrian Hunter {
815718c602dSAdrian Hunter }
816718c602dSAdrian Hunter 
817718c602dSAdrian Hunter void __weak auxtrace_mmap_params__set_idx(
818718c602dSAdrian Hunter 			struct auxtrace_mmap_params *mp __maybe_unused,
819718c602dSAdrian Hunter 			struct perf_evlist *evlist __maybe_unused,
820718c602dSAdrian Hunter 			int idx __maybe_unused,
821718c602dSAdrian Hunter 			bool per_cpu __maybe_unused)
822718c602dSAdrian Hunter {
823718c602dSAdrian Hunter }
824718c602dSAdrian Hunter 
82593edcbd9SAdrian Hunter static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
82693edcbd9SAdrian Hunter {
82793edcbd9SAdrian Hunter 	if (evlist->mmap[idx].base != NULL) {
82893edcbd9SAdrian Hunter 		munmap(evlist->mmap[idx].base, evlist->mmap_len);
82993edcbd9SAdrian Hunter 		evlist->mmap[idx].base = NULL;
8307143849aSArnaldo Carvalho de Melo 		atomic_set(&evlist->mmap[idx].refcnt, 0);
83193edcbd9SAdrian Hunter 	}
832718c602dSAdrian Hunter 	auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
83393edcbd9SAdrian Hunter }
83493edcbd9SAdrian Hunter 
8357e2ed097SArnaldo Carvalho de Melo void perf_evlist__munmap(struct perf_evlist *evlist)
836f8a95309SArnaldo Carvalho de Melo {
837aece948fSArnaldo Carvalho de Melo 	int i;
838f8a95309SArnaldo Carvalho de Melo 
839983874d1SArnaldo Carvalho de Melo 	if (evlist->mmap == NULL)
840983874d1SArnaldo Carvalho de Melo 		return;
841983874d1SArnaldo Carvalho de Melo 
84293edcbd9SAdrian Hunter 	for (i = 0; i < evlist->nr_mmaps; i++)
84393edcbd9SAdrian Hunter 		__perf_evlist__munmap(evlist, i);
844aece948fSArnaldo Carvalho de Melo 
84504662523SArnaldo Carvalho de Melo 	zfree(&evlist->mmap);
846f8a95309SArnaldo Carvalho de Melo }
847f8a95309SArnaldo Carvalho de Melo 
848806fb630SArnaldo Carvalho de Melo static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
849f8a95309SArnaldo Carvalho de Melo {
850a14bb7a6SArnaldo Carvalho de Melo 	evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
851ec1e7e43SSukadev Bhattiprolu 	if (cpu_map__empty(evlist->cpus))
852b3a319d5SNamhyung Kim 		evlist->nr_mmaps = thread_map__nr(evlist->threads);
853aece948fSArnaldo Carvalho de Melo 	evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
854f8a95309SArnaldo Carvalho de Melo 	return evlist->mmap != NULL ? 0 : -ENOMEM;
855f8a95309SArnaldo Carvalho de Melo }
856f8a95309SArnaldo Carvalho de Melo 
857a8a8f3ebSAdrian Hunter struct mmap_params {
858a8a8f3ebSAdrian Hunter 	int prot;
859a8a8f3ebSAdrian Hunter 	int mask;
860718c602dSAdrian Hunter 	struct auxtrace_mmap_params auxtrace_mp;
861a8a8f3ebSAdrian Hunter };
862a8a8f3ebSAdrian Hunter 
863a8a8f3ebSAdrian Hunter static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
864a8a8f3ebSAdrian Hunter 			       struct mmap_params *mp, int fd)
865f8a95309SArnaldo Carvalho de Melo {
86682396986SArnaldo Carvalho de Melo 	/*
86782396986SArnaldo Carvalho de Melo 	 * The last one will be done at perf_evlist__mmap_consume(), so that we
86882396986SArnaldo Carvalho de Melo 	 * make sure we don't prevent tools from consuming every last event in
86982396986SArnaldo Carvalho de Melo 	 * the ring buffer.
87082396986SArnaldo Carvalho de Melo 	 *
87182396986SArnaldo Carvalho de Melo 	 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
87282396986SArnaldo Carvalho de Melo 	 * anymore, but the last events for it are still in the ring buffer,
87382396986SArnaldo Carvalho de Melo 	 * waiting to be consumed.
87482396986SArnaldo Carvalho de Melo 	 *
87582396986SArnaldo Carvalho de Melo 	 * Tools can chose to ignore this at their own discretion, but the
87682396986SArnaldo Carvalho de Melo 	 * evlist layer can't just drop it when filtering events in
87782396986SArnaldo Carvalho de Melo 	 * perf_evlist__filter_pollfd().
87882396986SArnaldo Carvalho de Melo 	 */
8797143849aSArnaldo Carvalho de Melo 	atomic_set(&evlist->mmap[idx].refcnt, 2);
880aece948fSArnaldo Carvalho de Melo 	evlist->mmap[idx].prev = 0;
881a8a8f3ebSAdrian Hunter 	evlist->mmap[idx].mask = mp->mask;
882a8a8f3ebSAdrian Hunter 	evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
883f8a95309SArnaldo Carvalho de Melo 				      MAP_SHARED, fd, 0);
884301b195dSNelson Elhage 	if (evlist->mmap[idx].base == MAP_FAILED) {
88502635965SAdrian Hunter 		pr_debug2("failed to mmap perf event ring buffer, error %d\n",
88602635965SAdrian Hunter 			  errno);
887301b195dSNelson Elhage 		evlist->mmap[idx].base = NULL;
888f8a95309SArnaldo Carvalho de Melo 		return -1;
889301b195dSNelson Elhage 	}
890ad6765ddSArnaldo Carvalho de Melo 
891718c602dSAdrian Hunter 	if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
892718c602dSAdrian Hunter 				&mp->auxtrace_mp, evlist->mmap[idx].base, fd))
893718c602dSAdrian Hunter 		return -1;
894718c602dSAdrian Hunter 
895f8a95309SArnaldo Carvalho de Melo 	return 0;
896f8a95309SArnaldo Carvalho de Melo }
897f8a95309SArnaldo Carvalho de Melo 
89804e21314SAdrian Hunter static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
899a8a8f3ebSAdrian Hunter 				       struct mmap_params *mp, int cpu,
900a8a8f3ebSAdrian Hunter 				       int thread, int *output)
901aece948fSArnaldo Carvalho de Melo {
902aece948fSArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
90304e21314SAdrian Hunter 
9040050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
905bf8e8f4bSAdrian Hunter 		int fd;
906bf8e8f4bSAdrian Hunter 
907bf8e8f4bSAdrian Hunter 		if (evsel->system_wide && thread)
908bf8e8f4bSAdrian Hunter 			continue;
909bf8e8f4bSAdrian Hunter 
910bf8e8f4bSAdrian Hunter 		fd = FD(evsel, cpu, thread);
91104e21314SAdrian Hunter 
91204e21314SAdrian Hunter 		if (*output == -1) {
91304e21314SAdrian Hunter 			*output = fd;
914a8a8f3ebSAdrian Hunter 			if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
91504e21314SAdrian Hunter 				return -1;
91604e21314SAdrian Hunter 		} else {
91704e21314SAdrian Hunter 			if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
91804e21314SAdrian Hunter 				return -1;
91982396986SArnaldo Carvalho de Melo 
92082396986SArnaldo Carvalho de Melo 			perf_evlist__mmap_get(evlist, idx);
92104e21314SAdrian Hunter 		}
92204e21314SAdrian Hunter 
923f90d194aSAdrian Hunter 		/*
924f90d194aSAdrian Hunter 		 * The system_wide flag causes a selected event to be opened
925f90d194aSAdrian Hunter 		 * always without a pid.  Consequently it will never get a
926f90d194aSAdrian Hunter 		 * POLLHUP, but it is used for tracking in combination with
927f90d194aSAdrian Hunter 		 * other events, so it should not need to be polled anyway.
928f90d194aSAdrian Hunter 		 * Therefore don't add it for polling.
929f90d194aSAdrian Hunter 		 */
930f90d194aSAdrian Hunter 		if (!evsel->system_wide &&
931f90d194aSAdrian Hunter 		    __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
93282396986SArnaldo Carvalho de Melo 			perf_evlist__mmap_put(evlist, idx);
933ad6765ddSArnaldo Carvalho de Melo 			return -1;
93482396986SArnaldo Carvalho de Melo 		}
935033fa713SArnaldo Carvalho de Melo 
9363c659eedSAdrian Hunter 		if (evsel->attr.read_format & PERF_FORMAT_ID) {
9373c659eedSAdrian Hunter 			if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
9383c659eedSAdrian Hunter 						   fd) < 0)
93904e21314SAdrian Hunter 				return -1;
9403c659eedSAdrian Hunter 			perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
9413c659eedSAdrian Hunter 						 thread);
9423c659eedSAdrian Hunter 		}
94304e21314SAdrian Hunter 	}
94404e21314SAdrian Hunter 
94504e21314SAdrian Hunter 	return 0;
94604e21314SAdrian Hunter }
94704e21314SAdrian Hunter 
948a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
949a8a8f3ebSAdrian Hunter 				     struct mmap_params *mp)
95004e21314SAdrian Hunter {
951aece948fSArnaldo Carvalho de Melo 	int cpu, thread;
952b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
953b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
954aece948fSArnaldo Carvalho de Melo 
955e3e1a54fSAdrian Hunter 	pr_debug2("perf event ring buffer mmapped per cpu\n");
956b3a319d5SNamhyung Kim 	for (cpu = 0; cpu < nr_cpus; cpu++) {
957aece948fSArnaldo Carvalho de Melo 		int output = -1;
958aece948fSArnaldo Carvalho de Melo 
959718c602dSAdrian Hunter 		auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
960718c602dSAdrian Hunter 					      true);
961718c602dSAdrian Hunter 
962b3a319d5SNamhyung Kim 		for (thread = 0; thread < nr_threads; thread++) {
963a8a8f3ebSAdrian Hunter 			if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
964a8a8f3ebSAdrian Hunter 							thread, &output))
965aece948fSArnaldo Carvalho de Melo 				goto out_unmap;
966aece948fSArnaldo Carvalho de Melo 		}
967aece948fSArnaldo Carvalho de Melo 	}
968aece948fSArnaldo Carvalho de Melo 
969aece948fSArnaldo Carvalho de Melo 	return 0;
970aece948fSArnaldo Carvalho de Melo 
971aece948fSArnaldo Carvalho de Melo out_unmap:
97293edcbd9SAdrian Hunter 	for (cpu = 0; cpu < nr_cpus; cpu++)
97393edcbd9SAdrian Hunter 		__perf_evlist__munmap(evlist, cpu);
974aece948fSArnaldo Carvalho de Melo 	return -1;
975aece948fSArnaldo Carvalho de Melo }
976aece948fSArnaldo Carvalho de Melo 
977a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
978a8a8f3ebSAdrian Hunter 					struct mmap_params *mp)
979aece948fSArnaldo Carvalho de Melo {
980aece948fSArnaldo Carvalho de Melo 	int thread;
981b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
982aece948fSArnaldo Carvalho de Melo 
983e3e1a54fSAdrian Hunter 	pr_debug2("perf event ring buffer mmapped per thread\n");
984b3a319d5SNamhyung Kim 	for (thread = 0; thread < nr_threads; thread++) {
985aece948fSArnaldo Carvalho de Melo 		int output = -1;
986aece948fSArnaldo Carvalho de Melo 
987718c602dSAdrian Hunter 		auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
988718c602dSAdrian Hunter 					      false);
989718c602dSAdrian Hunter 
990a8a8f3ebSAdrian Hunter 		if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
991a8a8f3ebSAdrian Hunter 						&output))
992aece948fSArnaldo Carvalho de Melo 			goto out_unmap;
993aece948fSArnaldo Carvalho de Melo 	}
994aece948fSArnaldo Carvalho de Melo 
995aece948fSArnaldo Carvalho de Melo 	return 0;
996aece948fSArnaldo Carvalho de Melo 
997aece948fSArnaldo Carvalho de Melo out_unmap:
99893edcbd9SAdrian Hunter 	for (thread = 0; thread < nr_threads; thread++)
99993edcbd9SAdrian Hunter 		__perf_evlist__munmap(evlist, thread);
1000aece948fSArnaldo Carvalho de Melo 	return -1;
1001aece948fSArnaldo Carvalho de Melo }
1002aece948fSArnaldo Carvalho de Melo 
1003994a1f78SJiri Olsa static size_t perf_evlist__mmap_size(unsigned long pages)
1004994a1f78SJiri Olsa {
10058185e881SArnaldo Carvalho de Melo 	if (pages == UINT_MAX) {
10068185e881SArnaldo Carvalho de Melo 		int max;
10078185e881SArnaldo Carvalho de Melo 
10088185e881SArnaldo Carvalho de Melo 		if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
10098185e881SArnaldo Carvalho de Melo 			/*
10108185e881SArnaldo Carvalho de Melo 			 * Pick a once upon a time good value, i.e. things look
10118185e881SArnaldo Carvalho de Melo 			 * strange since we can't read a sysctl value, but lets not
10128185e881SArnaldo Carvalho de Melo 			 * die yet...
10138185e881SArnaldo Carvalho de Melo 			 */
10148185e881SArnaldo Carvalho de Melo 			max = 512;
10158185e881SArnaldo Carvalho de Melo 		} else {
10168185e881SArnaldo Carvalho de Melo 			max -= (page_size / 1024);
10178185e881SArnaldo Carvalho de Melo 		}
10188185e881SArnaldo Carvalho de Melo 
10198185e881SArnaldo Carvalho de Melo 		pages = (max * 1024) / page_size;
10201be300f4SArnaldo Carvalho de Melo 		if (!is_power_of_2(pages))
10211be300f4SArnaldo Carvalho de Melo 			pages = rounddown_pow_of_two(pages);
10228185e881SArnaldo Carvalho de Melo 	} else if (!is_power_of_2(pages))
1023994a1f78SJiri Olsa 		return 0;
1024994a1f78SJiri Olsa 
1025994a1f78SJiri Olsa 	return (pages + 1) * page_size;
1026994a1f78SJiri Olsa }
1027994a1f78SJiri Olsa 
102833c2dcfdSDavid Ahern static long parse_pages_arg(const char *str, unsigned long min,
102933c2dcfdSDavid Ahern 			    unsigned long max)
1030994a1f78SJiri Olsa {
10312fbe4abeSAdrian Hunter 	unsigned long pages, val;
103227050f53SJiri Olsa 	static struct parse_tag tags[] = {
103327050f53SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
103427050f53SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
103527050f53SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
103627050f53SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
103727050f53SJiri Olsa 		{ .tag  = 0 },
103827050f53SJiri Olsa 	};
1039994a1f78SJiri Olsa 
10408973504bSDavid Ahern 	if (str == NULL)
104133c2dcfdSDavid Ahern 		return -EINVAL;
10428973504bSDavid Ahern 
104327050f53SJiri Olsa 	val = parse_tag_value(str, tags);
10442fbe4abeSAdrian Hunter 	if (val != (unsigned long) -1) {
104527050f53SJiri Olsa 		/* we got file size value */
104627050f53SJiri Olsa 		pages = PERF_ALIGN(val, page_size) / page_size;
104727050f53SJiri Olsa 	} else {
104827050f53SJiri Olsa 		/* we got pages count value */
104927050f53SJiri Olsa 		char *eptr;
1050994a1f78SJiri Olsa 		pages = strtoul(str, &eptr, 10);
105133c2dcfdSDavid Ahern 		if (*eptr != '\0')
105233c2dcfdSDavid Ahern 			return -EINVAL;
105327050f53SJiri Olsa 	}
1054994a1f78SJiri Olsa 
10552bcab6c1SAdrian Hunter 	if (pages == 0 && min == 0) {
105633c2dcfdSDavid Ahern 		/* leave number of pages at 0 */
10571dbfa938SAdrian Hunter 	} else if (!is_power_of_2(pages)) {
105833c2dcfdSDavid Ahern 		/* round pages up to next power of 2 */
105991529834SArnaldo Carvalho de Melo 		pages = roundup_pow_of_two(pages);
10601dbfa938SAdrian Hunter 		if (!pages)
10611dbfa938SAdrian Hunter 			return -EINVAL;
10629639837eSDavid Ahern 		pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
10639639837eSDavid Ahern 			pages * page_size, pages);
10642fbe4abeSAdrian Hunter 	}
10652fbe4abeSAdrian Hunter 
106633c2dcfdSDavid Ahern 	if (pages > max)
106733c2dcfdSDavid Ahern 		return -EINVAL;
106833c2dcfdSDavid Ahern 
106933c2dcfdSDavid Ahern 	return pages;
107033c2dcfdSDavid Ahern }
107133c2dcfdSDavid Ahern 
1072e9db1310SAdrian Hunter int __perf_evlist__parse_mmap_pages(unsigned int *mmap_pages, const char *str)
107333c2dcfdSDavid Ahern {
107433c2dcfdSDavid Ahern 	unsigned long max = UINT_MAX;
107533c2dcfdSDavid Ahern 	long pages;
107633c2dcfdSDavid Ahern 
1077f5ae9c42SAdrian Hunter 	if (max > SIZE_MAX / page_size)
107833c2dcfdSDavid Ahern 		max = SIZE_MAX / page_size;
107933c2dcfdSDavid Ahern 
108033c2dcfdSDavid Ahern 	pages = parse_pages_arg(str, 1, max);
108133c2dcfdSDavid Ahern 	if (pages < 0) {
108233c2dcfdSDavid Ahern 		pr_err("Invalid argument for --mmap_pages/-m\n");
1083994a1f78SJiri Olsa 		return -1;
1084994a1f78SJiri Olsa 	}
1085994a1f78SJiri Olsa 
1086994a1f78SJiri Olsa 	*mmap_pages = pages;
1087994a1f78SJiri Olsa 	return 0;
1088994a1f78SJiri Olsa }
1089994a1f78SJiri Olsa 
1090e9db1310SAdrian Hunter int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
1091e9db1310SAdrian Hunter 				  int unset __maybe_unused)
1092e9db1310SAdrian Hunter {
1093e9db1310SAdrian Hunter 	return __perf_evlist__parse_mmap_pages(opt->value, str);
1094e9db1310SAdrian Hunter }
1095e9db1310SAdrian Hunter 
1096c83fa7f2SAdrian Hunter /**
1097718c602dSAdrian Hunter  * perf_evlist__mmap_ex - Create mmaps to receive events.
1098c83fa7f2SAdrian Hunter  * @evlist: list of events
1099c83fa7f2SAdrian Hunter  * @pages: map length in pages
1100c83fa7f2SAdrian Hunter  * @overwrite: overwrite older events?
1101718c602dSAdrian Hunter  * @auxtrace_pages - auxtrace map length in pages
1102718c602dSAdrian Hunter  * @auxtrace_overwrite - overwrite older auxtrace data?
1103f8a95309SArnaldo Carvalho de Melo  *
1104c83fa7f2SAdrian Hunter  * If @overwrite is %false the user needs to signal event consumption using
1105c83fa7f2SAdrian Hunter  * perf_mmap__write_tail().  Using perf_evlist__mmap_read() does this
1106c83fa7f2SAdrian Hunter  * automatically.
1107f8a95309SArnaldo Carvalho de Melo  *
1108718c602dSAdrian Hunter  * Similarly, if @auxtrace_overwrite is %false the user needs to signal data
1109718c602dSAdrian Hunter  * consumption using auxtrace_mmap__write_tail().
1110718c602dSAdrian Hunter  *
1111c83fa7f2SAdrian Hunter  * Return: %0 on success, negative error code otherwise.
1112f8a95309SArnaldo Carvalho de Melo  */
1113718c602dSAdrian Hunter int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1114718c602dSAdrian Hunter 			 bool overwrite, unsigned int auxtrace_pages,
1115718c602dSAdrian Hunter 			 bool auxtrace_overwrite)
1116f8a95309SArnaldo Carvalho de Melo {
1117aece948fSArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
11187e2ed097SArnaldo Carvalho de Melo 	const struct cpu_map *cpus = evlist->cpus;
11197e2ed097SArnaldo Carvalho de Melo 	const struct thread_map *threads = evlist->threads;
1120a8a8f3ebSAdrian Hunter 	struct mmap_params mp = {
1121a8a8f3ebSAdrian Hunter 		.prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
1122a8a8f3ebSAdrian Hunter 	};
112350a682ceSArnaldo Carvalho de Melo 
11247e2ed097SArnaldo Carvalho de Melo 	if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
1125f8a95309SArnaldo Carvalho de Melo 		return -ENOMEM;
1126f8a95309SArnaldo Carvalho de Melo 
11271b85337dSArnaldo Carvalho de Melo 	if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
1128f8a95309SArnaldo Carvalho de Melo 		return -ENOMEM;
1129f8a95309SArnaldo Carvalho de Melo 
1130f8a95309SArnaldo Carvalho de Melo 	evlist->overwrite = overwrite;
1131994a1f78SJiri Olsa 	evlist->mmap_len = perf_evlist__mmap_size(pages);
11322af68ef5SAdrian Hunter 	pr_debug("mmap size %zuB\n", evlist->mmap_len);
1133a8a8f3ebSAdrian Hunter 	mp.mask = evlist->mmap_len - page_size - 1;
1134f8a95309SArnaldo Carvalho de Melo 
1135718c602dSAdrian Hunter 	auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
1136718c602dSAdrian Hunter 				   auxtrace_pages, auxtrace_overwrite);
1137718c602dSAdrian Hunter 
11380050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
1139f8a95309SArnaldo Carvalho de Melo 		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
1140a91e5431SArnaldo Carvalho de Melo 		    evsel->sample_id == NULL &&
1141a14bb7a6SArnaldo Carvalho de Melo 		    perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
1142f8a95309SArnaldo Carvalho de Melo 			return -ENOMEM;
1143f8a95309SArnaldo Carvalho de Melo 	}
1144f8a95309SArnaldo Carvalho de Melo 
1145ec1e7e43SSukadev Bhattiprolu 	if (cpu_map__empty(cpus))
1146a8a8f3ebSAdrian Hunter 		return perf_evlist__mmap_per_thread(evlist, &mp);
1147f8a95309SArnaldo Carvalho de Melo 
1148a8a8f3ebSAdrian Hunter 	return perf_evlist__mmap_per_cpu(evlist, &mp);
1149f8a95309SArnaldo Carvalho de Melo }
11507e2ed097SArnaldo Carvalho de Melo 
1151718c602dSAdrian Hunter int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1152718c602dSAdrian Hunter 		      bool overwrite)
1153718c602dSAdrian Hunter {
1154718c602dSAdrian Hunter 	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
1155718c602dSAdrian Hunter }
1156718c602dSAdrian Hunter 
1157602ad878SArnaldo Carvalho de Melo int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
11587e2ed097SArnaldo Carvalho de Melo {
115974bfd2b2SAdrian Hunter 	struct cpu_map *cpus;
116074bfd2b2SAdrian Hunter 	struct thread_map *threads;
11617e2ed097SArnaldo Carvalho de Melo 
116274bfd2b2SAdrian Hunter 	threads = thread_map__new_str(target->pid, target->tid, target->uid);
116374bfd2b2SAdrian Hunter 
116474bfd2b2SAdrian Hunter 	if (!threads)
11657e2ed097SArnaldo Carvalho de Melo 		return -1;
11667e2ed097SArnaldo Carvalho de Melo 
11679c105fbcSDongsheng Yang 	if (target__uses_dummy_map(target))
116874bfd2b2SAdrian Hunter 		cpus = cpu_map__dummy_new();
1169879d77d0SNamhyung Kim 	else
117074bfd2b2SAdrian Hunter 		cpus = cpu_map__new(target->cpu_list);
11717e2ed097SArnaldo Carvalho de Melo 
117274bfd2b2SAdrian Hunter 	if (!cpus)
11737e2ed097SArnaldo Carvalho de Melo 		goto out_delete_threads;
11747e2ed097SArnaldo Carvalho de Melo 
1175ec9a77a7SAdrian Hunter 	evlist->has_user_cpus = !!target->cpu_list;
1176ec9a77a7SAdrian Hunter 
117774bfd2b2SAdrian Hunter 	perf_evlist__set_maps(evlist, cpus, threads);
1178d5bc056eSAdrian Hunter 
1179d5bc056eSAdrian Hunter 	return 0;
11807e2ed097SArnaldo Carvalho de Melo 
11817e2ed097SArnaldo Carvalho de Melo out_delete_threads:
118274bfd2b2SAdrian Hunter 	thread_map__put(threads);
11837e2ed097SArnaldo Carvalho de Melo 	return -1;
11847e2ed097SArnaldo Carvalho de Melo }
11857e2ed097SArnaldo Carvalho de Melo 
1186d5bc056eSAdrian Hunter void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
11873de5cfb0SJiri Olsa 			   struct thread_map *threads)
11883de5cfb0SJiri Olsa {
1189934e0f20SAdrian Hunter 	/*
1190934e0f20SAdrian Hunter 	 * Allow for the possibility that one or another of the maps isn't being
1191934e0f20SAdrian Hunter 	 * changed i.e. don't put it.  Note we are assuming the maps that are
1192934e0f20SAdrian Hunter 	 * being applied are brand new and evlist is taking ownership of the
1193934e0f20SAdrian Hunter 	 * original reference count of 1.  If that is not the case it is up to
1194934e0f20SAdrian Hunter 	 * the caller to increase the reference count.
1195934e0f20SAdrian Hunter 	 */
1196934e0f20SAdrian Hunter 	if (cpus != evlist->cpus) {
11973de5cfb0SJiri Olsa 		cpu_map__put(evlist->cpus);
11983de5cfb0SJiri Olsa 		evlist->cpus = cpus;
1199934e0f20SAdrian Hunter 	}
12003de5cfb0SJiri Olsa 
1201934e0f20SAdrian Hunter 	if (threads != evlist->threads) {
12023de5cfb0SJiri Olsa 		thread_map__put(evlist->threads);
12033de5cfb0SJiri Olsa 		evlist->threads = threads;
1204934e0f20SAdrian Hunter 	}
12053de5cfb0SJiri Olsa 
1206ec9a77a7SAdrian Hunter 	perf_evlist__propagate_maps(evlist);
12073de5cfb0SJiri Olsa }
12083de5cfb0SJiri Olsa 
120923d4aad4SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
12100a102479SFrederic Weisbecker {
12110a102479SFrederic Weisbecker 	struct perf_evsel *evsel;
1212745cefc5SArnaldo Carvalho de Melo 	int err = 0;
1213745cefc5SArnaldo Carvalho de Melo 	const int ncpus = cpu_map__nr(evlist->cpus),
1214b3a319d5SNamhyung Kim 		  nthreads = thread_map__nr(evlist->threads);
12150a102479SFrederic Weisbecker 
12160050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
1217745cefc5SArnaldo Carvalho de Melo 		if (evsel->filter == NULL)
12180a102479SFrederic Weisbecker 			continue;
1219745cefc5SArnaldo Carvalho de Melo 
1220d988d5eeSKan Liang 		/*
1221d988d5eeSKan Liang 		 * filters only work for tracepoint event, which doesn't have cpu limit.
1222d988d5eeSKan Liang 		 * So evlist and evsel should always be same.
1223d988d5eeSKan Liang 		 */
1224f47805a2SArnaldo Carvalho de Melo 		err = perf_evsel__apply_filter(evsel, ncpus, nthreads, evsel->filter);
122523d4aad4SArnaldo Carvalho de Melo 		if (err) {
122623d4aad4SArnaldo Carvalho de Melo 			*err_evsel = evsel;
1227745cefc5SArnaldo Carvalho de Melo 			break;
12280a102479SFrederic Weisbecker 		}
122923d4aad4SArnaldo Carvalho de Melo 	}
12300a102479SFrederic Weisbecker 
1231745cefc5SArnaldo Carvalho de Melo 	return err;
1232745cefc5SArnaldo Carvalho de Melo }
1233745cefc5SArnaldo Carvalho de Melo 
1234745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1235745cefc5SArnaldo Carvalho de Melo {
1236745cefc5SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
1237745cefc5SArnaldo Carvalho de Melo 	int err = 0;
1238745cefc5SArnaldo Carvalho de Melo 
12390050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
124094ad89bcSArnaldo Carvalho de Melo 		err = perf_evsel__set_filter(evsel, filter);
1241745cefc5SArnaldo Carvalho de Melo 		if (err)
1242745cefc5SArnaldo Carvalho de Melo 			break;
1243745cefc5SArnaldo Carvalho de Melo 	}
1244745cefc5SArnaldo Carvalho de Melo 
1245745cefc5SArnaldo Carvalho de Melo 	return err;
12460a102479SFrederic Weisbecker }
124774429964SFrederic Weisbecker 
1248be199adaSArnaldo Carvalho de Melo int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
1249cfd70a26SArnaldo Carvalho de Melo {
1250cfd70a26SArnaldo Carvalho de Melo 	char *filter;
1251be199adaSArnaldo Carvalho de Melo 	int ret = -1;
1252be199adaSArnaldo Carvalho de Melo 	size_t i;
1253cfd70a26SArnaldo Carvalho de Melo 
1254be199adaSArnaldo Carvalho de Melo 	for (i = 0; i < npids; ++i) {
1255be199adaSArnaldo Carvalho de Melo 		if (i == 0) {
1256be199adaSArnaldo Carvalho de Melo 			if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
1257cfd70a26SArnaldo Carvalho de Melo 				return -1;
1258be199adaSArnaldo Carvalho de Melo 		} else {
1259be199adaSArnaldo Carvalho de Melo 			char *tmp;
1260be199adaSArnaldo Carvalho de Melo 
1261be199adaSArnaldo Carvalho de Melo 			if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
1262be199adaSArnaldo Carvalho de Melo 				goto out_free;
1263be199adaSArnaldo Carvalho de Melo 
1264be199adaSArnaldo Carvalho de Melo 			free(filter);
1265be199adaSArnaldo Carvalho de Melo 			filter = tmp;
1266be199adaSArnaldo Carvalho de Melo 		}
1267be199adaSArnaldo Carvalho de Melo 	}
1268cfd70a26SArnaldo Carvalho de Melo 
1269cfd70a26SArnaldo Carvalho de Melo 	ret = perf_evlist__set_filter(evlist, filter);
1270be199adaSArnaldo Carvalho de Melo out_free:
1271cfd70a26SArnaldo Carvalho de Melo 	free(filter);
1272cfd70a26SArnaldo Carvalho de Melo 	return ret;
1273cfd70a26SArnaldo Carvalho de Melo }
1274cfd70a26SArnaldo Carvalho de Melo 
1275be199adaSArnaldo Carvalho de Melo int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
1276be199adaSArnaldo Carvalho de Melo {
1277be199adaSArnaldo Carvalho de Melo 	return perf_evlist__set_filter_pids(evlist, 1, &pid);
1278be199adaSArnaldo Carvalho de Melo }
1279be199adaSArnaldo Carvalho de Melo 
12800c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
128174429964SFrederic Weisbecker {
128275562573SAdrian Hunter 	struct perf_evsel *pos;
1283c2a70653SArnaldo Carvalho de Melo 
128475562573SAdrian Hunter 	if (evlist->nr_entries == 1)
128575562573SAdrian Hunter 		return true;
128675562573SAdrian Hunter 
128775562573SAdrian Hunter 	if (evlist->id_pos < 0 || evlist->is_pos < 0)
128875562573SAdrian Hunter 		return false;
128975562573SAdrian Hunter 
12900050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
129175562573SAdrian Hunter 		if (pos->id_pos != evlist->id_pos ||
129275562573SAdrian Hunter 		    pos->is_pos != evlist->is_pos)
1293c2a70653SArnaldo Carvalho de Melo 			return false;
129474429964SFrederic Weisbecker 	}
129574429964SFrederic Weisbecker 
1296c2a70653SArnaldo Carvalho de Melo 	return true;
1297c2a70653SArnaldo Carvalho de Melo }
1298c2a70653SArnaldo Carvalho de Melo 
129975562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
1300c2a70653SArnaldo Carvalho de Melo {
130175562573SAdrian Hunter 	struct perf_evsel *evsel;
130275562573SAdrian Hunter 
130375562573SAdrian Hunter 	if (evlist->combined_sample_type)
130475562573SAdrian Hunter 		return evlist->combined_sample_type;
130575562573SAdrian Hunter 
13060050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel)
130775562573SAdrian Hunter 		evlist->combined_sample_type |= evsel->attr.sample_type;
130875562573SAdrian Hunter 
130975562573SAdrian Hunter 	return evlist->combined_sample_type;
131075562573SAdrian Hunter }
131175562573SAdrian Hunter 
131275562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist)
131375562573SAdrian Hunter {
131475562573SAdrian Hunter 	evlist->combined_sample_type = 0;
131575562573SAdrian Hunter 	return __perf_evlist__combined_sample_type(evlist);
1316c2a70653SArnaldo Carvalho de Melo }
1317c2a70653SArnaldo Carvalho de Melo 
131898df858eSAndi Kleen u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
131998df858eSAndi Kleen {
132098df858eSAndi Kleen 	struct perf_evsel *evsel;
132198df858eSAndi Kleen 	u64 branch_type = 0;
132298df858eSAndi Kleen 
132398df858eSAndi Kleen 	evlist__for_each(evlist, evsel)
132498df858eSAndi Kleen 		branch_type |= evsel->attr.branch_sample_type;
132598df858eSAndi Kleen 	return branch_type;
132698df858eSAndi Kleen }
132798df858eSAndi Kleen 
13289ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
13299ede473cSJiri Olsa {
13309ede473cSJiri Olsa 	struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
13319ede473cSJiri Olsa 	u64 read_format = first->attr.read_format;
13329ede473cSJiri Olsa 	u64 sample_type = first->attr.sample_type;
13339ede473cSJiri Olsa 
13340050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, pos) {
13359ede473cSJiri Olsa 		if (read_format != pos->attr.read_format)
13369ede473cSJiri Olsa 			return false;
13379ede473cSJiri Olsa 	}
13389ede473cSJiri Olsa 
13399ede473cSJiri Olsa 	/* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */
13409ede473cSJiri Olsa 	if ((sample_type & PERF_SAMPLE_READ) &&
13419ede473cSJiri Olsa 	    !(read_format & PERF_FORMAT_ID)) {
13429ede473cSJiri Olsa 		return false;
13439ede473cSJiri Olsa 	}
13449ede473cSJiri Olsa 
13459ede473cSJiri Olsa 	return true;
13469ede473cSJiri Olsa }
13479ede473cSJiri Olsa 
13489ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist)
13499ede473cSJiri Olsa {
13509ede473cSJiri Olsa 	struct perf_evsel *first = perf_evlist__first(evlist);
13519ede473cSJiri Olsa 	return first->attr.read_format;
13529ede473cSJiri Olsa }
13539ede473cSJiri Olsa 
13540c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
135581e36bffSArnaldo Carvalho de Melo {
13560c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist);
135781e36bffSArnaldo Carvalho de Melo 	struct perf_sample *data;
135881e36bffSArnaldo Carvalho de Melo 	u64 sample_type;
135981e36bffSArnaldo Carvalho de Melo 	u16 size = 0;
136081e36bffSArnaldo Carvalho de Melo 
136181e36bffSArnaldo Carvalho de Melo 	if (!first->attr.sample_id_all)
136281e36bffSArnaldo Carvalho de Melo 		goto out;
136381e36bffSArnaldo Carvalho de Melo 
136481e36bffSArnaldo Carvalho de Melo 	sample_type = first->attr.sample_type;
136581e36bffSArnaldo Carvalho de Melo 
136681e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_TID)
136781e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->tid) * 2;
136881e36bffSArnaldo Carvalho de Melo 
136981e36bffSArnaldo Carvalho de Melo        if (sample_type & PERF_SAMPLE_TIME)
137081e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->time);
137181e36bffSArnaldo Carvalho de Melo 
137281e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_ID)
137381e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->id);
137481e36bffSArnaldo Carvalho de Melo 
137581e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_STREAM_ID)
137681e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->stream_id);
137781e36bffSArnaldo Carvalho de Melo 
137881e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_CPU)
137981e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->cpu) * 2;
138075562573SAdrian Hunter 
138175562573SAdrian Hunter 	if (sample_type & PERF_SAMPLE_IDENTIFIER)
138275562573SAdrian Hunter 		size += sizeof(data->id);
138381e36bffSArnaldo Carvalho de Melo out:
138481e36bffSArnaldo Carvalho de Melo 	return size;
138581e36bffSArnaldo Carvalho de Melo }
138681e36bffSArnaldo Carvalho de Melo 
13870c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
1388c2a70653SArnaldo Carvalho de Melo {
13890c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
1390c2a70653SArnaldo Carvalho de Melo 
13910050f7aaSArnaldo Carvalho de Melo 	evlist__for_each_continue(evlist, pos) {
1392c2a70653SArnaldo Carvalho de Melo 		if (first->attr.sample_id_all != pos->attr.sample_id_all)
1393c2a70653SArnaldo Carvalho de Melo 			return false;
1394c2a70653SArnaldo Carvalho de Melo 	}
1395c2a70653SArnaldo Carvalho de Melo 
1396c2a70653SArnaldo Carvalho de Melo 	return true;
139774429964SFrederic Weisbecker }
139874429964SFrederic Weisbecker 
13990c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
140074429964SFrederic Weisbecker {
14010c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist);
1402c2a70653SArnaldo Carvalho de Melo 	return first->attr.sample_id_all;
140374429964SFrederic Weisbecker }
140481cce8deSArnaldo Carvalho de Melo 
140581cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist,
140681cce8deSArnaldo Carvalho de Melo 			       struct perf_evsel *evsel)
140781cce8deSArnaldo Carvalho de Melo {
140881cce8deSArnaldo Carvalho de Melo 	evlist->selected = evsel;
140981cce8deSArnaldo Carvalho de Melo }
1410727ab04eSArnaldo Carvalho de Melo 
1411a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist)
1412a74b4b66SNamhyung Kim {
1413a74b4b66SNamhyung Kim 	struct perf_evsel *evsel;
1414a74b4b66SNamhyung Kim 	int ncpus = cpu_map__nr(evlist->cpus);
1415a74b4b66SNamhyung Kim 	int nthreads = thread_map__nr(evlist->threads);
14168ad9219eSStephane Eranian 	int n;
1417a74b4b66SNamhyung Kim 
14188ad9219eSStephane Eranian 	evlist__for_each_reverse(evlist, evsel) {
14198ad9219eSStephane Eranian 		n = evsel->cpus ? evsel->cpus->nr : ncpus;
14208ad9219eSStephane Eranian 		perf_evsel__close(evsel, n, nthreads);
14218ad9219eSStephane Eranian 	}
1422a74b4b66SNamhyung Kim }
1423a74b4b66SNamhyung Kim 
14244112eb18SArnaldo Carvalho de Melo static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
14254112eb18SArnaldo Carvalho de Melo {
14268c0498b6SAdrian Hunter 	struct cpu_map	  *cpus;
14278c0498b6SAdrian Hunter 	struct thread_map *threads;
14284112eb18SArnaldo Carvalho de Melo 	int err = -ENOMEM;
14294112eb18SArnaldo Carvalho de Melo 
14304112eb18SArnaldo Carvalho de Melo 	/*
14314112eb18SArnaldo Carvalho de Melo 	 * Try reading /sys/devices/system/cpu/online to get
14324112eb18SArnaldo Carvalho de Melo 	 * an all cpus map.
14334112eb18SArnaldo Carvalho de Melo 	 *
14344112eb18SArnaldo Carvalho de Melo 	 * FIXME: -ENOMEM is the best we can do here, the cpu_map
14354112eb18SArnaldo Carvalho de Melo 	 * code needs an overhaul to properly forward the
14364112eb18SArnaldo Carvalho de Melo 	 * error, and we may not want to do that fallback to a
14374112eb18SArnaldo Carvalho de Melo 	 * default cpu identity map :-\
14384112eb18SArnaldo Carvalho de Melo 	 */
14398c0498b6SAdrian Hunter 	cpus = cpu_map__new(NULL);
14408c0498b6SAdrian Hunter 	if (!cpus)
14414112eb18SArnaldo Carvalho de Melo 		goto out;
14424112eb18SArnaldo Carvalho de Melo 
14438c0498b6SAdrian Hunter 	threads = thread_map__new_dummy();
14448c0498b6SAdrian Hunter 	if (!threads)
14458c0498b6SAdrian Hunter 		goto out_put;
14464112eb18SArnaldo Carvalho de Melo 
14478c0498b6SAdrian Hunter 	perf_evlist__set_maps(evlist, cpus, threads);
14484112eb18SArnaldo Carvalho de Melo out:
14494112eb18SArnaldo Carvalho de Melo 	return err;
14508c0498b6SAdrian Hunter out_put:
14518c0498b6SAdrian Hunter 	cpu_map__put(cpus);
14524112eb18SArnaldo Carvalho de Melo 	goto out;
14534112eb18SArnaldo Carvalho de Melo }
14544112eb18SArnaldo Carvalho de Melo 
14556a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist)
1456727ab04eSArnaldo Carvalho de Melo {
14576a4bb04cSJiri Olsa 	struct perf_evsel *evsel;
1458a74b4b66SNamhyung Kim 	int err;
1459727ab04eSArnaldo Carvalho de Melo 
14604112eb18SArnaldo Carvalho de Melo 	/*
14614112eb18SArnaldo Carvalho de Melo 	 * Default: one fd per CPU, all threads, aka systemwide
14624112eb18SArnaldo Carvalho de Melo 	 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
14634112eb18SArnaldo Carvalho de Melo 	 */
14644112eb18SArnaldo Carvalho de Melo 	if (evlist->threads == NULL && evlist->cpus == NULL) {
14654112eb18SArnaldo Carvalho de Melo 		err = perf_evlist__create_syswide_maps(evlist);
14664112eb18SArnaldo Carvalho de Melo 		if (err < 0)
14674112eb18SArnaldo Carvalho de Melo 			goto out_err;
14684112eb18SArnaldo Carvalho de Melo 	}
14694112eb18SArnaldo Carvalho de Melo 
1470733cd2feSAdrian Hunter 	perf_evlist__update_id_pos(evlist);
1471733cd2feSAdrian Hunter 
14720050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
14736a4bb04cSJiri Olsa 		err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
1474727ab04eSArnaldo Carvalho de Melo 		if (err < 0)
1475727ab04eSArnaldo Carvalho de Melo 			goto out_err;
1476727ab04eSArnaldo Carvalho de Melo 	}
1477727ab04eSArnaldo Carvalho de Melo 
1478727ab04eSArnaldo Carvalho de Melo 	return 0;
1479727ab04eSArnaldo Carvalho de Melo out_err:
1480a74b4b66SNamhyung Kim 	perf_evlist__close(evlist);
148141c21a68SNamhyung Kim 	errno = -err;
1482727ab04eSArnaldo Carvalho de Melo 	return err;
1483727ab04eSArnaldo Carvalho de Melo }
148435b9d88eSArnaldo Carvalho de Melo 
1485602ad878SArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
148655e162eaSNamhyung Kim 				  const char *argv[], bool pipe_output,
1487735f7e0bSArnaldo Carvalho de Melo 				  void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
148835b9d88eSArnaldo Carvalho de Melo {
148935b9d88eSArnaldo Carvalho de Melo 	int child_ready_pipe[2], go_pipe[2];
149035b9d88eSArnaldo Carvalho de Melo 	char bf;
149135b9d88eSArnaldo Carvalho de Melo 
149235b9d88eSArnaldo Carvalho de Melo 	if (pipe(child_ready_pipe) < 0) {
149335b9d88eSArnaldo Carvalho de Melo 		perror("failed to create 'ready' pipe");
149435b9d88eSArnaldo Carvalho de Melo 		return -1;
149535b9d88eSArnaldo Carvalho de Melo 	}
149635b9d88eSArnaldo Carvalho de Melo 
149735b9d88eSArnaldo Carvalho de Melo 	if (pipe(go_pipe) < 0) {
149835b9d88eSArnaldo Carvalho de Melo 		perror("failed to create 'go' pipe");
149935b9d88eSArnaldo Carvalho de Melo 		goto out_close_ready_pipe;
150035b9d88eSArnaldo Carvalho de Melo 	}
150135b9d88eSArnaldo Carvalho de Melo 
150235b9d88eSArnaldo Carvalho de Melo 	evlist->workload.pid = fork();
150335b9d88eSArnaldo Carvalho de Melo 	if (evlist->workload.pid < 0) {
150435b9d88eSArnaldo Carvalho de Melo 		perror("failed to fork");
150535b9d88eSArnaldo Carvalho de Melo 		goto out_close_pipes;
150635b9d88eSArnaldo Carvalho de Melo 	}
150735b9d88eSArnaldo Carvalho de Melo 
150835b9d88eSArnaldo Carvalho de Melo 	if (!evlist->workload.pid) {
15095f1c4225SArnaldo Carvalho de Melo 		int ret;
15105f1c4225SArnaldo Carvalho de Melo 
1511119fa3c9SNamhyung Kim 		if (pipe_output)
151235b9d88eSArnaldo Carvalho de Melo 			dup2(2, 1);
151335b9d88eSArnaldo Carvalho de Melo 
15140817df08SDavid Ahern 		signal(SIGTERM, SIG_DFL);
15150817df08SDavid Ahern 
151635b9d88eSArnaldo Carvalho de Melo 		close(child_ready_pipe[0]);
151735b9d88eSArnaldo Carvalho de Melo 		close(go_pipe[1]);
151835b9d88eSArnaldo Carvalho de Melo 		fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
151935b9d88eSArnaldo Carvalho de Melo 
152035b9d88eSArnaldo Carvalho de Melo 		/*
152135b9d88eSArnaldo Carvalho de Melo 		 * Tell the parent we're ready to go
152235b9d88eSArnaldo Carvalho de Melo 		 */
152335b9d88eSArnaldo Carvalho de Melo 		close(child_ready_pipe[1]);
152435b9d88eSArnaldo Carvalho de Melo 
152535b9d88eSArnaldo Carvalho de Melo 		/*
152635b9d88eSArnaldo Carvalho de Melo 		 * Wait until the parent tells us to go.
152735b9d88eSArnaldo Carvalho de Melo 		 */
15285f1c4225SArnaldo Carvalho de Melo 		ret = read(go_pipe[0], &bf, 1);
15295f1c4225SArnaldo Carvalho de Melo 		/*
15305f1c4225SArnaldo Carvalho de Melo 		 * The parent will ask for the execvp() to be performed by
15315f1c4225SArnaldo Carvalho de Melo 		 * writing exactly one byte, in workload.cork_fd, usually via
15325f1c4225SArnaldo Carvalho de Melo 		 * perf_evlist__start_workload().
15335f1c4225SArnaldo Carvalho de Melo 		 *
153420f86fc1SArnaldo Carvalho de Melo 		 * For cancelling the workload without actually running it,
15355f1c4225SArnaldo Carvalho de Melo 		 * the parent will just close workload.cork_fd, without writing
15365f1c4225SArnaldo Carvalho de Melo 		 * anything, i.e. read will return zero and we just exit()
15375f1c4225SArnaldo Carvalho de Melo 		 * here.
15385f1c4225SArnaldo Carvalho de Melo 		 */
15395f1c4225SArnaldo Carvalho de Melo 		if (ret != 1) {
15405f1c4225SArnaldo Carvalho de Melo 			if (ret == -1)
154135b9d88eSArnaldo Carvalho de Melo 				perror("unable to read pipe");
15425f1c4225SArnaldo Carvalho de Melo 			exit(ret);
15435f1c4225SArnaldo Carvalho de Melo 		}
154435b9d88eSArnaldo Carvalho de Melo 
154535b9d88eSArnaldo Carvalho de Melo 		execvp(argv[0], (char **)argv);
154635b9d88eSArnaldo Carvalho de Melo 
1547735f7e0bSArnaldo Carvalho de Melo 		if (exec_error) {
1548f33cbe72SArnaldo Carvalho de Melo 			union sigval val;
1549f33cbe72SArnaldo Carvalho de Melo 
1550f33cbe72SArnaldo Carvalho de Melo 			val.sival_int = errno;
1551f33cbe72SArnaldo Carvalho de Melo 			if (sigqueue(getppid(), SIGUSR1, val))
155235b9d88eSArnaldo Carvalho de Melo 				perror(argv[0]);
1553f33cbe72SArnaldo Carvalho de Melo 		} else
1554f33cbe72SArnaldo Carvalho de Melo 			perror(argv[0]);
155535b9d88eSArnaldo Carvalho de Melo 		exit(-1);
155635b9d88eSArnaldo Carvalho de Melo 	}
155735b9d88eSArnaldo Carvalho de Melo 
1558735f7e0bSArnaldo Carvalho de Melo 	if (exec_error) {
1559735f7e0bSArnaldo Carvalho de Melo 		struct sigaction act = {
1560735f7e0bSArnaldo Carvalho de Melo 			.sa_flags     = SA_SIGINFO,
1561735f7e0bSArnaldo Carvalho de Melo 			.sa_sigaction = exec_error,
1562735f7e0bSArnaldo Carvalho de Melo 		};
1563735f7e0bSArnaldo Carvalho de Melo 		sigaction(SIGUSR1, &act, NULL);
1564735f7e0bSArnaldo Carvalho de Melo 	}
1565735f7e0bSArnaldo Carvalho de Melo 
15661aaf63b1SArnaldo Carvalho de Melo 	if (target__none(target)) {
15671aaf63b1SArnaldo Carvalho de Melo 		if (evlist->threads == NULL) {
15681aaf63b1SArnaldo Carvalho de Melo 			fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
15691aaf63b1SArnaldo Carvalho de Melo 				__func__, __LINE__);
15701aaf63b1SArnaldo Carvalho de Melo 			goto out_close_pipes;
15711aaf63b1SArnaldo Carvalho de Melo 		}
1572e13798c7SJiri Olsa 		thread_map__set_pid(evlist->threads, 0, evlist->workload.pid);
15731aaf63b1SArnaldo Carvalho de Melo 	}
157435b9d88eSArnaldo Carvalho de Melo 
157535b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[1]);
157635b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[0]);
157735b9d88eSArnaldo Carvalho de Melo 	/*
157835b9d88eSArnaldo Carvalho de Melo 	 * wait for child to settle
157935b9d88eSArnaldo Carvalho de Melo 	 */
158035b9d88eSArnaldo Carvalho de Melo 	if (read(child_ready_pipe[0], &bf, 1) == -1) {
158135b9d88eSArnaldo Carvalho de Melo 		perror("unable to read pipe");
158235b9d88eSArnaldo Carvalho de Melo 		goto out_close_pipes;
158335b9d88eSArnaldo Carvalho de Melo 	}
158435b9d88eSArnaldo Carvalho de Melo 
1585bcf3145fSNamhyung Kim 	fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
158635b9d88eSArnaldo Carvalho de Melo 	evlist->workload.cork_fd = go_pipe[1];
158735b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[0]);
158835b9d88eSArnaldo Carvalho de Melo 	return 0;
158935b9d88eSArnaldo Carvalho de Melo 
159035b9d88eSArnaldo Carvalho de Melo out_close_pipes:
159135b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[0]);
159235b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[1]);
159335b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe:
159435b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[0]);
159535b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[1]);
159635b9d88eSArnaldo Carvalho de Melo 	return -1;
159735b9d88eSArnaldo Carvalho de Melo }
159835b9d88eSArnaldo Carvalho de Melo 
159935b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist)
160035b9d88eSArnaldo Carvalho de Melo {
160135b9d88eSArnaldo Carvalho de Melo 	if (evlist->workload.cork_fd > 0) {
1602b3824404SDavid Ahern 		char bf = 0;
1603bcf3145fSNamhyung Kim 		int ret;
160435b9d88eSArnaldo Carvalho de Melo 		/*
160535b9d88eSArnaldo Carvalho de Melo 		 * Remove the cork, let it rip!
160635b9d88eSArnaldo Carvalho de Melo 		 */
1607bcf3145fSNamhyung Kim 		ret = write(evlist->workload.cork_fd, &bf, 1);
1608bcf3145fSNamhyung Kim 		if (ret < 0)
1609bcf3145fSNamhyung Kim 			perror("enable to write to pipe");
1610bcf3145fSNamhyung Kim 
1611bcf3145fSNamhyung Kim 		close(evlist->workload.cork_fd);
1612bcf3145fSNamhyung Kim 		return ret;
161335b9d88eSArnaldo Carvalho de Melo 	}
161435b9d88eSArnaldo Carvalho de Melo 
161535b9d88eSArnaldo Carvalho de Melo 	return 0;
161635b9d88eSArnaldo Carvalho de Melo }
1617cb0b29e0SArnaldo Carvalho de Melo 
1618a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
16190807d2d8SArnaldo Carvalho de Melo 			      struct perf_sample *sample)
1620cb0b29e0SArnaldo Carvalho de Melo {
162175562573SAdrian Hunter 	struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
162275562573SAdrian Hunter 
162375562573SAdrian Hunter 	if (!evsel)
162475562573SAdrian Hunter 		return -EFAULT;
16250807d2d8SArnaldo Carvalho de Melo 	return perf_evsel__parse_sample(evsel, event, sample);
1626cb0b29e0SArnaldo Carvalho de Melo }
162778f067b3SArnaldo Carvalho de Melo 
162878f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
162978f067b3SArnaldo Carvalho de Melo {
163078f067b3SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
163178f067b3SArnaldo Carvalho de Melo 	size_t printed = 0;
163278f067b3SArnaldo Carvalho de Melo 
16330050f7aaSArnaldo Carvalho de Melo 	evlist__for_each(evlist, evsel) {
163478f067b3SArnaldo Carvalho de Melo 		printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
163578f067b3SArnaldo Carvalho de Melo 				   perf_evsel__name(evsel));
163678f067b3SArnaldo Carvalho de Melo 	}
163778f067b3SArnaldo Carvalho de Melo 
1638b2222139SDavidlohr Bueso 	return printed + fprintf(fp, "\n");
163978f067b3SArnaldo Carvalho de Melo }
16406ef068cbSArnaldo Carvalho de Melo 
1641a8f23d8fSArnaldo Carvalho de Melo int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1642a8f23d8fSArnaldo Carvalho de Melo 			       int err, char *buf, size_t size)
1643a8f23d8fSArnaldo Carvalho de Melo {
1644a8f23d8fSArnaldo Carvalho de Melo 	int printed, value;
16456e81c74cSMasami Hiramatsu 	char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1646a8f23d8fSArnaldo Carvalho de Melo 
1647a8f23d8fSArnaldo Carvalho de Melo 	switch (err) {
1648a8f23d8fSArnaldo Carvalho de Melo 	case EACCES:
1649a8f23d8fSArnaldo Carvalho de Melo 	case EPERM:
1650a8f23d8fSArnaldo Carvalho de Melo 		printed = scnprintf(buf, size,
1651a8f23d8fSArnaldo Carvalho de Melo 				    "Error:\t%s.\n"
1652a8f23d8fSArnaldo Carvalho de Melo 				    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1653a8f23d8fSArnaldo Carvalho de Melo 
16541a47245dSAdrian Hunter 		value = perf_event_paranoid();
1655a8f23d8fSArnaldo Carvalho de Melo 
1656a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1657a8f23d8fSArnaldo Carvalho de Melo 
1658a8f23d8fSArnaldo Carvalho de Melo 		if (value >= 2) {
1659a8f23d8fSArnaldo Carvalho de Melo 			printed += scnprintf(buf + printed, size - printed,
1660a8f23d8fSArnaldo Carvalho de Melo 					     "For your workloads it needs to be <= 1\nHint:\t");
1661a8f23d8fSArnaldo Carvalho de Melo 		}
1662a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
16635229e366SArnaldo Carvalho de Melo 				     "For system wide tracing it needs to be set to -1.\n");
1664a8f23d8fSArnaldo Carvalho de Melo 
1665a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
16665229e366SArnaldo Carvalho de Melo 				    "Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n"
16675229e366SArnaldo Carvalho de Melo 				    "Hint:\tThe current value is %d.", value);
1668a8f23d8fSArnaldo Carvalho de Melo 		break;
1669a8f23d8fSArnaldo Carvalho de Melo 	default:
1670a8f23d8fSArnaldo Carvalho de Melo 		scnprintf(buf, size, "%s", emsg);
1671a8f23d8fSArnaldo Carvalho de Melo 		break;
1672a8f23d8fSArnaldo Carvalho de Melo 	}
1673a8f23d8fSArnaldo Carvalho de Melo 
1674a8f23d8fSArnaldo Carvalho de Melo 	return 0;
1675a8f23d8fSArnaldo Carvalho de Melo }
1676a025e4f0SAdrian Hunter 
1677956fa571SArnaldo Carvalho de Melo int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1678956fa571SArnaldo Carvalho de Melo {
1679956fa571SArnaldo Carvalho de Melo 	char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1680e965bea1SArnaldo Carvalho de Melo 	int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1681956fa571SArnaldo Carvalho de Melo 
1682956fa571SArnaldo Carvalho de Melo 	switch (err) {
1683956fa571SArnaldo Carvalho de Melo 	case EPERM:
1684e5d4a290SArnaldo Carvalho de Melo 		sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
1685e965bea1SArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
1686e965bea1SArnaldo Carvalho de Melo 				     "Error:\t%s.\n"
1687956fa571SArnaldo Carvalho de Melo 				     "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
1688e965bea1SArnaldo Carvalho de Melo 				     "Hint:\tTried using %zd kB.\n",
1689e5d4a290SArnaldo Carvalho de Melo 				     emsg, pages_max_per_user, pages_attempted);
1690e965bea1SArnaldo Carvalho de Melo 
1691e965bea1SArnaldo Carvalho de Melo 		if (pages_attempted >= pages_max_per_user) {
1692e965bea1SArnaldo Carvalho de Melo 			printed += scnprintf(buf + printed, size - printed,
1693e965bea1SArnaldo Carvalho de Melo 					     "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
1694e965bea1SArnaldo Carvalho de Melo 					     pages_max_per_user + pages_attempted);
1695e965bea1SArnaldo Carvalho de Melo 		}
1696e965bea1SArnaldo Carvalho de Melo 
1697e965bea1SArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
1698e965bea1SArnaldo Carvalho de Melo 				     "Hint:\tTry using a smaller -m/--mmap-pages value.");
1699956fa571SArnaldo Carvalho de Melo 		break;
1700956fa571SArnaldo Carvalho de Melo 	default:
1701956fa571SArnaldo Carvalho de Melo 		scnprintf(buf, size, "%s", emsg);
1702956fa571SArnaldo Carvalho de Melo 		break;
1703956fa571SArnaldo Carvalho de Melo 	}
1704956fa571SArnaldo Carvalho de Melo 
1705956fa571SArnaldo Carvalho de Melo 	return 0;
1706956fa571SArnaldo Carvalho de Melo }
1707956fa571SArnaldo Carvalho de Melo 
1708a025e4f0SAdrian Hunter void perf_evlist__to_front(struct perf_evlist *evlist,
1709a025e4f0SAdrian Hunter 			   struct perf_evsel *move_evsel)
1710a025e4f0SAdrian Hunter {
1711a025e4f0SAdrian Hunter 	struct perf_evsel *evsel, *n;
1712a025e4f0SAdrian Hunter 	LIST_HEAD(move);
1713a025e4f0SAdrian Hunter 
1714a025e4f0SAdrian Hunter 	if (move_evsel == perf_evlist__first(evlist))
1715a025e4f0SAdrian Hunter 		return;
1716a025e4f0SAdrian Hunter 
17170050f7aaSArnaldo Carvalho de Melo 	evlist__for_each_safe(evlist, n, evsel) {
1718a025e4f0SAdrian Hunter 		if (evsel->leader == move_evsel->leader)
1719a025e4f0SAdrian Hunter 			list_move_tail(&evsel->node, &move);
1720a025e4f0SAdrian Hunter 	}
1721a025e4f0SAdrian Hunter 
1722a025e4f0SAdrian Hunter 	list_splice(&move, &evlist->entries);
1723a025e4f0SAdrian Hunter }
172460b0896cSAdrian Hunter 
172560b0896cSAdrian Hunter void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
172660b0896cSAdrian Hunter 				     struct perf_evsel *tracking_evsel)
172760b0896cSAdrian Hunter {
172860b0896cSAdrian Hunter 	struct perf_evsel *evsel;
172960b0896cSAdrian Hunter 
173060b0896cSAdrian Hunter 	if (tracking_evsel->tracking)
173160b0896cSAdrian Hunter 		return;
173260b0896cSAdrian Hunter 
173360b0896cSAdrian Hunter 	evlist__for_each(evlist, evsel) {
173460b0896cSAdrian Hunter 		if (evsel != tracking_evsel)
173560b0896cSAdrian Hunter 			evsel->tracking = false;
173660b0896cSAdrian Hunter 	}
173760b0896cSAdrian Hunter 
173860b0896cSAdrian Hunter 	tracking_evsel->tracking = true;
173960b0896cSAdrian Hunter }
1740