18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Parts came from builtin-{top,stat,record}.c, see those files for further
68c2ecf20Sopenharmony_ci * copyright notes.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <api/fs/fs.h>
98c2ecf20Sopenharmony_ci#include <errno.h>
108c2ecf20Sopenharmony_ci#include <inttypes.h>
118c2ecf20Sopenharmony_ci#include <poll.h>
128c2ecf20Sopenharmony_ci#include "cpumap.h"
138c2ecf20Sopenharmony_ci#include "util/mmap.h"
148c2ecf20Sopenharmony_ci#include "thread_map.h"
158c2ecf20Sopenharmony_ci#include "target.h"
168c2ecf20Sopenharmony_ci#include "evlist.h"
178c2ecf20Sopenharmony_ci#include "evsel.h"
188c2ecf20Sopenharmony_ci#include "debug.h"
198c2ecf20Sopenharmony_ci#include "units.h"
208c2ecf20Sopenharmony_ci#include <internal/lib.h> // page_size
218c2ecf20Sopenharmony_ci#include "affinity.h"
228c2ecf20Sopenharmony_ci#include "../perf.h"
238c2ecf20Sopenharmony_ci#include "asm/bug.h"
248c2ecf20Sopenharmony_ci#include "bpf-event.h"
258c2ecf20Sopenharmony_ci#include "util/string2.h"
268c2ecf20Sopenharmony_ci#include "util/perf_api_probe.h"
278c2ecf20Sopenharmony_ci#include <signal.h>
288c2ecf20Sopenharmony_ci#include <unistd.h>
298c2ecf20Sopenharmony_ci#include <sched.h>
308c2ecf20Sopenharmony_ci#include <stdlib.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include "parse-events.h"
338c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <fcntl.h>
368c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
378c2ecf20Sopenharmony_ci#include <sys/mman.h>
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include <linux/bitops.h>
408c2ecf20Sopenharmony_ci#include <linux/hash.h>
418c2ecf20Sopenharmony_ci#include <linux/log2.h>
428c2ecf20Sopenharmony_ci#include <linux/err.h>
438c2ecf20Sopenharmony_ci#include <linux/string.h>
448c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
458c2ecf20Sopenharmony_ci#include <perf/evlist.h>
468c2ecf20Sopenharmony_ci#include <perf/evsel.h>
478c2ecf20Sopenharmony_ci#include <perf/cpumap.h>
488c2ecf20Sopenharmony_ci#include <perf/mmap.h>
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include <internal/xyarray.h>
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#ifdef LACKS_SIGQUEUE_PROTOTYPE
538c2ecf20Sopenharmony_ciint sigqueue(pid_t pid, int sig, const union sigval value);
548c2ecf20Sopenharmony_ci#endif
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
578c2ecf20Sopenharmony_ci#define SID(e, x, y) xyarray__entry(e->core.sample_id, x, y)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_civoid evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
608c2ecf20Sopenharmony_ci		  struct perf_thread_map *threads)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	perf_evlist__init(&evlist->core);
638c2ecf20Sopenharmony_ci	perf_evlist__set_maps(&evlist->core, cpus, threads);
648c2ecf20Sopenharmony_ci	evlist->workload.pid = -1;
658c2ecf20Sopenharmony_ci	evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
668c2ecf20Sopenharmony_ci	evlist->ctl_fd.fd = -1;
678c2ecf20Sopenharmony_ci	evlist->ctl_fd.ack = -1;
688c2ecf20Sopenharmony_ci	evlist->ctl_fd.pos = -1;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistruct evlist *evlist__new(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct evlist *evlist = zalloc(sizeof(*evlist));
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	if (evlist != NULL)
768c2ecf20Sopenharmony_ci		evlist__init(evlist, NULL, NULL);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return evlist;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistruct evlist *perf_evlist__new_default(void)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	struct evlist *evlist = evlist__new();
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if (evlist && evlist__add_default(evlist)) {
868c2ecf20Sopenharmony_ci		evlist__delete(evlist);
878c2ecf20Sopenharmony_ci		evlist = NULL;
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	return evlist;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct evlist *perf_evlist__new_dummy(void)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	struct evlist *evlist = evlist__new();
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	if (evlist && evlist__add_dummy(evlist)) {
988c2ecf20Sopenharmony_ci		evlist__delete(evlist);
998c2ecf20Sopenharmony_ci		evlist = NULL;
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return evlist;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/**
1068c2ecf20Sopenharmony_ci * perf_evlist__set_id_pos - set the positions of event ids.
1078c2ecf20Sopenharmony_ci * @evlist: selected event list
1088c2ecf20Sopenharmony_ci *
1098c2ecf20Sopenharmony_ci * Events with compatible sample types all have the same id_pos
1108c2ecf20Sopenharmony_ci * and is_pos.  For convenience, put a copy on evlist.
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_civoid perf_evlist__set_id_pos(struct evlist *evlist)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	evlist->id_pos = first->id_pos;
1178c2ecf20Sopenharmony_ci	evlist->is_pos = first->is_pos;
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic void perf_evlist__update_id_pos(struct evlist *evlist)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	struct evsel *evsel;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
1258c2ecf20Sopenharmony_ci		evsel__calc_id_pos(evsel);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	perf_evlist__set_id_pos(evlist);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic void evlist__purge(struct evlist *evlist)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	struct evsel *pos, *n;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	evlist__for_each_entry_safe(evlist, n, pos) {
1358c2ecf20Sopenharmony_ci		list_del_init(&pos->core.node);
1368c2ecf20Sopenharmony_ci		pos->evlist = NULL;
1378c2ecf20Sopenharmony_ci		evsel__delete(pos);
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	evlist->core.nr_entries = 0;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_civoid evlist__exit(struct evlist *evlist)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	zfree(&evlist->mmap);
1468c2ecf20Sopenharmony_ci	zfree(&evlist->overwrite_mmap);
1478c2ecf20Sopenharmony_ci	perf_evlist__exit(&evlist->core);
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_civoid evlist__delete(struct evlist *evlist)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	if (evlist == NULL)
1538c2ecf20Sopenharmony_ci		return;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	evlist__munmap(evlist);
1568c2ecf20Sopenharmony_ci	evlist__close(evlist);
1578c2ecf20Sopenharmony_ci	evlist__purge(evlist);
1588c2ecf20Sopenharmony_ci	evlist__exit(evlist);
1598c2ecf20Sopenharmony_ci	free(evlist);
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_civoid evlist__add(struct evlist *evlist, struct evsel *entry)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	entry->evlist = evlist;
1658c2ecf20Sopenharmony_ci	entry->idx = evlist->core.nr_entries;
1668c2ecf20Sopenharmony_ci	entry->tracking = !entry->idx;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	perf_evlist__add(&evlist->core, &entry->core);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	if (evlist->core.nr_entries == 1)
1718c2ecf20Sopenharmony_ci		perf_evlist__set_id_pos(evlist);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_civoid evlist__remove(struct evlist *evlist, struct evsel *evsel)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	evsel->evlist = NULL;
1778c2ecf20Sopenharmony_ci	perf_evlist__remove(&evlist->core, &evsel->core);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_civoid perf_evlist__splice_list_tail(struct evlist *evlist,
1818c2ecf20Sopenharmony_ci				   struct list_head *list)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	struct evsel *evsel, *temp;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	__evlist__for_each_entry_safe(list, temp, evsel) {
1868c2ecf20Sopenharmony_ci		list_del_init(&evsel->core.node);
1878c2ecf20Sopenharmony_ci		evlist__add(evlist, evsel);
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ciint __evlist__set_tracepoints_handlers(struct evlist *evlist,
1928c2ecf20Sopenharmony_ci				       const struct evsel_str_handler *assocs, size_t nr_assocs)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct evsel *evsel;
1958c2ecf20Sopenharmony_ci	size_t i;
1968c2ecf20Sopenharmony_ci	int err;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	for (i = 0; i < nr_assocs; i++) {
1998c2ecf20Sopenharmony_ci		// Adding a handler for an event not in this evlist, just ignore it.
2008c2ecf20Sopenharmony_ci		evsel = perf_evlist__find_tracepoint_by_name(evlist, assocs[i].name);
2018c2ecf20Sopenharmony_ci		if (evsel == NULL)
2028c2ecf20Sopenharmony_ci			continue;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci		err = -EEXIST;
2058c2ecf20Sopenharmony_ci		if (evsel->handler != NULL)
2068c2ecf20Sopenharmony_ci			goto out;
2078c2ecf20Sopenharmony_ci		evsel->handler = assocs[i].handler;
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	err = 0;
2118c2ecf20Sopenharmony_ciout:
2128c2ecf20Sopenharmony_ci	return err;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_civoid __perf_evlist__set_leader(struct list_head *list)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct evsel *evsel, *leader;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	leader = list_entry(list->next, struct evsel, core.node);
2208c2ecf20Sopenharmony_ci	evsel = list_entry(list->prev, struct evsel, core.node);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	leader->core.nr_members = evsel->idx - leader->idx + 1;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	__evlist__for_each_entry(list, evsel) {
2258c2ecf20Sopenharmony_ci		evsel->leader = leader;
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_civoid perf_evlist__set_leader(struct evlist *evlist)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	if (evlist->core.nr_entries) {
2328c2ecf20Sopenharmony_ci		evlist->nr_groups = evlist->core.nr_entries > 1 ? 1 : 0;
2338c2ecf20Sopenharmony_ci		__perf_evlist__set_leader(&evlist->core.entries);
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciint __evlist__add_default(struct evlist *evlist, bool precise)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct evsel *evsel = evsel__new_cycles(precise);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	if (evsel == NULL)
2428c2ecf20Sopenharmony_ci		return -ENOMEM;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	evlist__add(evlist, evsel);
2458c2ecf20Sopenharmony_ci	return 0;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ciint evlist__add_dummy(struct evlist *evlist)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct perf_event_attr attr = {
2518c2ecf20Sopenharmony_ci		.type	= PERF_TYPE_SOFTWARE,
2528c2ecf20Sopenharmony_ci		.config = PERF_COUNT_SW_DUMMY,
2538c2ecf20Sopenharmony_ci		.size	= sizeof(attr), /* to capture ABI version */
2548c2ecf20Sopenharmony_ci	};
2558c2ecf20Sopenharmony_ci	struct evsel *evsel = evsel__new_idx(&attr, evlist->core.nr_entries);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	if (evsel == NULL)
2588c2ecf20Sopenharmony_ci		return -ENOMEM;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	evlist__add(evlist, evsel);
2618c2ecf20Sopenharmony_ci	return 0;
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct evsel *evsel, *n;
2678c2ecf20Sopenharmony_ci	LIST_HEAD(head);
2688c2ecf20Sopenharmony_ci	size_t i;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	for (i = 0; i < nr_attrs; i++) {
2718c2ecf20Sopenharmony_ci		evsel = evsel__new_idx(attrs + i, evlist->core.nr_entries + i);
2728c2ecf20Sopenharmony_ci		if (evsel == NULL)
2738c2ecf20Sopenharmony_ci			goto out_delete_partial_list;
2748c2ecf20Sopenharmony_ci		list_add_tail(&evsel->core.node, &head);
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	perf_evlist__splice_list_tail(evlist, &head);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	return 0;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ciout_delete_partial_list:
2828c2ecf20Sopenharmony_ci	__evlist__for_each_entry_safe(&head, n, evsel)
2838c2ecf20Sopenharmony_ci		evsel__delete(evsel);
2848c2ecf20Sopenharmony_ci	return -1;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ciint __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	size_t i;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	for (i = 0; i < nr_attrs; i++)
2928c2ecf20Sopenharmony_ci		event_attr_init(attrs + i);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	return evlist__add_attrs(evlist, attrs, nr_attrs);
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistruct evsel *
2988c2ecf20Sopenharmony_ciperf_evlist__find_tracepoint_by_id(struct evlist *evlist, int id)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct evsel *evsel;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
3038c2ecf20Sopenharmony_ci		if (evsel->core.attr.type   == PERF_TYPE_TRACEPOINT &&
3048c2ecf20Sopenharmony_ci		    (int)evsel->core.attr.config == id)
3058c2ecf20Sopenharmony_ci			return evsel;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return NULL;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistruct evsel *
3128c2ecf20Sopenharmony_ciperf_evlist__find_tracepoint_by_name(struct evlist *evlist,
3138c2ecf20Sopenharmony_ci				     const char *name)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct evsel *evsel;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
3188c2ecf20Sopenharmony_ci		if ((evsel->core.attr.type == PERF_TYPE_TRACEPOINT) &&
3198c2ecf20Sopenharmony_ci		    (strcmp(evsel->name, name) == 0))
3208c2ecf20Sopenharmony_ci			return evsel;
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	return NULL;
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ciint evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	struct evsel *evsel = evsel__newtp(sys, name);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (IS_ERR(evsel))
3318c2ecf20Sopenharmony_ci		return -1;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	evsel->handler = handler;
3348c2ecf20Sopenharmony_ci	evlist__add(evlist, evsel);
3358c2ecf20Sopenharmony_ci	return 0;
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic int perf_evlist__nr_threads(struct evlist *evlist,
3398c2ecf20Sopenharmony_ci				   struct evsel *evsel)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	if (evsel->core.system_wide)
3428c2ecf20Sopenharmony_ci		return 1;
3438c2ecf20Sopenharmony_ci	else
3448c2ecf20Sopenharmony_ci		return perf_thread_map__nr(evlist->core.threads);
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_civoid evlist__cpu_iter_start(struct evlist *evlist)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	struct evsel *pos;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/*
3528c2ecf20Sopenharmony_ci	 * Reset the per evsel cpu_iter. This is needed because
3538c2ecf20Sopenharmony_ci	 * each evsel's cpumap may have a different index space,
3548c2ecf20Sopenharmony_ci	 * and some operations need the index to modify
3558c2ecf20Sopenharmony_ci	 * the FD xyarray (e.g. open, close)
3568c2ecf20Sopenharmony_ci	 */
3578c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos)
3588c2ecf20Sopenharmony_ci		pos->cpu_iter = 0;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cibool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	if (ev->cpu_iter >= ev->core.cpus->nr)
3648c2ecf20Sopenharmony_ci		return true;
3658c2ecf20Sopenharmony_ci	if (cpu >= 0 && ev->core.cpus->map[ev->cpu_iter] != cpu)
3668c2ecf20Sopenharmony_ci		return true;
3678c2ecf20Sopenharmony_ci	return false;
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cibool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
3738c2ecf20Sopenharmony_ci		ev->cpu_iter++;
3748c2ecf20Sopenharmony_ci		return false;
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci	return true;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_civoid evlist__disable(struct evlist *evlist)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct evsel *pos;
3828c2ecf20Sopenharmony_ci	struct affinity affinity;
3838c2ecf20Sopenharmony_ci	int cpu, i, imm = 0;
3848c2ecf20Sopenharmony_ci	bool has_imm = false;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (affinity__setup(&affinity) < 0)
3878c2ecf20Sopenharmony_ci		return;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* Disable 'immediate' events last */
3908c2ecf20Sopenharmony_ci	for (imm = 0; imm <= 1; imm++) {
3918c2ecf20Sopenharmony_ci		evlist__for_each_cpu(evlist, i, cpu) {
3928c2ecf20Sopenharmony_ci			affinity__set(&affinity, cpu);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci			evlist__for_each_entry(evlist, pos) {
3958c2ecf20Sopenharmony_ci				if (evsel__cpu_iter_skip(pos, cpu))
3968c2ecf20Sopenharmony_ci					continue;
3978c2ecf20Sopenharmony_ci				if (pos->disabled || !evsel__is_group_leader(pos) || !pos->core.fd)
3988c2ecf20Sopenharmony_ci					continue;
3998c2ecf20Sopenharmony_ci				if (pos->immediate)
4008c2ecf20Sopenharmony_ci					has_imm = true;
4018c2ecf20Sopenharmony_ci				if (pos->immediate != imm)
4028c2ecf20Sopenharmony_ci					continue;
4038c2ecf20Sopenharmony_ci				evsel__disable_cpu(pos, pos->cpu_iter - 1);
4048c2ecf20Sopenharmony_ci			}
4058c2ecf20Sopenharmony_ci		}
4068c2ecf20Sopenharmony_ci		if (!has_imm)
4078c2ecf20Sopenharmony_ci			break;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	affinity__cleanup(&affinity);
4118c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
4128c2ecf20Sopenharmony_ci		if (!evsel__is_group_leader(pos) || !pos->core.fd)
4138c2ecf20Sopenharmony_ci			continue;
4148c2ecf20Sopenharmony_ci		pos->disabled = true;
4158c2ecf20Sopenharmony_ci	}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	evlist->enabled = false;
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_civoid evlist__enable(struct evlist *evlist)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	struct evsel *pos;
4238c2ecf20Sopenharmony_ci	struct affinity affinity;
4248c2ecf20Sopenharmony_ci	int cpu, i;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (affinity__setup(&affinity) < 0)
4278c2ecf20Sopenharmony_ci		return;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	evlist__for_each_cpu(evlist, i, cpu) {
4308c2ecf20Sopenharmony_ci		affinity__set(&affinity, cpu);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci		evlist__for_each_entry(evlist, pos) {
4338c2ecf20Sopenharmony_ci			if (evsel__cpu_iter_skip(pos, cpu))
4348c2ecf20Sopenharmony_ci				continue;
4358c2ecf20Sopenharmony_ci			if (!evsel__is_group_leader(pos) || !pos->core.fd)
4368c2ecf20Sopenharmony_ci				continue;
4378c2ecf20Sopenharmony_ci			evsel__enable_cpu(pos, pos->cpu_iter - 1);
4388c2ecf20Sopenharmony_ci		}
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci	affinity__cleanup(&affinity);
4418c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
4428c2ecf20Sopenharmony_ci		if (!evsel__is_group_leader(pos) || !pos->core.fd)
4438c2ecf20Sopenharmony_ci			continue;
4448c2ecf20Sopenharmony_ci		pos->disabled = false;
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	evlist->enabled = true;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_civoid perf_evlist__toggle_enable(struct evlist *evlist)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	(evlist->enabled ? evlist__disable : evlist__enable)(evlist);
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_cistatic int perf_evlist__enable_event_cpu(struct evlist *evlist,
4568c2ecf20Sopenharmony_ci					 struct evsel *evsel, int cpu)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	int thread;
4598c2ecf20Sopenharmony_ci	int nr_threads = perf_evlist__nr_threads(evlist, evsel);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	if (!evsel->core.fd)
4628c2ecf20Sopenharmony_ci		return -EINVAL;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	for (thread = 0; thread < nr_threads; thread++) {
4658c2ecf20Sopenharmony_ci		int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
4668c2ecf20Sopenharmony_ci		if (err)
4678c2ecf20Sopenharmony_ci			return err;
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci	return 0;
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic int perf_evlist__enable_event_thread(struct evlist *evlist,
4738c2ecf20Sopenharmony_ci					    struct evsel *evsel,
4748c2ecf20Sopenharmony_ci					    int thread)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci	int cpu;
4778c2ecf20Sopenharmony_ci	int nr_cpus = perf_cpu_map__nr(evlist->core.cpus);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	if (!evsel->core.fd)
4808c2ecf20Sopenharmony_ci		return -EINVAL;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < nr_cpus; cpu++) {
4838c2ecf20Sopenharmony_ci		int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
4848c2ecf20Sopenharmony_ci		if (err)
4858c2ecf20Sopenharmony_ci			return err;
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci	return 0;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ciint perf_evlist__enable_event_idx(struct evlist *evlist,
4918c2ecf20Sopenharmony_ci				  struct evsel *evsel, int idx)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	bool per_cpu_mmaps = !perf_cpu_map__empty(evlist->core.cpus);
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	if (per_cpu_mmaps)
4968c2ecf20Sopenharmony_ci		return perf_evlist__enable_event_cpu(evlist, evsel, idx);
4978c2ecf20Sopenharmony_ci	else
4988c2ecf20Sopenharmony_ci		return perf_evlist__enable_event_thread(evlist, evsel, idx);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ciint evlist__add_pollfd(struct evlist *evlist, int fd)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	return perf_evlist__add_pollfd(&evlist->core, fd, NULL, POLLIN, fdarray_flag__default);
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ciint evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	return perf_evlist__filter_pollfd(&evlist->core, revents_and_mask);
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT
5128c2ecf20Sopenharmony_ciint evlist__add_wakeup_eventfd(struct evlist *evlist, int fd)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	return perf_evlist__add_pollfd(&evlist->core, fd, NULL, POLLIN,
5158c2ecf20Sopenharmony_ci				       fdarray_flag__nonfilterable);
5168c2ecf20Sopenharmony_ci}
5178c2ecf20Sopenharmony_ci#endif
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ciint evlist__poll(struct evlist *evlist, int timeout)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	return perf_evlist__poll(&evlist->core, timeout);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_cistruct perf_sample_id *perf_evlist__id2sid(struct evlist *evlist, u64 id)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	struct hlist_head *head;
5278c2ecf20Sopenharmony_ci	struct perf_sample_id *sid;
5288c2ecf20Sopenharmony_ci	int hash;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
5318c2ecf20Sopenharmony_ci	head = &evlist->core.heads[hash];
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	hlist_for_each_entry(sid, head, node)
5348c2ecf20Sopenharmony_ci		if (sid->id == id)
5358c2ecf20Sopenharmony_ci			return sid;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	return NULL;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cistruct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	struct perf_sample_id *sid;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	if (evlist->core.nr_entries == 1 || !id)
5458c2ecf20Sopenharmony_ci		return evlist__first(evlist);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	sid = perf_evlist__id2sid(evlist, id);
5488c2ecf20Sopenharmony_ci	if (sid)
5498c2ecf20Sopenharmony_ci		return container_of(sid->evsel, struct evsel, core);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if (!evlist__sample_id_all(evlist))
5528c2ecf20Sopenharmony_ci		return evlist__first(evlist);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	return NULL;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_cistruct evsel *perf_evlist__id2evsel_strict(struct evlist *evlist,
5588c2ecf20Sopenharmony_ci						u64 id)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	struct perf_sample_id *sid;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (!id)
5638c2ecf20Sopenharmony_ci		return NULL;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	sid = perf_evlist__id2sid(evlist, id);
5668c2ecf20Sopenharmony_ci	if (sid)
5678c2ecf20Sopenharmony_ci		return container_of(sid->evsel, struct evsel, core);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	return NULL;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic int perf_evlist__event2id(struct evlist *evlist,
5738c2ecf20Sopenharmony_ci				 union perf_event *event, u64 *id)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	const __u64 *array = event->sample.array;
5768c2ecf20Sopenharmony_ci	ssize_t n;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	n = (event->header.size - sizeof(event->header)) >> 3;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_SAMPLE) {
5818c2ecf20Sopenharmony_ci		if (evlist->id_pos >= n)
5828c2ecf20Sopenharmony_ci			return -1;
5838c2ecf20Sopenharmony_ci		*id = array[evlist->id_pos];
5848c2ecf20Sopenharmony_ci	} else {
5858c2ecf20Sopenharmony_ci		if (evlist->is_pos > n)
5868c2ecf20Sopenharmony_ci			return -1;
5878c2ecf20Sopenharmony_ci		n -= evlist->is_pos;
5888c2ecf20Sopenharmony_ci		*id = array[n];
5898c2ecf20Sopenharmony_ci	}
5908c2ecf20Sopenharmony_ci	return 0;
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistruct evsel *perf_evlist__event2evsel(struct evlist *evlist,
5948c2ecf20Sopenharmony_ci					    union perf_event *event)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist);
5978c2ecf20Sopenharmony_ci	struct hlist_head *head;
5988c2ecf20Sopenharmony_ci	struct perf_sample_id *sid;
5998c2ecf20Sopenharmony_ci	int hash;
6008c2ecf20Sopenharmony_ci	u64 id;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (evlist->core.nr_entries == 1)
6038c2ecf20Sopenharmony_ci		return first;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	if (!first->core.attr.sample_id_all &&
6068c2ecf20Sopenharmony_ci	    event->header.type != PERF_RECORD_SAMPLE)
6078c2ecf20Sopenharmony_ci		return first;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (perf_evlist__event2id(evlist, event, &id))
6108c2ecf20Sopenharmony_ci		return NULL;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* Synthesized events have an id of zero */
6138c2ecf20Sopenharmony_ci	if (!id)
6148c2ecf20Sopenharmony_ci		return first;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
6178c2ecf20Sopenharmony_ci	head = &evlist->core.heads[hash];
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	hlist_for_each_entry(sid, head, node) {
6208c2ecf20Sopenharmony_ci		if (sid->id == id)
6218c2ecf20Sopenharmony_ci			return container_of(sid->evsel, struct evsel, core);
6228c2ecf20Sopenharmony_ci	}
6238c2ecf20Sopenharmony_ci	return NULL;
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic int perf_evlist__set_paused(struct evlist *evlist, bool value)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	int i;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (!evlist->overwrite_mmap)
6318c2ecf20Sopenharmony_ci		return 0;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	for (i = 0; i < evlist->core.nr_mmaps; i++) {
6348c2ecf20Sopenharmony_ci		int fd = evlist->overwrite_mmap[i].core.fd;
6358c2ecf20Sopenharmony_ci		int err;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci		if (fd < 0)
6388c2ecf20Sopenharmony_ci			continue;
6398c2ecf20Sopenharmony_ci		err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0);
6408c2ecf20Sopenharmony_ci		if (err)
6418c2ecf20Sopenharmony_ci			return err;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci	return 0;
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic int perf_evlist__pause(struct evlist *evlist)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	return perf_evlist__set_paused(evlist, true);
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic int perf_evlist__resume(struct evlist *evlist)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	return perf_evlist__set_paused(evlist, false);
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic void evlist__munmap_nofree(struct evlist *evlist)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	int i;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	if (evlist->mmap)
6618c2ecf20Sopenharmony_ci		for (i = 0; i < evlist->core.nr_mmaps; i++)
6628c2ecf20Sopenharmony_ci			perf_mmap__munmap(&evlist->mmap[i].core);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	if (evlist->overwrite_mmap)
6658c2ecf20Sopenharmony_ci		for (i = 0; i < evlist->core.nr_mmaps; i++)
6668c2ecf20Sopenharmony_ci			perf_mmap__munmap(&evlist->overwrite_mmap[i].core);
6678c2ecf20Sopenharmony_ci}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_civoid evlist__munmap(struct evlist *evlist)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	evlist__munmap_nofree(evlist);
6728c2ecf20Sopenharmony_ci	zfree(&evlist->mmap);
6738c2ecf20Sopenharmony_ci	zfree(&evlist->overwrite_mmap);
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic void perf_mmap__unmap_cb(struct perf_mmap *map)
6778c2ecf20Sopenharmony_ci{
6788c2ecf20Sopenharmony_ci	struct mmap *m = container_of(map, struct mmap, core);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	mmap__munmap(m);
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistatic struct mmap *evlist__alloc_mmap(struct evlist *evlist,
6848c2ecf20Sopenharmony_ci				       bool overwrite)
6858c2ecf20Sopenharmony_ci{
6868c2ecf20Sopenharmony_ci	int i;
6878c2ecf20Sopenharmony_ci	struct mmap *map;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	map = zalloc(evlist->core.nr_mmaps * sizeof(struct mmap));
6908c2ecf20Sopenharmony_ci	if (!map)
6918c2ecf20Sopenharmony_ci		return NULL;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	for (i = 0; i < evlist->core.nr_mmaps; i++) {
6948c2ecf20Sopenharmony_ci		struct perf_mmap *prev = i ? &map[i - 1].core : NULL;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		/*
6978c2ecf20Sopenharmony_ci		 * When the perf_mmap() call is made we grab one refcount, plus
6988c2ecf20Sopenharmony_ci		 * one extra to let perf_mmap__consume() get the last
6998c2ecf20Sopenharmony_ci		 * events after all real references (perf_mmap__get()) are
7008c2ecf20Sopenharmony_ci		 * dropped.
7018c2ecf20Sopenharmony_ci		 *
7028c2ecf20Sopenharmony_ci		 * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
7038c2ecf20Sopenharmony_ci		 * thus does perf_mmap__get() on it.
7048c2ecf20Sopenharmony_ci		 */
7058c2ecf20Sopenharmony_ci		perf_mmap__init(&map[i].core, prev, overwrite, perf_mmap__unmap_cb);
7068c2ecf20Sopenharmony_ci	}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	return map;
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_cistatic void
7128c2ecf20Sopenharmony_ciperf_evlist__mmap_cb_idx(struct perf_evlist *_evlist,
7138c2ecf20Sopenharmony_ci			 struct perf_mmap_param *_mp,
7148c2ecf20Sopenharmony_ci			 int idx, bool per_cpu)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	struct evlist *evlist = container_of(_evlist, struct evlist, core);
7178c2ecf20Sopenharmony_ci	struct mmap_params *mp = container_of(_mp, struct mmap_params, core);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, idx, per_cpu);
7208c2ecf20Sopenharmony_ci}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic struct perf_mmap*
7238c2ecf20Sopenharmony_ciperf_evlist__mmap_cb_get(struct perf_evlist *_evlist, bool overwrite, int idx)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	struct evlist *evlist = container_of(_evlist, struct evlist, core);
7268c2ecf20Sopenharmony_ci	struct mmap *maps;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (!maps) {
7318c2ecf20Sopenharmony_ci		maps = evlist__alloc_mmap(evlist, overwrite);
7328c2ecf20Sopenharmony_ci		if (!maps)
7338c2ecf20Sopenharmony_ci			return NULL;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci		if (overwrite) {
7368c2ecf20Sopenharmony_ci			evlist->overwrite_mmap = maps;
7378c2ecf20Sopenharmony_ci			if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
7388c2ecf20Sopenharmony_ci				perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
7398c2ecf20Sopenharmony_ci		} else {
7408c2ecf20Sopenharmony_ci			evlist->mmap = maps;
7418c2ecf20Sopenharmony_ci		}
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	return &maps[idx].core;
7458c2ecf20Sopenharmony_ci}
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cistatic int
7488c2ecf20Sopenharmony_ciperf_evlist__mmap_cb_mmap(struct perf_mmap *_map, struct perf_mmap_param *_mp,
7498c2ecf20Sopenharmony_ci			  int output, int cpu)
7508c2ecf20Sopenharmony_ci{
7518c2ecf20Sopenharmony_ci	struct mmap *map = container_of(_map, struct mmap, core);
7528c2ecf20Sopenharmony_ci	struct mmap_params *mp = container_of(_mp, struct mmap_params, core);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	return mmap__mmap(map, mp, output, cpu);
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ciunsigned long perf_event_mlock_kb_in_pages(void)
7588c2ecf20Sopenharmony_ci{
7598c2ecf20Sopenharmony_ci	unsigned long pages;
7608c2ecf20Sopenharmony_ci	int max;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
7638c2ecf20Sopenharmony_ci		/*
7648c2ecf20Sopenharmony_ci		 * Pick a once upon a time good value, i.e. things look
7658c2ecf20Sopenharmony_ci		 * strange since we can't read a sysctl value, but lets not
7668c2ecf20Sopenharmony_ci		 * die yet...
7678c2ecf20Sopenharmony_ci		 */
7688c2ecf20Sopenharmony_ci		max = 512;
7698c2ecf20Sopenharmony_ci	} else {
7708c2ecf20Sopenharmony_ci		max -= (page_size / 1024);
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	pages = (max * 1024) / page_size;
7748c2ecf20Sopenharmony_ci	if (!is_power_of_2(pages))
7758c2ecf20Sopenharmony_ci		pages = rounddown_pow_of_two(pages);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	return pages;
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_cisize_t evlist__mmap_size(unsigned long pages)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	if (pages == UINT_MAX)
7838c2ecf20Sopenharmony_ci		pages = perf_event_mlock_kb_in_pages();
7848c2ecf20Sopenharmony_ci	else if (!is_power_of_2(pages))
7858c2ecf20Sopenharmony_ci		return 0;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	return (pages + 1) * page_size;
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_cistatic long parse_pages_arg(const char *str, unsigned long min,
7918c2ecf20Sopenharmony_ci			    unsigned long max)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	unsigned long pages, val;
7948c2ecf20Sopenharmony_ci	static struct parse_tag tags[] = {
7958c2ecf20Sopenharmony_ci		{ .tag  = 'B', .mult = 1       },
7968c2ecf20Sopenharmony_ci		{ .tag  = 'K', .mult = 1 << 10 },
7978c2ecf20Sopenharmony_ci		{ .tag  = 'M', .mult = 1 << 20 },
7988c2ecf20Sopenharmony_ci		{ .tag  = 'G', .mult = 1 << 30 },
7998c2ecf20Sopenharmony_ci		{ .tag  = 0 },
8008c2ecf20Sopenharmony_ci	};
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	if (str == NULL)
8038c2ecf20Sopenharmony_ci		return -EINVAL;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	val = parse_tag_value(str, tags);
8068c2ecf20Sopenharmony_ci	if (val != (unsigned long) -1) {
8078c2ecf20Sopenharmony_ci		/* we got file size value */
8088c2ecf20Sopenharmony_ci		pages = PERF_ALIGN(val, page_size) / page_size;
8098c2ecf20Sopenharmony_ci	} else {
8108c2ecf20Sopenharmony_ci		/* we got pages count value */
8118c2ecf20Sopenharmony_ci		char *eptr;
8128c2ecf20Sopenharmony_ci		pages = strtoul(str, &eptr, 10);
8138c2ecf20Sopenharmony_ci		if (*eptr != '\0')
8148c2ecf20Sopenharmony_ci			return -EINVAL;
8158c2ecf20Sopenharmony_ci	}
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	if (pages == 0 && min == 0) {
8188c2ecf20Sopenharmony_ci		/* leave number of pages at 0 */
8198c2ecf20Sopenharmony_ci	} else if (!is_power_of_2(pages)) {
8208c2ecf20Sopenharmony_ci		char buf[100];
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci		/* round pages up to next power of 2 */
8238c2ecf20Sopenharmony_ci		pages = roundup_pow_of_two(pages);
8248c2ecf20Sopenharmony_ci		if (!pages)
8258c2ecf20Sopenharmony_ci			return -EINVAL;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci		unit_number__scnprintf(buf, sizeof(buf), pages * page_size);
8288c2ecf20Sopenharmony_ci		pr_info("rounding mmap pages size to %s (%lu pages)\n",
8298c2ecf20Sopenharmony_ci			buf, pages);
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	if (pages > max)
8338c2ecf20Sopenharmony_ci		return -EINVAL;
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	return pages;
8368c2ecf20Sopenharmony_ci}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ciint __perf_evlist__parse_mmap_pages(unsigned int *mmap_pages, const char *str)
8398c2ecf20Sopenharmony_ci{
8408c2ecf20Sopenharmony_ci	unsigned long max = UINT_MAX;
8418c2ecf20Sopenharmony_ci	long pages;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	if (max > SIZE_MAX / page_size)
8448c2ecf20Sopenharmony_ci		max = SIZE_MAX / page_size;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	pages = parse_pages_arg(str, 1, max);
8478c2ecf20Sopenharmony_ci	if (pages < 0) {
8488c2ecf20Sopenharmony_ci		pr_err("Invalid argument for --mmap_pages/-m\n");
8498c2ecf20Sopenharmony_ci		return -1;
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	*mmap_pages = pages;
8538c2ecf20Sopenharmony_ci	return 0;
8548c2ecf20Sopenharmony_ci}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ciint perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
8578c2ecf20Sopenharmony_ci				  int unset __maybe_unused)
8588c2ecf20Sopenharmony_ci{
8598c2ecf20Sopenharmony_ci	return __perf_evlist__parse_mmap_pages(opt->value, str);
8608c2ecf20Sopenharmony_ci}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci/**
8638c2ecf20Sopenharmony_ci * evlist__mmap_ex - Create mmaps to receive events.
8648c2ecf20Sopenharmony_ci * @evlist: list of events
8658c2ecf20Sopenharmony_ci * @pages: map length in pages
8668c2ecf20Sopenharmony_ci * @overwrite: overwrite older events?
8678c2ecf20Sopenharmony_ci * @auxtrace_pages - auxtrace map length in pages
8688c2ecf20Sopenharmony_ci * @auxtrace_overwrite - overwrite older auxtrace data?
8698c2ecf20Sopenharmony_ci *
8708c2ecf20Sopenharmony_ci * If @overwrite is %false the user needs to signal event consumption using
8718c2ecf20Sopenharmony_ci * perf_mmap__write_tail().  Using evlist__mmap_read() does this
8728c2ecf20Sopenharmony_ci * automatically.
8738c2ecf20Sopenharmony_ci *
8748c2ecf20Sopenharmony_ci * Similarly, if @auxtrace_overwrite is %false the user needs to signal data
8758c2ecf20Sopenharmony_ci * consumption using auxtrace_mmap__write_tail().
8768c2ecf20Sopenharmony_ci *
8778c2ecf20Sopenharmony_ci * Return: %0 on success, negative error code otherwise.
8788c2ecf20Sopenharmony_ci */
8798c2ecf20Sopenharmony_ciint evlist__mmap_ex(struct evlist *evlist, unsigned int pages,
8808c2ecf20Sopenharmony_ci			 unsigned int auxtrace_pages,
8818c2ecf20Sopenharmony_ci			 bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush,
8828c2ecf20Sopenharmony_ci			 int comp_level)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	/*
8858c2ecf20Sopenharmony_ci	 * Delay setting mp.prot: set it before calling perf_mmap__mmap.
8868c2ecf20Sopenharmony_ci	 * Its value is decided by evsel's write_backward.
8878c2ecf20Sopenharmony_ci	 * So &mp should not be passed through const pointer.
8888c2ecf20Sopenharmony_ci	 */
8898c2ecf20Sopenharmony_ci	struct mmap_params mp = {
8908c2ecf20Sopenharmony_ci		.nr_cblocks	= nr_cblocks,
8918c2ecf20Sopenharmony_ci		.affinity	= affinity,
8928c2ecf20Sopenharmony_ci		.flush		= flush,
8938c2ecf20Sopenharmony_ci		.comp_level	= comp_level
8948c2ecf20Sopenharmony_ci	};
8958c2ecf20Sopenharmony_ci	struct perf_evlist_mmap_ops ops = {
8968c2ecf20Sopenharmony_ci		.idx  = perf_evlist__mmap_cb_idx,
8978c2ecf20Sopenharmony_ci		.get  = perf_evlist__mmap_cb_get,
8988c2ecf20Sopenharmony_ci		.mmap = perf_evlist__mmap_cb_mmap,
8998c2ecf20Sopenharmony_ci	};
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	evlist->core.mmap_len = evlist__mmap_size(pages);
9028c2ecf20Sopenharmony_ci	pr_debug("mmap size %zuB\n", evlist->core.mmap_len);
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->core.mmap_len,
9058c2ecf20Sopenharmony_ci				   auxtrace_pages, auxtrace_overwrite);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	return perf_evlist__mmap_ops(&evlist->core, &ops, &mp.core);
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ciint evlist__mmap(struct evlist *evlist, unsigned int pages)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci	return evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1, 0);
9138c2ecf20Sopenharmony_ci}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ciint perf_evlist__create_maps(struct evlist *evlist, struct target *target)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	bool all_threads = (target->per_thread && target->system_wide);
9188c2ecf20Sopenharmony_ci	struct perf_cpu_map *cpus;
9198c2ecf20Sopenharmony_ci	struct perf_thread_map *threads;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	/*
9228c2ecf20Sopenharmony_ci	 * If specify '-a' and '--per-thread' to perf record, perf record
9238c2ecf20Sopenharmony_ci	 * will override '--per-thread'. target->per_thread = false and
9248c2ecf20Sopenharmony_ci	 * target->system_wide = true.
9258c2ecf20Sopenharmony_ci	 *
9268c2ecf20Sopenharmony_ci	 * If specify '--per-thread' only to perf record,
9278c2ecf20Sopenharmony_ci	 * target->per_thread = true and target->system_wide = false.
9288c2ecf20Sopenharmony_ci	 *
9298c2ecf20Sopenharmony_ci	 * So target->per_thread && target->system_wide is false.
9308c2ecf20Sopenharmony_ci	 * For perf record, thread_map__new_str doesn't call
9318c2ecf20Sopenharmony_ci	 * thread_map__new_all_cpus. That will keep perf record's
9328c2ecf20Sopenharmony_ci	 * current behavior.
9338c2ecf20Sopenharmony_ci	 *
9348c2ecf20Sopenharmony_ci	 * For perf stat, it allows the case that target->per_thread and
9358c2ecf20Sopenharmony_ci	 * target->system_wide are all true. It means to collect system-wide
9368c2ecf20Sopenharmony_ci	 * per-thread data. thread_map__new_str will call
9378c2ecf20Sopenharmony_ci	 * thread_map__new_all_cpus to enumerate all threads.
9388c2ecf20Sopenharmony_ci	 */
9398c2ecf20Sopenharmony_ci	threads = thread_map__new_str(target->pid, target->tid, target->uid,
9408c2ecf20Sopenharmony_ci				      all_threads);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	if (!threads)
9438c2ecf20Sopenharmony_ci		return -1;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	if (target__uses_dummy_map(target))
9468c2ecf20Sopenharmony_ci		cpus = perf_cpu_map__dummy_new();
9478c2ecf20Sopenharmony_ci	else
9488c2ecf20Sopenharmony_ci		cpus = perf_cpu_map__new(target->cpu_list);
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	if (!cpus)
9518c2ecf20Sopenharmony_ci		goto out_delete_threads;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	evlist->core.has_user_cpus = !!target->cpu_list;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	perf_evlist__set_maps(&evlist->core, cpus, threads);
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	/* as evlist now has references, put count here */
9588c2ecf20Sopenharmony_ci	perf_cpu_map__put(cpus);
9598c2ecf20Sopenharmony_ci	perf_thread_map__put(threads);
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	return 0;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ciout_delete_threads:
9648c2ecf20Sopenharmony_ci	perf_thread_map__put(threads);
9658c2ecf20Sopenharmony_ci	return -1;
9668c2ecf20Sopenharmony_ci}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_civoid __perf_evlist__set_sample_bit(struct evlist *evlist,
9698c2ecf20Sopenharmony_ci				   enum perf_event_sample_format bit)
9708c2ecf20Sopenharmony_ci{
9718c2ecf20Sopenharmony_ci	struct evsel *evsel;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
9748c2ecf20Sopenharmony_ci		__evsel__set_sample_bit(evsel, bit);
9758c2ecf20Sopenharmony_ci}
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_civoid __perf_evlist__reset_sample_bit(struct evlist *evlist,
9788c2ecf20Sopenharmony_ci				     enum perf_event_sample_format bit)
9798c2ecf20Sopenharmony_ci{
9808c2ecf20Sopenharmony_ci	struct evsel *evsel;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
9838c2ecf20Sopenharmony_ci		__evsel__reset_sample_bit(evsel, bit);
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ciint perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	struct evsel *evsel;
9898c2ecf20Sopenharmony_ci	int err = 0;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
9928c2ecf20Sopenharmony_ci		if (evsel->filter == NULL)
9938c2ecf20Sopenharmony_ci			continue;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci		/*
9968c2ecf20Sopenharmony_ci		 * filters only work for tracepoint event, which doesn't have cpu limit.
9978c2ecf20Sopenharmony_ci		 * So evlist and evsel should always be same.
9988c2ecf20Sopenharmony_ci		 */
9998c2ecf20Sopenharmony_ci		err = perf_evsel__apply_filter(&evsel->core, evsel->filter);
10008c2ecf20Sopenharmony_ci		if (err) {
10018c2ecf20Sopenharmony_ci			*err_evsel = evsel;
10028c2ecf20Sopenharmony_ci			break;
10038c2ecf20Sopenharmony_ci		}
10048c2ecf20Sopenharmony_ci	}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	return err;
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ciint perf_evlist__set_tp_filter(struct evlist *evlist, const char *filter)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	struct evsel *evsel;
10128c2ecf20Sopenharmony_ci	int err = 0;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	if (filter == NULL)
10158c2ecf20Sopenharmony_ci		return -1;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
10188c2ecf20Sopenharmony_ci		if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
10198c2ecf20Sopenharmony_ci			continue;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci		err = evsel__set_filter(evsel, filter);
10228c2ecf20Sopenharmony_ci		if (err)
10238c2ecf20Sopenharmony_ci			break;
10248c2ecf20Sopenharmony_ci	}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	return err;
10278c2ecf20Sopenharmony_ci}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ciint perf_evlist__append_tp_filter(struct evlist *evlist, const char *filter)
10308c2ecf20Sopenharmony_ci{
10318c2ecf20Sopenharmony_ci	struct evsel *evsel;
10328c2ecf20Sopenharmony_ci	int err = 0;
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	if (filter == NULL)
10358c2ecf20Sopenharmony_ci		return -1;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
10388c2ecf20Sopenharmony_ci		if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
10398c2ecf20Sopenharmony_ci			continue;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		err = evsel__append_tp_filter(evsel, filter);
10428c2ecf20Sopenharmony_ci		if (err)
10438c2ecf20Sopenharmony_ci			break;
10448c2ecf20Sopenharmony_ci	}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	return err;
10478c2ecf20Sopenharmony_ci}
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cichar *asprintf__tp_filter_pids(size_t npids, pid_t *pids)
10508c2ecf20Sopenharmony_ci{
10518c2ecf20Sopenharmony_ci	char *filter;
10528c2ecf20Sopenharmony_ci	size_t i;
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	for (i = 0; i < npids; ++i) {
10558c2ecf20Sopenharmony_ci		if (i == 0) {
10568c2ecf20Sopenharmony_ci			if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
10578c2ecf20Sopenharmony_ci				return NULL;
10588c2ecf20Sopenharmony_ci		} else {
10598c2ecf20Sopenharmony_ci			char *tmp;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci			if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
10628c2ecf20Sopenharmony_ci				goto out_free;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci			free(filter);
10658c2ecf20Sopenharmony_ci			filter = tmp;
10668c2ecf20Sopenharmony_ci		}
10678c2ecf20Sopenharmony_ci	}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	return filter;
10708c2ecf20Sopenharmony_ciout_free:
10718c2ecf20Sopenharmony_ci	free(filter);
10728c2ecf20Sopenharmony_ci	return NULL;
10738c2ecf20Sopenharmony_ci}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ciint perf_evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	char *filter = asprintf__tp_filter_pids(npids, pids);
10788c2ecf20Sopenharmony_ci	int ret = perf_evlist__set_tp_filter(evlist, filter);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	free(filter);
10818c2ecf20Sopenharmony_ci	return ret;
10828c2ecf20Sopenharmony_ci}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ciint perf_evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid)
10858c2ecf20Sopenharmony_ci{
10868c2ecf20Sopenharmony_ci	return perf_evlist__set_tp_filter_pids(evlist, 1, &pid);
10878c2ecf20Sopenharmony_ci}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ciint perf_evlist__append_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids)
10908c2ecf20Sopenharmony_ci{
10918c2ecf20Sopenharmony_ci	char *filter = asprintf__tp_filter_pids(npids, pids);
10928c2ecf20Sopenharmony_ci	int ret = perf_evlist__append_tp_filter(evlist, filter);
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	free(filter);
10958c2ecf20Sopenharmony_ci	return ret;
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ciint perf_evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	return perf_evlist__append_tp_filter_pids(evlist, 1, &pid);
11018c2ecf20Sopenharmony_ci}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_cibool evlist__valid_sample_type(struct evlist *evlist)
11048c2ecf20Sopenharmony_ci{
11058c2ecf20Sopenharmony_ci	struct evsel *pos;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	if (evlist->core.nr_entries == 1)
11088c2ecf20Sopenharmony_ci		return true;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	if (evlist->id_pos < 0 || evlist->is_pos < 0)
11118c2ecf20Sopenharmony_ci		return false;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
11148c2ecf20Sopenharmony_ci		if (pos->id_pos != evlist->id_pos ||
11158c2ecf20Sopenharmony_ci		    pos->is_pos != evlist->is_pos)
11168c2ecf20Sopenharmony_ci			return false;
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	return true;
11208c2ecf20Sopenharmony_ci}
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ciu64 __evlist__combined_sample_type(struct evlist *evlist)
11238c2ecf20Sopenharmony_ci{
11248c2ecf20Sopenharmony_ci	struct evsel *evsel;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	if (evlist->combined_sample_type)
11278c2ecf20Sopenharmony_ci		return evlist->combined_sample_type;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
11308c2ecf20Sopenharmony_ci		evlist->combined_sample_type |= evsel->core.attr.sample_type;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	return evlist->combined_sample_type;
11338c2ecf20Sopenharmony_ci}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ciu64 evlist__combined_sample_type(struct evlist *evlist)
11368c2ecf20Sopenharmony_ci{
11378c2ecf20Sopenharmony_ci	evlist->combined_sample_type = 0;
11388c2ecf20Sopenharmony_ci	return __evlist__combined_sample_type(evlist);
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ciu64 evlist__combined_branch_type(struct evlist *evlist)
11428c2ecf20Sopenharmony_ci{
11438c2ecf20Sopenharmony_ci	struct evsel *evsel;
11448c2ecf20Sopenharmony_ci	u64 branch_type = 0;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel)
11478c2ecf20Sopenharmony_ci		branch_type |= evsel->core.attr.branch_sample_type;
11488c2ecf20Sopenharmony_ci	return branch_type;
11498c2ecf20Sopenharmony_ci}
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_cibool perf_evlist__valid_read_format(struct evlist *evlist)
11528c2ecf20Sopenharmony_ci{
11538c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist), *pos = first;
11548c2ecf20Sopenharmony_ci	u64 read_format = first->core.attr.read_format;
11558c2ecf20Sopenharmony_ci	u64 sample_type = first->core.attr.sample_type;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
11588c2ecf20Sopenharmony_ci		if (read_format != pos->core.attr.read_format) {
11598c2ecf20Sopenharmony_ci			pr_debug("Read format differs %#" PRIx64 " vs %#" PRIx64 "\n",
11608c2ecf20Sopenharmony_ci				 read_format, (u64)pos->core.attr.read_format);
11618c2ecf20Sopenharmony_ci		}
11628c2ecf20Sopenharmony_ci	}
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	/* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */
11658c2ecf20Sopenharmony_ci	if ((sample_type & PERF_SAMPLE_READ) &&
11668c2ecf20Sopenharmony_ci	    !(read_format & PERF_FORMAT_ID)) {
11678c2ecf20Sopenharmony_ci		return false;
11688c2ecf20Sopenharmony_ci	}
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	return true;
11718c2ecf20Sopenharmony_ci}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ciu16 perf_evlist__id_hdr_size(struct evlist *evlist)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist);
11768c2ecf20Sopenharmony_ci	struct perf_sample *data;
11778c2ecf20Sopenharmony_ci	u64 sample_type;
11788c2ecf20Sopenharmony_ci	u16 size = 0;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	if (!first->core.attr.sample_id_all)
11818c2ecf20Sopenharmony_ci		goto out;
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	sample_type = first->core.attr.sample_type;
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_TID)
11868c2ecf20Sopenharmony_ci		size += sizeof(data->tid) * 2;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci       if (sample_type & PERF_SAMPLE_TIME)
11898c2ecf20Sopenharmony_ci		size += sizeof(data->time);
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_ID)
11928c2ecf20Sopenharmony_ci		size += sizeof(data->id);
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_STREAM_ID)
11958c2ecf20Sopenharmony_ci		size += sizeof(data->stream_id);
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_CPU)
11988c2ecf20Sopenharmony_ci		size += sizeof(data->cpu) * 2;
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_IDENTIFIER)
12018c2ecf20Sopenharmony_ci		size += sizeof(data->id);
12028c2ecf20Sopenharmony_ciout:
12038c2ecf20Sopenharmony_ci	return size;
12048c2ecf20Sopenharmony_ci}
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_cibool evlist__valid_sample_id_all(struct evlist *evlist)
12078c2ecf20Sopenharmony_ci{
12088c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist), *pos = first;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	evlist__for_each_entry_continue(evlist, pos) {
12118c2ecf20Sopenharmony_ci		if (first->core.attr.sample_id_all != pos->core.attr.sample_id_all)
12128c2ecf20Sopenharmony_ci			return false;
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	return true;
12168c2ecf20Sopenharmony_ci}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_cibool evlist__sample_id_all(struct evlist *evlist)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	struct evsel *first = evlist__first(evlist);
12218c2ecf20Sopenharmony_ci	return first->core.attr.sample_id_all;
12228c2ecf20Sopenharmony_ci}
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_civoid perf_evlist__set_selected(struct evlist *evlist,
12258c2ecf20Sopenharmony_ci			       struct evsel *evsel)
12268c2ecf20Sopenharmony_ci{
12278c2ecf20Sopenharmony_ci	evlist->selected = evsel;
12288c2ecf20Sopenharmony_ci}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_civoid evlist__close(struct evlist *evlist)
12318c2ecf20Sopenharmony_ci{
12328c2ecf20Sopenharmony_ci	struct evsel *evsel;
12338c2ecf20Sopenharmony_ci	struct affinity affinity;
12348c2ecf20Sopenharmony_ci	int cpu, i;
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	/*
12378c2ecf20Sopenharmony_ci	 * With perf record core.cpus is usually NULL.
12388c2ecf20Sopenharmony_ci	 * Use the old method to handle this for now.
12398c2ecf20Sopenharmony_ci	 */
12408c2ecf20Sopenharmony_ci	if (!evlist->core.cpus) {
12418c2ecf20Sopenharmony_ci		evlist__for_each_entry_reverse(evlist, evsel)
12428c2ecf20Sopenharmony_ci			evsel__close(evsel);
12438c2ecf20Sopenharmony_ci		return;
12448c2ecf20Sopenharmony_ci	}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	if (affinity__setup(&affinity) < 0)
12478c2ecf20Sopenharmony_ci		return;
12488c2ecf20Sopenharmony_ci	evlist__for_each_cpu(evlist, i, cpu) {
12498c2ecf20Sopenharmony_ci		affinity__set(&affinity, cpu);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci		evlist__for_each_entry_reverse(evlist, evsel) {
12528c2ecf20Sopenharmony_ci			if (evsel__cpu_iter_skip(evsel, cpu))
12538c2ecf20Sopenharmony_ci			    continue;
12548c2ecf20Sopenharmony_ci			perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
12558c2ecf20Sopenharmony_ci		}
12568c2ecf20Sopenharmony_ci	}
12578c2ecf20Sopenharmony_ci	affinity__cleanup(&affinity);
12588c2ecf20Sopenharmony_ci	evlist__for_each_entry_reverse(evlist, evsel) {
12598c2ecf20Sopenharmony_ci		perf_evsel__free_fd(&evsel->core);
12608c2ecf20Sopenharmony_ci		perf_evsel__free_id(&evsel->core);
12618c2ecf20Sopenharmony_ci	}
12628c2ecf20Sopenharmony_ci}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_cistatic int perf_evlist__create_syswide_maps(struct evlist *evlist)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	struct perf_cpu_map *cpus;
12678c2ecf20Sopenharmony_ci	struct perf_thread_map *threads;
12688c2ecf20Sopenharmony_ci	int err = -ENOMEM;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	/*
12718c2ecf20Sopenharmony_ci	 * Try reading /sys/devices/system/cpu/online to get
12728c2ecf20Sopenharmony_ci	 * an all cpus map.
12738c2ecf20Sopenharmony_ci	 *
12748c2ecf20Sopenharmony_ci	 * FIXME: -ENOMEM is the best we can do here, the cpu_map
12758c2ecf20Sopenharmony_ci	 * code needs an overhaul to properly forward the
12768c2ecf20Sopenharmony_ci	 * error, and we may not want to do that fallback to a
12778c2ecf20Sopenharmony_ci	 * default cpu identity map :-\
12788c2ecf20Sopenharmony_ci	 */
12798c2ecf20Sopenharmony_ci	cpus = perf_cpu_map__new(NULL);
12808c2ecf20Sopenharmony_ci	if (!cpus)
12818c2ecf20Sopenharmony_ci		goto out;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	threads = perf_thread_map__new_dummy();
12848c2ecf20Sopenharmony_ci	if (!threads)
12858c2ecf20Sopenharmony_ci		goto out_put;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	perf_evlist__set_maps(&evlist->core, cpus, threads);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	perf_thread_map__put(threads);
12908c2ecf20Sopenharmony_ciout_put:
12918c2ecf20Sopenharmony_ci	perf_cpu_map__put(cpus);
12928c2ecf20Sopenharmony_ciout:
12938c2ecf20Sopenharmony_ci	return err;
12948c2ecf20Sopenharmony_ci}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ciint evlist__open(struct evlist *evlist)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct evsel *evsel;
12998c2ecf20Sopenharmony_ci	int err;
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	/*
13028c2ecf20Sopenharmony_ci	 * Default: one fd per CPU, all threads, aka systemwide
13038c2ecf20Sopenharmony_ci	 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
13048c2ecf20Sopenharmony_ci	 */
13058c2ecf20Sopenharmony_ci	if (evlist->core.threads == NULL && evlist->core.cpus == NULL) {
13068c2ecf20Sopenharmony_ci		err = perf_evlist__create_syswide_maps(evlist);
13078c2ecf20Sopenharmony_ci		if (err < 0)
13088c2ecf20Sopenharmony_ci			goto out_err;
13098c2ecf20Sopenharmony_ci	}
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	perf_evlist__update_id_pos(evlist);
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
13148c2ecf20Sopenharmony_ci		err = evsel__open(evsel, evsel->core.cpus, evsel->core.threads);
13158c2ecf20Sopenharmony_ci		if (err < 0)
13168c2ecf20Sopenharmony_ci			goto out_err;
13178c2ecf20Sopenharmony_ci	}
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	return 0;
13208c2ecf20Sopenharmony_ciout_err:
13218c2ecf20Sopenharmony_ci	evlist__close(evlist);
13228c2ecf20Sopenharmony_ci	errno = -err;
13238c2ecf20Sopenharmony_ci	return err;
13248c2ecf20Sopenharmony_ci}
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ciint perf_evlist__prepare_workload(struct evlist *evlist, struct target *target,
13278c2ecf20Sopenharmony_ci				  const char *argv[], bool pipe_output,
13288c2ecf20Sopenharmony_ci				  void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
13298c2ecf20Sopenharmony_ci{
13308c2ecf20Sopenharmony_ci	int child_ready_pipe[2], go_pipe[2];
13318c2ecf20Sopenharmony_ci	char bf;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	if (pipe(child_ready_pipe) < 0) {
13348c2ecf20Sopenharmony_ci		perror("failed to create 'ready' pipe");
13358c2ecf20Sopenharmony_ci		return -1;
13368c2ecf20Sopenharmony_ci	}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	if (pipe(go_pipe) < 0) {
13398c2ecf20Sopenharmony_ci		perror("failed to create 'go' pipe");
13408c2ecf20Sopenharmony_ci		goto out_close_ready_pipe;
13418c2ecf20Sopenharmony_ci	}
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	evlist->workload.pid = fork();
13448c2ecf20Sopenharmony_ci	if (evlist->workload.pid < 0) {
13458c2ecf20Sopenharmony_ci		perror("failed to fork");
13468c2ecf20Sopenharmony_ci		goto out_close_pipes;
13478c2ecf20Sopenharmony_ci	}
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	if (!evlist->workload.pid) {
13508c2ecf20Sopenharmony_ci		int ret;
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci		if (pipe_output)
13538c2ecf20Sopenharmony_ci			dup2(2, 1);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci		signal(SIGTERM, SIG_DFL);
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_ci		close(child_ready_pipe[0]);
13588c2ecf20Sopenharmony_ci		close(go_pipe[1]);
13598c2ecf20Sopenharmony_ci		fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci		/*
13628c2ecf20Sopenharmony_ci		 * Tell the parent we're ready to go
13638c2ecf20Sopenharmony_ci		 */
13648c2ecf20Sopenharmony_ci		close(child_ready_pipe[1]);
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci		/*
13678c2ecf20Sopenharmony_ci		 * Wait until the parent tells us to go.
13688c2ecf20Sopenharmony_ci		 */
13698c2ecf20Sopenharmony_ci		ret = read(go_pipe[0], &bf, 1);
13708c2ecf20Sopenharmony_ci		/*
13718c2ecf20Sopenharmony_ci		 * The parent will ask for the execvp() to be performed by
13728c2ecf20Sopenharmony_ci		 * writing exactly one byte, in workload.cork_fd, usually via
13738c2ecf20Sopenharmony_ci		 * perf_evlist__start_workload().
13748c2ecf20Sopenharmony_ci		 *
13758c2ecf20Sopenharmony_ci		 * For cancelling the workload without actually running it,
13768c2ecf20Sopenharmony_ci		 * the parent will just close workload.cork_fd, without writing
13778c2ecf20Sopenharmony_ci		 * anything, i.e. read will return zero and we just exit()
13788c2ecf20Sopenharmony_ci		 * here.
13798c2ecf20Sopenharmony_ci		 */
13808c2ecf20Sopenharmony_ci		if (ret != 1) {
13818c2ecf20Sopenharmony_ci			if (ret == -1)
13828c2ecf20Sopenharmony_ci				perror("unable to read pipe");
13838c2ecf20Sopenharmony_ci			exit(ret);
13848c2ecf20Sopenharmony_ci		}
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci		execvp(argv[0], (char **)argv);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci		if (exec_error) {
13898c2ecf20Sopenharmony_ci			union sigval val;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci			val.sival_int = errno;
13928c2ecf20Sopenharmony_ci			if (sigqueue(getppid(), SIGUSR1, val))
13938c2ecf20Sopenharmony_ci				perror(argv[0]);
13948c2ecf20Sopenharmony_ci		} else
13958c2ecf20Sopenharmony_ci			perror(argv[0]);
13968c2ecf20Sopenharmony_ci		exit(-1);
13978c2ecf20Sopenharmony_ci	}
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	if (exec_error) {
14008c2ecf20Sopenharmony_ci		struct sigaction act = {
14018c2ecf20Sopenharmony_ci			.sa_flags     = SA_SIGINFO,
14028c2ecf20Sopenharmony_ci			.sa_sigaction = exec_error,
14038c2ecf20Sopenharmony_ci		};
14048c2ecf20Sopenharmony_ci		sigaction(SIGUSR1, &act, NULL);
14058c2ecf20Sopenharmony_ci	}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	if (target__none(target)) {
14088c2ecf20Sopenharmony_ci		if (evlist->core.threads == NULL) {
14098c2ecf20Sopenharmony_ci			fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
14108c2ecf20Sopenharmony_ci				__func__, __LINE__);
14118c2ecf20Sopenharmony_ci			goto out_close_pipes;
14128c2ecf20Sopenharmony_ci		}
14138c2ecf20Sopenharmony_ci		perf_thread_map__set_pid(evlist->core.threads, 0, evlist->workload.pid);
14148c2ecf20Sopenharmony_ci	}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	close(child_ready_pipe[1]);
14178c2ecf20Sopenharmony_ci	close(go_pipe[0]);
14188c2ecf20Sopenharmony_ci	/*
14198c2ecf20Sopenharmony_ci	 * wait for child to settle
14208c2ecf20Sopenharmony_ci	 */
14218c2ecf20Sopenharmony_ci	if (read(child_ready_pipe[0], &bf, 1) == -1) {
14228c2ecf20Sopenharmony_ci		perror("unable to read pipe");
14238c2ecf20Sopenharmony_ci		goto out_close_pipes;
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
14278c2ecf20Sopenharmony_ci	evlist->workload.cork_fd = go_pipe[1];
14288c2ecf20Sopenharmony_ci	close(child_ready_pipe[0]);
14298c2ecf20Sopenharmony_ci	return 0;
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ciout_close_pipes:
14328c2ecf20Sopenharmony_ci	close(go_pipe[0]);
14338c2ecf20Sopenharmony_ci	close(go_pipe[1]);
14348c2ecf20Sopenharmony_ciout_close_ready_pipe:
14358c2ecf20Sopenharmony_ci	close(child_ready_pipe[0]);
14368c2ecf20Sopenharmony_ci	close(child_ready_pipe[1]);
14378c2ecf20Sopenharmony_ci	return -1;
14388c2ecf20Sopenharmony_ci}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ciint perf_evlist__start_workload(struct evlist *evlist)
14418c2ecf20Sopenharmony_ci{
14428c2ecf20Sopenharmony_ci	if (evlist->workload.cork_fd > 0) {
14438c2ecf20Sopenharmony_ci		char bf = 0;
14448c2ecf20Sopenharmony_ci		int ret;
14458c2ecf20Sopenharmony_ci		/*
14468c2ecf20Sopenharmony_ci		 * Remove the cork, let it rip!
14478c2ecf20Sopenharmony_ci		 */
14488c2ecf20Sopenharmony_ci		ret = write(evlist->workload.cork_fd, &bf, 1);
14498c2ecf20Sopenharmony_ci		if (ret < 0)
14508c2ecf20Sopenharmony_ci			perror("unable to write to pipe");
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci		close(evlist->workload.cork_fd);
14538c2ecf20Sopenharmony_ci		return ret;
14548c2ecf20Sopenharmony_ci	}
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	return 0;
14578c2ecf20Sopenharmony_ci}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ciint perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event,
14608c2ecf20Sopenharmony_ci			      struct perf_sample *sample)
14618c2ecf20Sopenharmony_ci{
14628c2ecf20Sopenharmony_ci	struct evsel *evsel = perf_evlist__event2evsel(evlist, event);
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	if (!evsel)
14658c2ecf20Sopenharmony_ci		return -EFAULT;
14668c2ecf20Sopenharmony_ci	return evsel__parse_sample(evsel, event, sample);
14678c2ecf20Sopenharmony_ci}
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ciint perf_evlist__parse_sample_timestamp(struct evlist *evlist,
14708c2ecf20Sopenharmony_ci					union perf_event *event,
14718c2ecf20Sopenharmony_ci					u64 *timestamp)
14728c2ecf20Sopenharmony_ci{
14738c2ecf20Sopenharmony_ci	struct evsel *evsel = perf_evlist__event2evsel(evlist, event);
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	if (!evsel)
14768c2ecf20Sopenharmony_ci		return -EFAULT;
14778c2ecf20Sopenharmony_ci	return evsel__parse_sample_timestamp(evsel, event, timestamp);
14788c2ecf20Sopenharmony_ci}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ciint evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size)
14818c2ecf20Sopenharmony_ci{
14828c2ecf20Sopenharmony_ci	int printed, value;
14838c2ecf20Sopenharmony_ci	char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	switch (err) {
14868c2ecf20Sopenharmony_ci	case EACCES:
14878c2ecf20Sopenharmony_ci	case EPERM:
14888c2ecf20Sopenharmony_ci		printed = scnprintf(buf, size,
14898c2ecf20Sopenharmony_ci				    "Error:\t%s.\n"
14908c2ecf20Sopenharmony_ci				    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci		value = perf_event_paranoid();
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci		printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci		if (value >= 2) {
14978c2ecf20Sopenharmony_ci			printed += scnprintf(buf + printed, size - printed,
14988c2ecf20Sopenharmony_ci					     "For your workloads it needs to be <= 1\nHint:\t");
14998c2ecf20Sopenharmony_ci		}
15008c2ecf20Sopenharmony_ci		printed += scnprintf(buf + printed, size - printed,
15018c2ecf20Sopenharmony_ci				     "For system wide tracing it needs to be set to -1.\n");
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci		printed += scnprintf(buf + printed, size - printed,
15048c2ecf20Sopenharmony_ci				    "Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n"
15058c2ecf20Sopenharmony_ci				    "Hint:\tThe current value is %d.", value);
15068c2ecf20Sopenharmony_ci		break;
15078c2ecf20Sopenharmony_ci	case EINVAL: {
15088c2ecf20Sopenharmony_ci		struct evsel *first = evlist__first(evlist);
15098c2ecf20Sopenharmony_ci		int max_freq;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci		if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0)
15128c2ecf20Sopenharmony_ci			goto out_default;
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci		if (first->core.attr.sample_freq < (u64)max_freq)
15158c2ecf20Sopenharmony_ci			goto out_default;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci		printed = scnprintf(buf, size,
15188c2ecf20Sopenharmony_ci				    "Error:\t%s.\n"
15198c2ecf20Sopenharmony_ci				    "Hint:\tCheck /proc/sys/kernel/perf_event_max_sample_rate.\n"
15208c2ecf20Sopenharmony_ci				    "Hint:\tThe current value is %d and %" PRIu64 " is being requested.",
15218c2ecf20Sopenharmony_ci				    emsg, max_freq, first->core.attr.sample_freq);
15228c2ecf20Sopenharmony_ci		break;
15238c2ecf20Sopenharmony_ci	}
15248c2ecf20Sopenharmony_ci	default:
15258c2ecf20Sopenharmony_ciout_default:
15268c2ecf20Sopenharmony_ci		scnprintf(buf, size, "%s", emsg);
15278c2ecf20Sopenharmony_ci		break;
15288c2ecf20Sopenharmony_ci	}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	return 0;
15318c2ecf20Sopenharmony_ci}
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ciint evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size)
15348c2ecf20Sopenharmony_ci{
15358c2ecf20Sopenharmony_ci	char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
15368c2ecf20Sopenharmony_ci	int pages_attempted = evlist->core.mmap_len / 1024, pages_max_per_user, printed = 0;
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	switch (err) {
15398c2ecf20Sopenharmony_ci	case EPERM:
15408c2ecf20Sopenharmony_ci		sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
15418c2ecf20Sopenharmony_ci		printed += scnprintf(buf + printed, size - printed,
15428c2ecf20Sopenharmony_ci				     "Error:\t%s.\n"
15438c2ecf20Sopenharmony_ci				     "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
15448c2ecf20Sopenharmony_ci				     "Hint:\tTried using %zd kB.\n",
15458c2ecf20Sopenharmony_ci				     emsg, pages_max_per_user, pages_attempted);
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci		if (pages_attempted >= pages_max_per_user) {
15488c2ecf20Sopenharmony_ci			printed += scnprintf(buf + printed, size - printed,
15498c2ecf20Sopenharmony_ci					     "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
15508c2ecf20Sopenharmony_ci					     pages_max_per_user + pages_attempted);
15518c2ecf20Sopenharmony_ci		}
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci		printed += scnprintf(buf + printed, size - printed,
15548c2ecf20Sopenharmony_ci				     "Hint:\tTry using a smaller -m/--mmap-pages value.");
15558c2ecf20Sopenharmony_ci		break;
15568c2ecf20Sopenharmony_ci	default:
15578c2ecf20Sopenharmony_ci		scnprintf(buf, size, "%s", emsg);
15588c2ecf20Sopenharmony_ci		break;
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	return 0;
15628c2ecf20Sopenharmony_ci}
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_civoid perf_evlist__to_front(struct evlist *evlist,
15658c2ecf20Sopenharmony_ci			   struct evsel *move_evsel)
15668c2ecf20Sopenharmony_ci{
15678c2ecf20Sopenharmony_ci	struct evsel *evsel, *n;
15688c2ecf20Sopenharmony_ci	LIST_HEAD(move);
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	if (move_evsel == evlist__first(evlist))
15718c2ecf20Sopenharmony_ci		return;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	evlist__for_each_entry_safe(evlist, n, evsel) {
15748c2ecf20Sopenharmony_ci		if (evsel->leader == move_evsel->leader)
15758c2ecf20Sopenharmony_ci			list_move_tail(&evsel->core.node, &move);
15768c2ecf20Sopenharmony_ci	}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	list_splice(&move, &evlist->core.entries);
15798c2ecf20Sopenharmony_ci}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_cistruct evsel *perf_evlist__get_tracking_event(struct evlist *evlist)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	struct evsel *evsel;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
15868c2ecf20Sopenharmony_ci		if (evsel->tracking)
15878c2ecf20Sopenharmony_ci			return evsel;
15888c2ecf20Sopenharmony_ci	}
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	return evlist__first(evlist);
15918c2ecf20Sopenharmony_ci}
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_civoid perf_evlist__set_tracking_event(struct evlist *evlist,
15948c2ecf20Sopenharmony_ci				     struct evsel *tracking_evsel)
15958c2ecf20Sopenharmony_ci{
15968c2ecf20Sopenharmony_ci	struct evsel *evsel;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (tracking_evsel->tracking)
15998c2ecf20Sopenharmony_ci		return;
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
16028c2ecf20Sopenharmony_ci		if (evsel != tracking_evsel)
16038c2ecf20Sopenharmony_ci			evsel->tracking = false;
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	tracking_evsel->tracking = true;
16078c2ecf20Sopenharmony_ci}
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_cistruct evsel *
16108c2ecf20Sopenharmony_ciperf_evlist__find_evsel_by_str(struct evlist *evlist,
16118c2ecf20Sopenharmony_ci			       const char *str)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	struct evsel *evsel;
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
16168c2ecf20Sopenharmony_ci		if (!evsel->name)
16178c2ecf20Sopenharmony_ci			continue;
16188c2ecf20Sopenharmony_ci		if (strcmp(str, evsel->name) == 0)
16198c2ecf20Sopenharmony_ci			return evsel;
16208c2ecf20Sopenharmony_ci	}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	return NULL;
16238c2ecf20Sopenharmony_ci}
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_civoid perf_evlist__toggle_bkw_mmap(struct evlist *evlist,
16268c2ecf20Sopenharmony_ci				  enum bkw_mmap_state state)
16278c2ecf20Sopenharmony_ci{
16288c2ecf20Sopenharmony_ci	enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
16298c2ecf20Sopenharmony_ci	enum action {
16308c2ecf20Sopenharmony_ci		NONE,
16318c2ecf20Sopenharmony_ci		PAUSE,
16328c2ecf20Sopenharmony_ci		RESUME,
16338c2ecf20Sopenharmony_ci	} action = NONE;
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	if (!evlist->overwrite_mmap)
16368c2ecf20Sopenharmony_ci		return;
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	switch (old_state) {
16398c2ecf20Sopenharmony_ci	case BKW_MMAP_NOTREADY: {
16408c2ecf20Sopenharmony_ci		if (state != BKW_MMAP_RUNNING)
16418c2ecf20Sopenharmony_ci			goto state_err;
16428c2ecf20Sopenharmony_ci		break;
16438c2ecf20Sopenharmony_ci	}
16448c2ecf20Sopenharmony_ci	case BKW_MMAP_RUNNING: {
16458c2ecf20Sopenharmony_ci		if (state != BKW_MMAP_DATA_PENDING)
16468c2ecf20Sopenharmony_ci			goto state_err;
16478c2ecf20Sopenharmony_ci		action = PAUSE;
16488c2ecf20Sopenharmony_ci		break;
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci	case BKW_MMAP_DATA_PENDING: {
16518c2ecf20Sopenharmony_ci		if (state != BKW_MMAP_EMPTY)
16528c2ecf20Sopenharmony_ci			goto state_err;
16538c2ecf20Sopenharmony_ci		break;
16548c2ecf20Sopenharmony_ci	}
16558c2ecf20Sopenharmony_ci	case BKW_MMAP_EMPTY: {
16568c2ecf20Sopenharmony_ci		if (state != BKW_MMAP_RUNNING)
16578c2ecf20Sopenharmony_ci			goto state_err;
16588c2ecf20Sopenharmony_ci		action = RESUME;
16598c2ecf20Sopenharmony_ci		break;
16608c2ecf20Sopenharmony_ci	}
16618c2ecf20Sopenharmony_ci	default:
16628c2ecf20Sopenharmony_ci		WARN_ONCE(1, "Shouldn't get there\n");
16638c2ecf20Sopenharmony_ci	}
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	evlist->bkw_mmap_state = state;
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	switch (action) {
16688c2ecf20Sopenharmony_ci	case PAUSE:
16698c2ecf20Sopenharmony_ci		perf_evlist__pause(evlist);
16708c2ecf20Sopenharmony_ci		break;
16718c2ecf20Sopenharmony_ci	case RESUME:
16728c2ecf20Sopenharmony_ci		perf_evlist__resume(evlist);
16738c2ecf20Sopenharmony_ci		break;
16748c2ecf20Sopenharmony_ci	case NONE:
16758c2ecf20Sopenharmony_ci	default:
16768c2ecf20Sopenharmony_ci		break;
16778c2ecf20Sopenharmony_ci	}
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_cistate_err:
16808c2ecf20Sopenharmony_ci	return;
16818c2ecf20Sopenharmony_ci}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_cibool perf_evlist__exclude_kernel(struct evlist *evlist)
16848c2ecf20Sopenharmony_ci{
16858c2ecf20Sopenharmony_ci	struct evsel *evsel;
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
16888c2ecf20Sopenharmony_ci		if (!evsel->core.attr.exclude_kernel)
16898c2ecf20Sopenharmony_ci			return false;
16908c2ecf20Sopenharmony_ci	}
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	return true;
16938c2ecf20Sopenharmony_ci}
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci/*
16968c2ecf20Sopenharmony_ci * Events in data file are not collect in groups, but we still want
16978c2ecf20Sopenharmony_ci * the group display. Set the artificial group and set the leader's
16988c2ecf20Sopenharmony_ci * forced_leader flag to notify the display code.
16998c2ecf20Sopenharmony_ci */
17008c2ecf20Sopenharmony_civoid perf_evlist__force_leader(struct evlist *evlist)
17018c2ecf20Sopenharmony_ci{
17028c2ecf20Sopenharmony_ci	if (!evlist->nr_groups) {
17038c2ecf20Sopenharmony_ci		struct evsel *leader = evlist__first(evlist);
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci		perf_evlist__set_leader(evlist);
17068c2ecf20Sopenharmony_ci		leader->forced_leader = true;
17078c2ecf20Sopenharmony_ci	}
17088c2ecf20Sopenharmony_ci}
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_cistruct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
17118c2ecf20Sopenharmony_ci						 struct evsel *evsel,
17128c2ecf20Sopenharmony_ci						bool close)
17138c2ecf20Sopenharmony_ci{
17148c2ecf20Sopenharmony_ci	struct evsel *c2, *leader;
17158c2ecf20Sopenharmony_ci	bool is_open = true;
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	leader = evsel->leader;
17188c2ecf20Sopenharmony_ci	pr_debug("Weak group for %s/%d failed\n",
17198c2ecf20Sopenharmony_ci			leader->name, leader->core.nr_members);
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	/*
17228c2ecf20Sopenharmony_ci	 * for_each_group_member doesn't work here because it doesn't
17238c2ecf20Sopenharmony_ci	 * include the first entry.
17248c2ecf20Sopenharmony_ci	 */
17258c2ecf20Sopenharmony_ci	evlist__for_each_entry(evsel_list, c2) {
17268c2ecf20Sopenharmony_ci		if (c2 == evsel)
17278c2ecf20Sopenharmony_ci			is_open = false;
17288c2ecf20Sopenharmony_ci		if (c2->leader == leader) {
17298c2ecf20Sopenharmony_ci			if (is_open && close)
17308c2ecf20Sopenharmony_ci				perf_evsel__close(&c2->core);
17318c2ecf20Sopenharmony_ci			c2->leader = c2;
17328c2ecf20Sopenharmony_ci			c2->core.nr_members = 0;
17338c2ecf20Sopenharmony_ci			/*
17348c2ecf20Sopenharmony_ci			 * Set this for all former members of the group
17358c2ecf20Sopenharmony_ci			 * to indicate they get reopened.
17368c2ecf20Sopenharmony_ci			 */
17378c2ecf20Sopenharmony_ci			c2->reset_group = true;
17388c2ecf20Sopenharmony_ci		}
17398c2ecf20Sopenharmony_ci	}
17408c2ecf20Sopenharmony_ci	return leader;
17418c2ecf20Sopenharmony_ci}
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_cistatic int evlist__parse_control_fifo(const char *str, int *ctl_fd, int *ctl_fd_ack, bool *ctl_fd_close)
17448c2ecf20Sopenharmony_ci{
17458c2ecf20Sopenharmony_ci	char *s, *p;
17468c2ecf20Sopenharmony_ci	int ret = 0, fd;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	if (strncmp(str, "fifo:", 5))
17498c2ecf20Sopenharmony_ci		return -EINVAL;
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	str += 5;
17528c2ecf20Sopenharmony_ci	if (!*str || *str == ',')
17538c2ecf20Sopenharmony_ci		return -EINVAL;
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	s = strdup(str);
17568c2ecf20Sopenharmony_ci	if (!s)
17578c2ecf20Sopenharmony_ci		return -ENOMEM;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	p = strchr(s, ',');
17608c2ecf20Sopenharmony_ci	if (p)
17618c2ecf20Sopenharmony_ci		*p = '\0';
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	/*
17648c2ecf20Sopenharmony_ci	 * O_RDWR avoids POLLHUPs which is necessary to allow the other
17658c2ecf20Sopenharmony_ci	 * end of a FIFO to be repeatedly opened and closed.
17668c2ecf20Sopenharmony_ci	 */
17678c2ecf20Sopenharmony_ci	fd = open(s, O_RDWR | O_NONBLOCK | O_CLOEXEC);
17688c2ecf20Sopenharmony_ci	if (fd < 0) {
17698c2ecf20Sopenharmony_ci		pr_err("Failed to open '%s'\n", s);
17708c2ecf20Sopenharmony_ci		ret = -errno;
17718c2ecf20Sopenharmony_ci		goto out_free;
17728c2ecf20Sopenharmony_ci	}
17738c2ecf20Sopenharmony_ci	*ctl_fd = fd;
17748c2ecf20Sopenharmony_ci	*ctl_fd_close = true;
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	if (p && *++p) {
17778c2ecf20Sopenharmony_ci		/* O_RDWR | O_NONBLOCK means the other end need not be open */
17788c2ecf20Sopenharmony_ci		fd = open(p, O_RDWR | O_NONBLOCK | O_CLOEXEC);
17798c2ecf20Sopenharmony_ci		if (fd < 0) {
17808c2ecf20Sopenharmony_ci			pr_err("Failed to open '%s'\n", p);
17818c2ecf20Sopenharmony_ci			ret = -errno;
17828c2ecf20Sopenharmony_ci			goto out_free;
17838c2ecf20Sopenharmony_ci		}
17848c2ecf20Sopenharmony_ci		*ctl_fd_ack = fd;
17858c2ecf20Sopenharmony_ci	}
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ciout_free:
17888c2ecf20Sopenharmony_ci	free(s);
17898c2ecf20Sopenharmony_ci	return ret;
17908c2ecf20Sopenharmony_ci}
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ciint evlist__parse_control(const char *str, int *ctl_fd, int *ctl_fd_ack, bool *ctl_fd_close)
17938c2ecf20Sopenharmony_ci{
17948c2ecf20Sopenharmony_ci	char *comma = NULL, *endptr = NULL;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	*ctl_fd_close = false;
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	if (strncmp(str, "fd:", 3))
17998c2ecf20Sopenharmony_ci		return evlist__parse_control_fifo(str, ctl_fd, ctl_fd_ack, ctl_fd_close);
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	*ctl_fd = strtoul(&str[3], &endptr, 0);
18028c2ecf20Sopenharmony_ci	if (endptr == &str[3])
18038c2ecf20Sopenharmony_ci		return -EINVAL;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	comma = strchr(str, ',');
18068c2ecf20Sopenharmony_ci	if (comma) {
18078c2ecf20Sopenharmony_ci		if (endptr != comma)
18088c2ecf20Sopenharmony_ci			return -EINVAL;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci		*ctl_fd_ack = strtoul(comma + 1, &endptr, 0);
18118c2ecf20Sopenharmony_ci		if (endptr == comma + 1 || *endptr != '\0')
18128c2ecf20Sopenharmony_ci			return -EINVAL;
18138c2ecf20Sopenharmony_ci	}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	return 0;
18168c2ecf20Sopenharmony_ci}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_civoid evlist__close_control(int ctl_fd, int ctl_fd_ack, bool *ctl_fd_close)
18198c2ecf20Sopenharmony_ci{
18208c2ecf20Sopenharmony_ci	if (*ctl_fd_close) {
18218c2ecf20Sopenharmony_ci		*ctl_fd_close = false;
18228c2ecf20Sopenharmony_ci		close(ctl_fd);
18238c2ecf20Sopenharmony_ci		if (ctl_fd_ack >= 0)
18248c2ecf20Sopenharmony_ci			close(ctl_fd_ack);
18258c2ecf20Sopenharmony_ci	}
18268c2ecf20Sopenharmony_ci}
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ciint evlist__initialize_ctlfd(struct evlist *evlist, int fd, int ack)
18298c2ecf20Sopenharmony_ci{
18308c2ecf20Sopenharmony_ci	if (fd == -1) {
18318c2ecf20Sopenharmony_ci		pr_debug("Control descriptor is not initialized\n");
18328c2ecf20Sopenharmony_ci		return 0;
18338c2ecf20Sopenharmony_ci	}
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	evlist->ctl_fd.pos = perf_evlist__add_pollfd(&evlist->core, fd, NULL, POLLIN,
18368c2ecf20Sopenharmony_ci						     fdarray_flag__nonfilterable);
18378c2ecf20Sopenharmony_ci	if (evlist->ctl_fd.pos < 0) {
18388c2ecf20Sopenharmony_ci		evlist->ctl_fd.pos = -1;
18398c2ecf20Sopenharmony_ci		pr_err("Failed to add ctl fd entry: %m\n");
18408c2ecf20Sopenharmony_ci		return -1;
18418c2ecf20Sopenharmony_ci	}
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	evlist->ctl_fd.fd = fd;
18448c2ecf20Sopenharmony_ci	evlist->ctl_fd.ack = ack;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci	return 0;
18478c2ecf20Sopenharmony_ci}
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_cibool evlist__ctlfd_initialized(struct evlist *evlist)
18508c2ecf20Sopenharmony_ci{
18518c2ecf20Sopenharmony_ci	return evlist->ctl_fd.pos >= 0;
18528c2ecf20Sopenharmony_ci}
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ciint evlist__finalize_ctlfd(struct evlist *evlist)
18558c2ecf20Sopenharmony_ci{
18568c2ecf20Sopenharmony_ci	struct pollfd *entries = evlist->core.pollfd.entries;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	if (!evlist__ctlfd_initialized(evlist))
18598c2ecf20Sopenharmony_ci		return 0;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	entries[evlist->ctl_fd.pos].fd = -1;
18628c2ecf20Sopenharmony_ci	entries[evlist->ctl_fd.pos].events = 0;
18638c2ecf20Sopenharmony_ci	entries[evlist->ctl_fd.pos].revents = 0;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	evlist->ctl_fd.pos = -1;
18668c2ecf20Sopenharmony_ci	evlist->ctl_fd.ack = -1;
18678c2ecf20Sopenharmony_ci	evlist->ctl_fd.fd = -1;
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	return 0;
18708c2ecf20Sopenharmony_ci}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_cistatic int evlist__ctlfd_recv(struct evlist *evlist, enum evlist_ctl_cmd *cmd,
18738c2ecf20Sopenharmony_ci			      char *cmd_data, size_t data_size)
18748c2ecf20Sopenharmony_ci{
18758c2ecf20Sopenharmony_ci	int err;
18768c2ecf20Sopenharmony_ci	char c;
18778c2ecf20Sopenharmony_ci	size_t bytes_read = 0;
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci	*cmd = EVLIST_CTL_CMD_UNSUPPORTED;
18808c2ecf20Sopenharmony_ci	memset(cmd_data, 0, data_size);
18818c2ecf20Sopenharmony_ci	data_size--;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	do {
18848c2ecf20Sopenharmony_ci		err = read(evlist->ctl_fd.fd, &c, 1);
18858c2ecf20Sopenharmony_ci		if (err > 0) {
18868c2ecf20Sopenharmony_ci			if (c == '\n' || c == '\0')
18878c2ecf20Sopenharmony_ci				break;
18888c2ecf20Sopenharmony_ci			cmd_data[bytes_read++] = c;
18898c2ecf20Sopenharmony_ci			if (bytes_read == data_size)
18908c2ecf20Sopenharmony_ci				break;
18918c2ecf20Sopenharmony_ci			continue;
18928c2ecf20Sopenharmony_ci		} else if (err == -1) {
18938c2ecf20Sopenharmony_ci			if (errno == EINTR)
18948c2ecf20Sopenharmony_ci				continue;
18958c2ecf20Sopenharmony_ci			if (errno == EAGAIN || errno == EWOULDBLOCK)
18968c2ecf20Sopenharmony_ci				err = 0;
18978c2ecf20Sopenharmony_ci			else
18988c2ecf20Sopenharmony_ci				pr_err("Failed to read from ctlfd %d: %m\n", evlist->ctl_fd.fd);
18998c2ecf20Sopenharmony_ci		}
19008c2ecf20Sopenharmony_ci		break;
19018c2ecf20Sopenharmony_ci	} while (1);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	pr_debug("Message from ctl_fd: \"%s%s\"\n", cmd_data,
19048c2ecf20Sopenharmony_ci		 bytes_read == data_size ? "" : c == '\n' ? "\\n" : "\\0");
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	if (bytes_read > 0) {
19078c2ecf20Sopenharmony_ci		if (!strncmp(cmd_data, EVLIST_CTL_CMD_ENABLE_TAG,
19088c2ecf20Sopenharmony_ci			     (sizeof(EVLIST_CTL_CMD_ENABLE_TAG)-1))) {
19098c2ecf20Sopenharmony_ci			*cmd = EVLIST_CTL_CMD_ENABLE;
19108c2ecf20Sopenharmony_ci		} else if (!strncmp(cmd_data, EVLIST_CTL_CMD_DISABLE_TAG,
19118c2ecf20Sopenharmony_ci				    (sizeof(EVLIST_CTL_CMD_DISABLE_TAG)-1))) {
19128c2ecf20Sopenharmony_ci			*cmd = EVLIST_CTL_CMD_DISABLE;
19138c2ecf20Sopenharmony_ci		} else if (!strncmp(cmd_data, EVLIST_CTL_CMD_SNAPSHOT_TAG,
19148c2ecf20Sopenharmony_ci				    (sizeof(EVLIST_CTL_CMD_SNAPSHOT_TAG)-1))) {
19158c2ecf20Sopenharmony_ci			*cmd = EVLIST_CTL_CMD_SNAPSHOT;
19168c2ecf20Sopenharmony_ci			pr_debug("is snapshot\n");
19178c2ecf20Sopenharmony_ci		}
19188c2ecf20Sopenharmony_ci	}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	return bytes_read ? (int)bytes_read : err;
19218c2ecf20Sopenharmony_ci}
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_ciint evlist__ctlfd_ack(struct evlist *evlist)
19248c2ecf20Sopenharmony_ci{
19258c2ecf20Sopenharmony_ci	int err;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	if (evlist->ctl_fd.ack == -1)
19288c2ecf20Sopenharmony_ci		return 0;
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	err = write(evlist->ctl_fd.ack, EVLIST_CTL_CMD_ACK_TAG,
19318c2ecf20Sopenharmony_ci		    sizeof(EVLIST_CTL_CMD_ACK_TAG));
19328c2ecf20Sopenharmony_ci	if (err == -1)
19338c2ecf20Sopenharmony_ci		pr_err("failed to write to ctl_ack_fd %d: %m\n", evlist->ctl_fd.ack);
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	return err;
19368c2ecf20Sopenharmony_ci}
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ciint evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd)
19398c2ecf20Sopenharmony_ci{
19408c2ecf20Sopenharmony_ci	int err = 0;
19418c2ecf20Sopenharmony_ci	char cmd_data[EVLIST_CTL_CMD_MAX_LEN];
19428c2ecf20Sopenharmony_ci	int ctlfd_pos = evlist->ctl_fd.pos;
19438c2ecf20Sopenharmony_ci	struct pollfd *entries = evlist->core.pollfd.entries;
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	if (!evlist__ctlfd_initialized(evlist) || !entries[ctlfd_pos].revents)
19468c2ecf20Sopenharmony_ci		return 0;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	if (entries[ctlfd_pos].revents & POLLIN) {
19498c2ecf20Sopenharmony_ci		err = evlist__ctlfd_recv(evlist, cmd, cmd_data,
19508c2ecf20Sopenharmony_ci					 EVLIST_CTL_CMD_MAX_LEN);
19518c2ecf20Sopenharmony_ci		if (err > 0) {
19528c2ecf20Sopenharmony_ci			switch (*cmd) {
19538c2ecf20Sopenharmony_ci			case EVLIST_CTL_CMD_ENABLE:
19548c2ecf20Sopenharmony_ci				evlist__enable(evlist);
19558c2ecf20Sopenharmony_ci				break;
19568c2ecf20Sopenharmony_ci			case EVLIST_CTL_CMD_DISABLE:
19578c2ecf20Sopenharmony_ci				evlist__disable(evlist);
19588c2ecf20Sopenharmony_ci				break;
19598c2ecf20Sopenharmony_ci			case EVLIST_CTL_CMD_SNAPSHOT:
19608c2ecf20Sopenharmony_ci				break;
19618c2ecf20Sopenharmony_ci			case EVLIST_CTL_CMD_ACK:
19628c2ecf20Sopenharmony_ci			case EVLIST_CTL_CMD_UNSUPPORTED:
19638c2ecf20Sopenharmony_ci			default:
19648c2ecf20Sopenharmony_ci				pr_debug("ctlfd: unsupported %d\n", *cmd);
19658c2ecf20Sopenharmony_ci				break;
19668c2ecf20Sopenharmony_ci			}
19678c2ecf20Sopenharmony_ci			if (!(*cmd == EVLIST_CTL_CMD_ACK || *cmd == EVLIST_CTL_CMD_UNSUPPORTED ||
19688c2ecf20Sopenharmony_ci			      *cmd == EVLIST_CTL_CMD_SNAPSHOT))
19698c2ecf20Sopenharmony_ci				evlist__ctlfd_ack(evlist);
19708c2ecf20Sopenharmony_ci		}
19718c2ecf20Sopenharmony_ci	}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	if (entries[ctlfd_pos].revents & (POLLHUP | POLLERR))
19748c2ecf20Sopenharmony_ci		evlist__finalize_ctlfd(evlist);
19758c2ecf20Sopenharmony_ci	else
19768c2ecf20Sopenharmony_ci		entries[ctlfd_pos].revents = 0;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	return err;
19798c2ecf20Sopenharmony_ci}
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_cistruct evsel *evlist__find_evsel(struct evlist *evlist, int idx)
19828c2ecf20Sopenharmony_ci{
19838c2ecf20Sopenharmony_ci	struct evsel *evsel;
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
19868c2ecf20Sopenharmony_ci		if (evsel->idx == idx)
19878c2ecf20Sopenharmony_ci			return evsel;
19888c2ecf20Sopenharmony_ci	}
19898c2ecf20Sopenharmony_ci	return NULL;
19908c2ecf20Sopenharmony_ci}
1991