xref: /openbmc/linux/tools/perf/builtin-record.c (revision 7954f71689f90cb2ae252d3923354d48071994bf)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
286470930SIngo Molnar /*
386470930SIngo Molnar  * builtin-record.c
486470930SIngo Molnar  *
586470930SIngo Molnar  * Builtin record command: Record the profile of a workload
686470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
786470930SIngo Molnar  * later analysis via perf report.
886470930SIngo Molnar  */
986470930SIngo Molnar #include "builtin.h"
1086470930SIngo Molnar 
116122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1386470930SIngo Molnar #include "util/parse-events.h"
1441840d21STaeung Song #include "util/config.h"
1586470930SIngo Molnar 
168f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
17f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
187c6a1c65SPeter Zijlstra #include "util/header.h"
1966e274f3SFrederic Weisbecker #include "util/event.h"
20361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2169aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
228f28827aSFrederic Weisbecker #include "util/debug.h"
23e0fcfb08SArnaldo Carvalho de Melo #include "util/mmap.h"
24aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h"
2594c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
28aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h"
29a12b51c4SPaul Mackerras #include "util/cpumap.h"
30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
31f5fc1412SJiri Olsa #include "util/data.h"
32bcc84ec6SStephane Eranian #include "util/perf_regs.h"
33ef149c25SAdrian Hunter #include "util/auxtrace.h"
3446bc29b9SAdrian Hunter #include "util/tsc.h"
35f00898f4SAndi Kleen #include "util/parse-branch-options.h"
36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3740c7d246SArnaldo Carvalho de Melo #include "util/perf_api_probe.h"
3871dc2326SWang Nan #include "util/llvm-utils.h"
398690a2a7SWang Nan #include "util/bpf-loader.h"
405f9cf599SWang Nan #include "util/trigger.h"
41a074865eSWang Nan #include "util/perf-hooks.h"
42f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
43ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h"
44c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4558db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
467b612e29SSong Liu #include "util/bpf-event.h"
47d99c22eaSStephane Eranian #include "util/util.h"
4870943490SStephane Eranian #include "util/pfm.h"
496953beb4SJiri Olsa #include "util/clockid.h"
50b53a0755SJin Yao #include "util/pmu-hybrid.h"
51b53a0755SJin Yao #include "util/evlist-hybrid.h"
52d8871ea7SWang Nan #include "asm/bug.h"
53c1a604dfSArnaldo Carvalho de Melo #include "perf.h"
547c6a1c65SPeter Zijlstra 
55a43783aeSArnaldo Carvalho de Melo #include <errno.h>
56fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
5767230479SArnaldo Carvalho de Melo #include <locale.h>
584208735dSArnaldo Carvalho de Melo #include <poll.h>
59d99c22eaSStephane Eranian #include <pthread.h>
6086470930SIngo Molnar #include <unistd.h>
6186470930SIngo Molnar #include <sched.h>
629607ad3aSArnaldo Carvalho de Melo #include <signal.h>
63da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
64da231338SAnand K Mistry #include <sys/eventfd.h>
65da231338SAnand K Mistry #endif
66a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
674208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
68eeb399b5SAdrian Hunter #include <sys/types.h>
69eeb399b5SAdrian Hunter #include <sys/stat.h>
70eeb399b5SAdrian Hunter #include <fcntl.h>
716ef81c55SMamatha Inamdar #include <linux/err.h>
728520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
730693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
74d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h>
758384a260SAlexey Budankov #include <linux/bitmap.h>
76d1e325cfSJiri Olsa #include <sys/time.h>
7778da39faSBernhard Rosenkraenzer 
781b43b704SJiri Olsa struct switch_output {
79dc0c6127SJiri Olsa 	bool		 enabled;
801b43b704SJiri Olsa 	bool		 signal;
81dc0c6127SJiri Olsa 	unsigned long	 size;
82bfacbe3bSJiri Olsa 	unsigned long	 time;
83cb4e1ebbSJiri Olsa 	const char	*str;
84cb4e1ebbSJiri Olsa 	bool		 set;
8503724b2eSAndi Kleen 	char		 **filenames;
8603724b2eSAndi Kleen 	int		 num_files;
8703724b2eSAndi Kleen 	int		 cur_file;
881b43b704SJiri Olsa };
891b43b704SJiri Olsa 
90*7954f716SAlexey Bayduraev struct thread_mask {
91*7954f716SAlexey Bayduraev 	struct mmap_cpu_mask	maps;
92*7954f716SAlexey Bayduraev 	struct mmap_cpu_mask	affinity;
93*7954f716SAlexey Bayduraev };
94*7954f716SAlexey Bayduraev 
958c6f45a7SArnaldo Carvalho de Melo struct record {
9645694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
97b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
98d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
998ceb41d7SJiri Olsa 	struct perf_data	data;
100ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
10163503dbaSJiri Olsa 	struct evlist	*evlist;
102d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
103bc477d79SArnaldo Carvalho de Melo 	struct evlist		*sb_evlist;
104899e5ffbSArnaldo Carvalho de Melo 	pthread_t		thread_id;
105d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
106899e5ffbSArnaldo Carvalho de Melo 	bool			switch_output_event_set;
107d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
108d2db9a98SWang Nan 	bool			no_buildid_set;
109d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
110d2db9a98SWang Nan 	bool			no_buildid_cache_set;
1116156681bSNamhyung Kim 	bool			buildid_all;
112e29386c8SJiri Olsa 	bool			buildid_mmap;
113ecfd7a9cSWang Nan 	bool			timestamp_filename;
11468588bafSJin Yao 	bool			timestamp_boundary;
1151b43b704SJiri Olsa 	struct switch_output	switch_output;
1169f065194SYang Shi 	unsigned long long	samples;
1178384a260SAlexey Budankov 	struct mmap_cpu_mask	affinity_mask;
1186d575816SJiwei Sun 	unsigned long		output_max_size;	/* = 0: unlimited */
1199bce13eaSJiri Olsa 	struct perf_debuginfod	debuginfod;
120*7954f716SAlexey Bayduraev 	int			nr_threads;
121*7954f716SAlexey Bayduraev 	struct thread_mask	*thread_masks;
1220f82ebc4SArnaldo Carvalho de Melo };
12386470930SIngo Molnar 
1246d575816SJiwei Sun static volatile int done;
1256d575816SJiwei Sun 
126dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
127dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
128dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
129dc0c6127SJiri Olsa 
1309d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
1319d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
1329d2ed645SAlexey Budankov };
1339d2ed645SAlexey Budankov 
134dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
135dc0c6127SJiri Olsa {
136dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
137dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
138dc0c6127SJiri Olsa }
139dc0c6127SJiri Olsa 
140dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
141dc0c6127SJiri Olsa {
142dc0c6127SJiri Olsa 	return rec->switch_output.size &&
143dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
144dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
145dc0c6127SJiri Olsa }
146dc0c6127SJiri Olsa 
147bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
148bfacbe3bSJiri Olsa {
149bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
150bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
151bfacbe3bSJiri Olsa }
152bfacbe3bSJiri Olsa 
1536d575816SJiwei Sun static bool record__output_max_size_exceeded(struct record *rec)
1546d575816SJiwei Sun {
1556d575816SJiwei Sun 	return rec->output_max_size &&
1566d575816SJiwei Sun 	       (rec->bytes_written >= rec->output_max_size);
1576d575816SJiwei Sun }
1586d575816SJiwei Sun 
159a5830532SJiri Olsa static int record__write(struct record *rec, struct mmap *map __maybe_unused,
160ded2b8feSJiri Olsa 			 void *bf, size_t size)
161f5970550SPeter Zijlstra {
162ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
163ded2b8feSJiri Olsa 
164ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1654f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1668d3eca20SDavid Ahern 		return -1;
1678d3eca20SDavid Ahern 	}
168f5970550SPeter Zijlstra 
169cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
170dc0c6127SJiri Olsa 
1716d575816SJiwei Sun 	if (record__output_max_size_exceeded(rec) && !done) {
1726d575816SJiwei Sun 		fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB),"
1736d575816SJiwei Sun 				" stopping session ]\n",
1746d575816SJiwei Sun 				rec->bytes_written >> 10);
1756d575816SJiwei Sun 		done = 1;
1766d575816SJiwei Sun 	}
1776d575816SJiwei Sun 
178dc0c6127SJiri Olsa 	if (switch_output_size(rec))
179dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
180dc0c6127SJiri Olsa 
1818d3eca20SDavid Ahern 	return 0;
182f5970550SPeter Zijlstra }
183f5970550SPeter Zijlstra 
184ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec);
185ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec);
1865d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
1875d7f4116SAlexey Budankov 			    void *src, size_t src_size);
1885d7f4116SAlexey Budankov 
189d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
190d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
191d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
192d3d1af6fSAlexey Budankov {
193d3d1af6fSAlexey Budankov 	int rc;
194d3d1af6fSAlexey Budankov 
195d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
196d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
197d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
198d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
199d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
200d3d1af6fSAlexey Budankov 
201d3d1af6fSAlexey Budankov 	do {
202d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
203d3d1af6fSAlexey Budankov 		if (rc == 0) {
204d3d1af6fSAlexey Budankov 			break;
205d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
206d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
207d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
208d3d1af6fSAlexey Budankov 			break;
209d3d1af6fSAlexey Budankov 		}
210d3d1af6fSAlexey Budankov 	} while (1);
211d3d1af6fSAlexey Budankov 
212d3d1af6fSAlexey Budankov 	return rc;
213d3d1af6fSAlexey Budankov }
214d3d1af6fSAlexey Budankov 
215a5830532SJiri Olsa static int record__aio_complete(struct mmap *md, struct aiocb *cblock)
216d3d1af6fSAlexey Budankov {
217d3d1af6fSAlexey Budankov 	void *rem_buf;
218d3d1af6fSAlexey Budankov 	off_t rem_off;
219d3d1af6fSAlexey Budankov 	size_t rem_size;
220d3d1af6fSAlexey Budankov 	int rc, aio_errno;
221d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
222d3d1af6fSAlexey Budankov 
223d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
224d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
225d3d1af6fSAlexey Budankov 		return 0;
226d3d1af6fSAlexey Budankov 
227d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
228d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
229d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
230d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
231d3d1af6fSAlexey Budankov 		written = 0;
232d3d1af6fSAlexey Budankov 	}
233d3d1af6fSAlexey Budankov 
234d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
235d3d1af6fSAlexey Budankov 
236d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
237d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
238d3d1af6fSAlexey Budankov 		/*
239ef781128SAlexey Budankov 		 * md->refcount is incremented in record__aio_pushfn() for
240ef781128SAlexey Budankov 		 * every aio write request started in record__aio_push() so
241ef781128SAlexey Budankov 		 * decrement it because the request is now complete.
242d3d1af6fSAlexey Budankov 		 */
24380e53d11SJiri Olsa 		perf_mmap__put(&md->core);
244d3d1af6fSAlexey Budankov 		rc = 1;
245d3d1af6fSAlexey Budankov 	} else {
246d3d1af6fSAlexey Budankov 		/*
247d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
248d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
249d3d1af6fSAlexey Budankov 		 * chunk at once.
250d3d1af6fSAlexey Budankov 		 */
251d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
252d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
253d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
254d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
255d3d1af6fSAlexey Budankov 		rc = 0;
256d3d1af6fSAlexey Budankov 	}
257d3d1af6fSAlexey Budankov 
258d3d1af6fSAlexey Budankov 	return rc;
259d3d1af6fSAlexey Budankov }
260d3d1af6fSAlexey Budankov 
261a5830532SJiri Olsa static int record__aio_sync(struct mmap *md, bool sync_all)
262d3d1af6fSAlexey Budankov {
26393f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
26493f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
265d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
26693f20c0fSAlexey Budankov 	int i, do_suspend;
267d3d1af6fSAlexey Budankov 
268d3d1af6fSAlexey Budankov 	do {
26993f20c0fSAlexey Budankov 		do_suspend = 0;
27093f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
27193f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
27293f20c0fSAlexey Budankov 				if (sync_all)
27393f20c0fSAlexey Budankov 					aiocb[i] = NULL;
27493f20c0fSAlexey Budankov 				else
27593f20c0fSAlexey Budankov 					return i;
27693f20c0fSAlexey Budankov 			} else {
27793f20c0fSAlexey Budankov 				/*
27893f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
27993f20c0fSAlexey Budankov 				 * so it has to be waited before the
28093f20c0fSAlexey Budankov 				 * next allocation.
28193f20c0fSAlexey Budankov 				 */
28293f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
28393f20c0fSAlexey Budankov 				do_suspend = 1;
28493f20c0fSAlexey Budankov 			}
28593f20c0fSAlexey Budankov 		}
28693f20c0fSAlexey Budankov 		if (!do_suspend)
28793f20c0fSAlexey Budankov 			return -1;
288d3d1af6fSAlexey Budankov 
28993f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
290d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
291d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
292d3d1af6fSAlexey Budankov 		}
293d3d1af6fSAlexey Budankov 	} while (1);
294d3d1af6fSAlexey Budankov }
295d3d1af6fSAlexey Budankov 
296ef781128SAlexey Budankov struct record_aio {
297ef781128SAlexey Budankov 	struct record	*rec;
298ef781128SAlexey Budankov 	void		*data;
299ef781128SAlexey Budankov 	size_t		size;
300ef781128SAlexey Budankov };
301ef781128SAlexey Budankov 
302a5830532SJiri Olsa static int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size)
303d3d1af6fSAlexey Budankov {
304ef781128SAlexey Budankov 	struct record_aio *aio = to;
305ef781128SAlexey Budankov 
306ef781128SAlexey Budankov 	/*
307547740f7SJiri Olsa 	 * map->core.base data pointed by buf is copied into free map->aio.data[] buffer
308ef781128SAlexey Budankov 	 * to release space in the kernel buffer as fast as possible, calling
309ef781128SAlexey Budankov 	 * perf_mmap__consume() from perf_mmap__push() function.
310ef781128SAlexey Budankov 	 *
311ef781128SAlexey Budankov 	 * That lets the kernel to proceed with storing more profiling data into
312ef781128SAlexey Budankov 	 * the kernel buffer earlier than other per-cpu kernel buffers are handled.
313ef781128SAlexey Budankov 	 *
314ef781128SAlexey Budankov 	 * Coping can be done in two steps in case the chunk of profiling data
315ef781128SAlexey Budankov 	 * crosses the upper bound of the kernel buffer. In this case we first move
316ef781128SAlexey Budankov 	 * part of data from map->start till the upper bound and then the reminder
317ef781128SAlexey Budankov 	 * from the beginning of the kernel buffer till the end of the data chunk.
318ef781128SAlexey Budankov 	 */
319ef781128SAlexey Budankov 
320ef781128SAlexey Budankov 	if (record__comp_enabled(aio->rec)) {
321ef781128SAlexey Budankov 		size = zstd_compress(aio->rec->session, aio->data + aio->size,
322bf59b305SJiri Olsa 				     mmap__mmap_len(map) - aio->size,
323ef781128SAlexey Budankov 				     buf, size);
324ef781128SAlexey Budankov 	} else {
325ef781128SAlexey Budankov 		memcpy(aio->data + aio->size, buf, size);
326ef781128SAlexey Budankov 	}
327ef781128SAlexey Budankov 
328ef781128SAlexey Budankov 	if (!aio->size) {
329ef781128SAlexey Budankov 		/*
330ef781128SAlexey Budankov 		 * Increment map->refcount to guard map->aio.data[] buffer
331ef781128SAlexey Budankov 		 * from premature deallocation because map object can be
332ef781128SAlexey Budankov 		 * released earlier than aio write request started on
333ef781128SAlexey Budankov 		 * map->aio.data[] buffer is complete.
334ef781128SAlexey Budankov 		 *
335ef781128SAlexey Budankov 		 * perf_mmap__put() is done at record__aio_complete()
336ef781128SAlexey Budankov 		 * after started aio request completion or at record__aio_push()
337ef781128SAlexey Budankov 		 * if the request failed to start.
338ef781128SAlexey Budankov 		 */
339e75710f0SJiri Olsa 		perf_mmap__get(&map->core);
340ef781128SAlexey Budankov 	}
341ef781128SAlexey Budankov 
342ef781128SAlexey Budankov 	aio->size += size;
343ef781128SAlexey Budankov 
344ef781128SAlexey Budankov 	return size;
345ef781128SAlexey Budankov }
346ef781128SAlexey Budankov 
347a5830532SJiri Olsa static int record__aio_push(struct record *rec, struct mmap *map, off_t *off)
348ef781128SAlexey Budankov {
349ef781128SAlexey Budankov 	int ret, idx;
350ef781128SAlexey Budankov 	int trace_fd = rec->session->data->file.fd;
351ef781128SAlexey Budankov 	struct record_aio aio = { .rec = rec, .size = 0 };
352ef781128SAlexey Budankov 
353ef781128SAlexey Budankov 	/*
354ef781128SAlexey Budankov 	 * Call record__aio_sync() to wait till map->aio.data[] buffer
355ef781128SAlexey Budankov 	 * becomes available after previous aio write operation.
356ef781128SAlexey Budankov 	 */
357ef781128SAlexey Budankov 
358ef781128SAlexey Budankov 	idx = record__aio_sync(map, false);
359ef781128SAlexey Budankov 	aio.data = map->aio.data[idx];
360ef781128SAlexey Budankov 	ret = perf_mmap__push(map, &aio, record__aio_pushfn);
361ef781128SAlexey Budankov 	if (ret != 0) /* ret > 0 - no data, ret < 0 - error */
362ef781128SAlexey Budankov 		return ret;
363d3d1af6fSAlexey Budankov 
364d3d1af6fSAlexey Budankov 	rec->samples++;
365ef781128SAlexey Budankov 	ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off);
366d3d1af6fSAlexey Budankov 	if (!ret) {
367ef781128SAlexey Budankov 		*off += aio.size;
368ef781128SAlexey Budankov 		rec->bytes_written += aio.size;
369d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
370d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
371ef781128SAlexey Budankov 	} else {
372ef781128SAlexey Budankov 		/*
373ef781128SAlexey Budankov 		 * Decrement map->refcount incremented in record__aio_pushfn()
374ef781128SAlexey Budankov 		 * back if record__aio_write() operation failed to start, otherwise
375ef781128SAlexey Budankov 		 * map->refcount is decremented in record__aio_complete() after
376ef781128SAlexey Budankov 		 * aio write operation finishes successfully.
377ef781128SAlexey Budankov 		 */
37880e53d11SJiri Olsa 		perf_mmap__put(&map->core);
379d3d1af6fSAlexey Budankov 	}
380d3d1af6fSAlexey Budankov 
381d3d1af6fSAlexey Budankov 	return ret;
382d3d1af6fSAlexey Budankov }
383d3d1af6fSAlexey Budankov 
384d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
385d3d1af6fSAlexey Budankov {
386d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
387d3d1af6fSAlexey Budankov }
388d3d1af6fSAlexey Budankov 
389d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
390d3d1af6fSAlexey Budankov {
391d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
392d3d1af6fSAlexey Budankov }
393d3d1af6fSAlexey Budankov 
394d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
395d3d1af6fSAlexey Budankov {
396d3d1af6fSAlexey Budankov 	int i;
39763503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
398a5830532SJiri Olsa 	struct mmap *maps = evlist->mmap;
399d3d1af6fSAlexey Budankov 
400ef781128SAlexey Budankov 	if (!record__aio_enabled(rec))
401d3d1af6fSAlexey Budankov 		return;
402d3d1af6fSAlexey Budankov 
403c976ee11SJiri Olsa 	for (i = 0; i < evlist->core.nr_mmaps; i++) {
404a5830532SJiri Olsa 		struct mmap *map = &maps[i];
405d3d1af6fSAlexey Budankov 
406547740f7SJiri Olsa 		if (map->core.base)
40793f20c0fSAlexey Budankov 			record__aio_sync(map, true);
408d3d1af6fSAlexey Budankov 	}
409d3d1af6fSAlexey Budankov }
410d3d1af6fSAlexey Budankov 
411d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
41293f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
413d3d1af6fSAlexey Budankov 
414d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
41593f20c0fSAlexey Budankov 			     const char *str,
416d3d1af6fSAlexey Budankov 			     int unset)
417d3d1af6fSAlexey Budankov {
418d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
419d3d1af6fSAlexey Budankov 
42093f20c0fSAlexey Budankov 	if (unset) {
421d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
42293f20c0fSAlexey Budankov 	} else {
42393f20c0fSAlexey Budankov 		if (str)
42493f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
42593f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
426d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
42793f20c0fSAlexey Budankov 	}
428d3d1af6fSAlexey Budankov 
429d3d1af6fSAlexey Budankov 	return 0;
430d3d1af6fSAlexey Budankov }
431d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
43293f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
43393f20c0fSAlexey Budankov 
434a5830532SJiri Olsa static int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused,
435ef781128SAlexey Budankov 			    off_t *off __maybe_unused)
436d3d1af6fSAlexey Budankov {
437d3d1af6fSAlexey Budankov 	return -1;
438d3d1af6fSAlexey Budankov }
439d3d1af6fSAlexey Budankov 
440d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
441d3d1af6fSAlexey Budankov {
442d3d1af6fSAlexey Budankov 	return -1;
443d3d1af6fSAlexey Budankov }
444d3d1af6fSAlexey Budankov 
445d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
446d3d1af6fSAlexey Budankov {
447d3d1af6fSAlexey Budankov }
448d3d1af6fSAlexey Budankov 
449d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
450d3d1af6fSAlexey Budankov {
451d3d1af6fSAlexey Budankov }
452d3d1af6fSAlexey Budankov #endif
453d3d1af6fSAlexey Budankov 
454d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
455d3d1af6fSAlexey Budankov {
456d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
457d3d1af6fSAlexey Budankov }
458d3d1af6fSAlexey Budankov 
459470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
460470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
461470530bbSAlexey Budankov 				    const char *str,
462470530bbSAlexey Budankov 				    int unset)
463470530bbSAlexey Budankov {
464470530bbSAlexey Budankov 	int flush_max;
465470530bbSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
466470530bbSAlexey Budankov 	static struct parse_tag tags[] = {
467470530bbSAlexey Budankov 			{ .tag  = 'B', .mult = 1       },
468470530bbSAlexey Budankov 			{ .tag  = 'K', .mult = 1 << 10 },
469470530bbSAlexey Budankov 			{ .tag  = 'M', .mult = 1 << 20 },
470470530bbSAlexey Budankov 			{ .tag  = 'G', .mult = 1 << 30 },
471470530bbSAlexey Budankov 			{ .tag  = 0 },
472470530bbSAlexey Budankov 	};
473470530bbSAlexey Budankov 
474470530bbSAlexey Budankov 	if (unset)
475470530bbSAlexey Budankov 		return 0;
476470530bbSAlexey Budankov 
477470530bbSAlexey Budankov 	if (str) {
478470530bbSAlexey Budankov 		opts->mmap_flush = parse_tag_value(str, tags);
479470530bbSAlexey Budankov 		if (opts->mmap_flush == (int)-1)
480470530bbSAlexey Budankov 			opts->mmap_flush = strtol(str, NULL, 0);
481470530bbSAlexey Budankov 	}
482470530bbSAlexey Budankov 
483470530bbSAlexey Budankov 	if (!opts->mmap_flush)
484470530bbSAlexey Budankov 		opts->mmap_flush = MMAP_FLUSH_DEFAULT;
485470530bbSAlexey Budankov 
4869521b5f2SJiri Olsa 	flush_max = evlist__mmap_size(opts->mmap_pages);
487470530bbSAlexey Budankov 	flush_max /= 4;
488470530bbSAlexey Budankov 	if (opts->mmap_flush > flush_max)
489470530bbSAlexey Budankov 		opts->mmap_flush = flush_max;
490470530bbSAlexey Budankov 
491470530bbSAlexey Budankov 	return 0;
492470530bbSAlexey Budankov }
493470530bbSAlexey Budankov 
494504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
495504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1;
496504c1ad1SAlexey Budankov 
497504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset)
498504c1ad1SAlexey Budankov {
499504c1ad1SAlexey Budankov 	struct record_opts *opts = opt->value;
500504c1ad1SAlexey Budankov 
501504c1ad1SAlexey Budankov 	if (unset) {
502504c1ad1SAlexey Budankov 		opts->comp_level = 0;
503504c1ad1SAlexey Budankov 	} else {
504504c1ad1SAlexey Budankov 		if (str)
505504c1ad1SAlexey Budankov 			opts->comp_level = strtol(str, NULL, 0);
506504c1ad1SAlexey Budankov 		if (!opts->comp_level)
507504c1ad1SAlexey Budankov 			opts->comp_level = comp_level_default;
508504c1ad1SAlexey Budankov 	}
509504c1ad1SAlexey Budankov 
510504c1ad1SAlexey Budankov 	return 0;
511504c1ad1SAlexey Budankov }
512504c1ad1SAlexey Budankov #endif
51351255a8aSAlexey Budankov static unsigned int comp_level_max = 22;
51451255a8aSAlexey Budankov 
51542e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec)
51642e1fd80SAlexey Budankov {
51742e1fd80SAlexey Budankov 	return rec->opts.comp_level > 0;
51842e1fd80SAlexey Budankov }
51942e1fd80SAlexey Budankov 
52045694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
521d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
5221d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
5231d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
524234fbbf5SArnaldo Carvalho de Melo {
5258c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
526ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
527234fbbf5SArnaldo Carvalho de Melo }
528234fbbf5SArnaldo Carvalho de Melo 
529d99c22eaSStephane Eranian static int process_locked_synthesized_event(struct perf_tool *tool,
530d99c22eaSStephane Eranian 				     union perf_event *event,
531d99c22eaSStephane Eranian 				     struct perf_sample *sample __maybe_unused,
532d99c22eaSStephane Eranian 				     struct machine *machine __maybe_unused)
533d99c22eaSStephane Eranian {
534d99c22eaSStephane Eranian 	static pthread_mutex_t synth_lock = PTHREAD_MUTEX_INITIALIZER;
535d99c22eaSStephane Eranian 	int ret;
536d99c22eaSStephane Eranian 
537d99c22eaSStephane Eranian 	pthread_mutex_lock(&synth_lock);
538d99c22eaSStephane Eranian 	ret = process_synthesized_event(tool, event, sample, machine);
539d99c22eaSStephane Eranian 	pthread_mutex_unlock(&synth_lock);
540d99c22eaSStephane Eranian 	return ret;
541d99c22eaSStephane Eranian }
542d99c22eaSStephane Eranian 
543a5830532SJiri Olsa static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size)
544d37f1586SArnaldo Carvalho de Melo {
545d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
546d37f1586SArnaldo Carvalho de Melo 
5475d7f4116SAlexey Budankov 	if (record__comp_enabled(rec)) {
548bf59b305SJiri Olsa 		size = zstd_compress(rec->session, map->data, mmap__mmap_len(map), bf, size);
5495d7f4116SAlexey Budankov 		bf   = map->data;
5505d7f4116SAlexey Budankov 	}
5515d7f4116SAlexey Budankov 
552d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
553ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
554d37f1586SArnaldo Carvalho de Melo }
555d37f1586SArnaldo Carvalho de Melo 
5562dd6d8a1SAdrian Hunter static volatile int signr = -1;
5572dd6d8a1SAdrian Hunter static volatile int child_finished;
558da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
559da231338SAnand K Mistry static int done_fd = -1;
560da231338SAnand K Mistry #endif
561c0bdc1c4SWang Nan 
5622dd6d8a1SAdrian Hunter static void sig_handler(int sig)
5632dd6d8a1SAdrian Hunter {
5642dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
5652dd6d8a1SAdrian Hunter 		child_finished = 1;
5662dd6d8a1SAdrian Hunter 	else
5672dd6d8a1SAdrian Hunter 		signr = sig;
5682dd6d8a1SAdrian Hunter 
5692dd6d8a1SAdrian Hunter 	done = 1;
570da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
571da231338SAnand K Mistry {
572da231338SAnand K Mistry 	u64 tmp = 1;
573da231338SAnand K Mistry 	/*
574da231338SAnand K Mistry 	 * It is possible for this signal handler to run after done is checked
575da231338SAnand K Mistry 	 * in the main loop, but before the perf counter fds are polled. If this
576da231338SAnand K Mistry 	 * happens, the poll() will continue to wait even though done is set,
577da231338SAnand K Mistry 	 * and will only break out if either another signal is received, or the
578da231338SAnand K Mistry 	 * counters are ready for read. To ensure the poll() doesn't sleep when
579da231338SAnand K Mistry 	 * done is set, use an eventfd (done_fd) to wake up the poll().
580da231338SAnand K Mistry 	 */
581da231338SAnand K Mistry 	if (write(done_fd, &tmp, sizeof(tmp)) < 0)
582da231338SAnand K Mistry 		pr_err("failed to signal wakeup fd, error: %m\n");
583da231338SAnand K Mistry }
584da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT
5852dd6d8a1SAdrian Hunter }
5862dd6d8a1SAdrian Hunter 
587a074865eSWang Nan static void sigsegv_handler(int sig)
588a074865eSWang Nan {
589a074865eSWang Nan 	perf_hooks__recover();
590a074865eSWang Nan 	sighandler_dump_stack(sig);
591a074865eSWang Nan }
592a074865eSWang Nan 
5932dd6d8a1SAdrian Hunter static void record__sig_exit(void)
5942dd6d8a1SAdrian Hunter {
5952dd6d8a1SAdrian Hunter 	if (signr == -1)
5962dd6d8a1SAdrian Hunter 		return;
5972dd6d8a1SAdrian Hunter 
5982dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
5992dd6d8a1SAdrian Hunter 	raise(signr);
6002dd6d8a1SAdrian Hunter }
6012dd6d8a1SAdrian Hunter 
602e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
603e31f0d01SAdrian Hunter 
604ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
605a5830532SJiri Olsa 				    struct mmap *map,
606ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
607ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
608ef149c25SAdrian Hunter {
609ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
6108ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
611ef149c25SAdrian Hunter 	size_t padding;
612ef149c25SAdrian Hunter 	u8 pad[8] = {0};
613ef149c25SAdrian Hunter 
61446e201efSAdrian Hunter 	if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) {
61599fa2984SAdrian Hunter 		off_t file_offset;
6168ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
61799fa2984SAdrian Hunter 		int err;
61899fa2984SAdrian Hunter 
61999fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
62099fa2984SAdrian Hunter 		if (file_offset == -1)
62199fa2984SAdrian Hunter 			return -1;
62299fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
62399fa2984SAdrian Hunter 						     event, file_offset);
62499fa2984SAdrian Hunter 		if (err)
62599fa2984SAdrian Hunter 			return err;
62699fa2984SAdrian Hunter 	}
62799fa2984SAdrian Hunter 
628ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
629ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
630ef149c25SAdrian Hunter 	if (padding)
631ef149c25SAdrian Hunter 		padding = 8 - padding;
632ef149c25SAdrian Hunter 
633ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
634ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
635ef149c25SAdrian Hunter 	if (len2)
636ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
637ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
638ef149c25SAdrian Hunter 
639ef149c25SAdrian Hunter 	return 0;
640ef149c25SAdrian Hunter }
641ef149c25SAdrian Hunter 
642ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
643a5830532SJiri Olsa 				      struct mmap *map)
644ef149c25SAdrian Hunter {
645ef149c25SAdrian Hunter 	int ret;
646ef149c25SAdrian Hunter 
647e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
648ef149c25SAdrian Hunter 				  record__process_auxtrace);
649ef149c25SAdrian Hunter 	if (ret < 0)
650ef149c25SAdrian Hunter 		return ret;
651ef149c25SAdrian Hunter 
652ef149c25SAdrian Hunter 	if (ret)
653ef149c25SAdrian Hunter 		rec->samples++;
654ef149c25SAdrian Hunter 
655ef149c25SAdrian Hunter 	return 0;
656ef149c25SAdrian Hunter }
657ef149c25SAdrian Hunter 
6582dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
659a5830532SJiri Olsa 					       struct mmap *map)
6602dd6d8a1SAdrian Hunter {
6612dd6d8a1SAdrian Hunter 	int ret;
6622dd6d8a1SAdrian Hunter 
663e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
6642dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
6652dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
6662dd6d8a1SAdrian Hunter 	if (ret < 0)
6672dd6d8a1SAdrian Hunter 		return ret;
6682dd6d8a1SAdrian Hunter 
6692dd6d8a1SAdrian Hunter 	if (ret)
6702dd6d8a1SAdrian Hunter 		rec->samples++;
6712dd6d8a1SAdrian Hunter 
6722dd6d8a1SAdrian Hunter 	return 0;
6732dd6d8a1SAdrian Hunter }
6742dd6d8a1SAdrian Hunter 
6752dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
6762dd6d8a1SAdrian Hunter {
6772dd6d8a1SAdrian Hunter 	int i;
6782dd6d8a1SAdrian Hunter 	int rc = 0;
6792dd6d8a1SAdrian Hunter 
680c976ee11SJiri Olsa 	for (i = 0; i < rec->evlist->core.nr_mmaps; i++) {
681a5830532SJiri Olsa 		struct mmap *map = &rec->evlist->mmap[i];
6822dd6d8a1SAdrian Hunter 
683e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
6842dd6d8a1SAdrian Hunter 			continue;
6852dd6d8a1SAdrian Hunter 
686e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
6872dd6d8a1SAdrian Hunter 			rc = -1;
6882dd6d8a1SAdrian Hunter 			goto out;
6892dd6d8a1SAdrian Hunter 		}
6902dd6d8a1SAdrian Hunter 	}
6912dd6d8a1SAdrian Hunter out:
6922dd6d8a1SAdrian Hunter 	return rc;
6932dd6d8a1SAdrian Hunter }
6942dd6d8a1SAdrian Hunter 
695ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
6962dd6d8a1SAdrian Hunter {
6972dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
6982dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
6995f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
7002dd6d8a1SAdrian Hunter 	} else {
701ce7b0e42SAlexander Shishkin 		if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
7025f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
7035f9cf599SWang Nan 		else
7045f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
7052dd6d8a1SAdrian Hunter 	}
7062dd6d8a1SAdrian Hunter }
7072dd6d8a1SAdrian Hunter 
708ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec)
709ce7b0e42SAlexander Shishkin {
710ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
711ce7b0e42SAlexander Shishkin 		return 0;
712ce7b0e42SAlexander Shishkin 
713ce7b0e42SAlexander Shishkin 	if (!auxtrace_record__snapshot_started &&
714ce7b0e42SAlexander Shishkin 	    auxtrace_record__snapshot_start(rec->itr))
715ce7b0e42SAlexander Shishkin 		return -1;
716ce7b0e42SAlexander Shishkin 
717ce7b0e42SAlexander Shishkin 	record__read_auxtrace_snapshot(rec, true);
718ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
719ce7b0e42SAlexander Shishkin 		return -1;
720ce7b0e42SAlexander Shishkin 
721ce7b0e42SAlexander Shishkin 	return 0;
722ce7b0e42SAlexander Shishkin }
723ce7b0e42SAlexander Shishkin 
7244b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
7254b5ea3bdSAdrian Hunter {
7264b5ea3bdSAdrian Hunter 	int err;
7274b5ea3bdSAdrian Hunter 
7284b5ea3bdSAdrian Hunter 	if (!rec->itr) {
7294b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
7304b5ea3bdSAdrian Hunter 		if (err)
7314b5ea3bdSAdrian Hunter 			return err;
7324b5ea3bdSAdrian Hunter 	}
7334b5ea3bdSAdrian Hunter 
7344b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
7354b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
7364b5ea3bdSAdrian Hunter 	if (err)
7374b5ea3bdSAdrian Hunter 		return err;
7384b5ea3bdSAdrian Hunter 
739c0a6de06SAdrian Hunter 	err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts,
740c0a6de06SAdrian Hunter 					    rec->opts.auxtrace_sample_opts);
741c0a6de06SAdrian Hunter 	if (err)
742c0a6de06SAdrian Hunter 		return err;
743c0a6de06SAdrian Hunter 
744d58b3f7eSAdrian Hunter 	auxtrace_regroup_aux_output(rec->evlist);
745d58b3f7eSAdrian Hunter 
7464b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
7474b5ea3bdSAdrian Hunter }
7484b5ea3bdSAdrian Hunter 
749e31f0d01SAdrian Hunter #else
750e31f0d01SAdrian Hunter 
751e31f0d01SAdrian Hunter static inline
752e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
753a5830532SJiri Olsa 			       struct mmap *map __maybe_unused)
754e31f0d01SAdrian Hunter {
755e31f0d01SAdrian Hunter 	return 0;
756e31f0d01SAdrian Hunter }
757e31f0d01SAdrian Hunter 
7582dd6d8a1SAdrian Hunter static inline
759ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
760ce7b0e42SAlexander Shishkin 				    bool on_exit __maybe_unused)
7612dd6d8a1SAdrian Hunter {
7622dd6d8a1SAdrian Hunter }
7632dd6d8a1SAdrian Hunter 
7642dd6d8a1SAdrian Hunter static inline
7652dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
7662dd6d8a1SAdrian Hunter {
7672dd6d8a1SAdrian Hunter 	return 0;
7682dd6d8a1SAdrian Hunter }
7692dd6d8a1SAdrian Hunter 
770ce7b0e42SAlexander Shishkin static inline
771ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
772ce7b0e42SAlexander Shishkin {
773ce7b0e42SAlexander Shishkin 	return 0;
774ce7b0e42SAlexander Shishkin }
775ce7b0e42SAlexander Shishkin 
7764b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
7774b5ea3bdSAdrian Hunter {
7784b5ea3bdSAdrian Hunter 	return 0;
7794b5ea3bdSAdrian Hunter }
7804b5ea3bdSAdrian Hunter 
781e31f0d01SAdrian Hunter #endif
782e31f0d01SAdrian Hunter 
783246eba8eSAdrian Hunter static int record__config_text_poke(struct evlist *evlist)
784246eba8eSAdrian Hunter {
785246eba8eSAdrian Hunter 	struct evsel *evsel;
786246eba8eSAdrian Hunter 	int err;
787246eba8eSAdrian Hunter 
788246eba8eSAdrian Hunter 	/* Nothing to do if text poke is already configured */
789246eba8eSAdrian Hunter 	evlist__for_each_entry(evlist, evsel) {
790246eba8eSAdrian Hunter 		if (evsel->core.attr.text_poke)
791246eba8eSAdrian Hunter 			return 0;
792246eba8eSAdrian Hunter 	}
793246eba8eSAdrian Hunter 
794246eba8eSAdrian Hunter 	err = parse_events(evlist, "dummy:u", NULL);
795246eba8eSAdrian Hunter 	if (err)
796246eba8eSAdrian Hunter 		return err;
797246eba8eSAdrian Hunter 
798246eba8eSAdrian Hunter 	evsel = evlist__last(evlist);
799246eba8eSAdrian Hunter 
800246eba8eSAdrian Hunter 	evsel->core.attr.freq = 0;
801246eba8eSAdrian Hunter 	evsel->core.attr.sample_period = 1;
802246eba8eSAdrian Hunter 	evsel->core.attr.text_poke = 1;
803246eba8eSAdrian Hunter 	evsel->core.attr.ksymbol = 1;
804246eba8eSAdrian Hunter 
805246eba8eSAdrian Hunter 	evsel->core.system_wide = true;
806246eba8eSAdrian Hunter 	evsel->no_aux_samples = true;
807246eba8eSAdrian Hunter 	evsel->immediate = true;
808246eba8eSAdrian Hunter 
809246eba8eSAdrian Hunter 	/* Text poke must be collected on all CPUs */
810246eba8eSAdrian Hunter 	perf_cpu_map__put(evsel->core.own_cpus);
811246eba8eSAdrian Hunter 	evsel->core.own_cpus = perf_cpu_map__new(NULL);
812246eba8eSAdrian Hunter 	perf_cpu_map__put(evsel->core.cpus);
813246eba8eSAdrian Hunter 	evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus);
814246eba8eSAdrian Hunter 
815246eba8eSAdrian Hunter 	evsel__set_sample_bit(evsel, TIME);
816246eba8eSAdrian Hunter 
817246eba8eSAdrian Hunter 	return 0;
818246eba8eSAdrian Hunter }
819246eba8eSAdrian Hunter 
820eeb399b5SAdrian Hunter static bool record__kcore_readable(struct machine *machine)
821eeb399b5SAdrian Hunter {
822eeb399b5SAdrian Hunter 	char kcore[PATH_MAX];
823eeb399b5SAdrian Hunter 	int fd;
824eeb399b5SAdrian Hunter 
825eeb399b5SAdrian Hunter 	scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir);
826eeb399b5SAdrian Hunter 
827eeb399b5SAdrian Hunter 	fd = open(kcore, O_RDONLY);
828eeb399b5SAdrian Hunter 	if (fd < 0)
829eeb399b5SAdrian Hunter 		return false;
830eeb399b5SAdrian Hunter 
831eeb399b5SAdrian Hunter 	close(fd);
832eeb399b5SAdrian Hunter 
833eeb399b5SAdrian Hunter 	return true;
834eeb399b5SAdrian Hunter }
835eeb399b5SAdrian Hunter 
836eeb399b5SAdrian Hunter static int record__kcore_copy(struct machine *machine, struct perf_data *data)
837eeb399b5SAdrian Hunter {
838eeb399b5SAdrian Hunter 	char from_dir[PATH_MAX];
839eeb399b5SAdrian Hunter 	char kcore_dir[PATH_MAX];
840eeb399b5SAdrian Hunter 	int ret;
841eeb399b5SAdrian Hunter 
842eeb399b5SAdrian Hunter 	snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir);
843eeb399b5SAdrian Hunter 
844eeb399b5SAdrian Hunter 	ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir));
845eeb399b5SAdrian Hunter 	if (ret)
846eeb399b5SAdrian Hunter 		return ret;
847eeb399b5SAdrian Hunter 
848eeb399b5SAdrian Hunter 	return kcore_copy(from_dir, kcore_dir);
849eeb399b5SAdrian Hunter }
850eeb399b5SAdrian Hunter 
851cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
85263503dbaSJiri Olsa 			       struct evlist *evlist)
853cda57a8cSWang Nan {
854cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
855c0a6de06SAdrian Hunter 	bool auxtrace_overwrite = opts->auxtrace_snapshot_mode ||
856c0a6de06SAdrian Hunter 				  opts->auxtrace_sample_mode;
857cda57a8cSWang Nan 	char msg[512];
858cda57a8cSWang Nan 
859f13de660SAlexey Budankov 	if (opts->affinity != PERF_AFFINITY_SYS)
860f13de660SAlexey Budankov 		cpu__setup_cpunode_map();
861f13de660SAlexey Budankov 
8629521b5f2SJiri Olsa 	if (evlist__mmap_ex(evlist, opts->mmap_pages,
863cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
864c0a6de06SAdrian Hunter 				 auxtrace_overwrite,
865470530bbSAlexey Budankov 				 opts->nr_cblocks, opts->affinity,
86651255a8aSAlexey Budankov 				 opts->mmap_flush, opts->comp_level) < 0) {
867cda57a8cSWang Nan 		if (errno == EPERM) {
868cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
869cda57a8cSWang Nan 			       "Consider increasing "
870cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
871cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
872cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
873cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
874cda57a8cSWang Nan 			return -errno;
875cda57a8cSWang Nan 		} else {
876cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
877c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
878cda57a8cSWang Nan 			if (errno)
879cda57a8cSWang Nan 				return -errno;
880cda57a8cSWang Nan 			else
881cda57a8cSWang Nan 				return -EINVAL;
882cda57a8cSWang Nan 		}
883cda57a8cSWang Nan 	}
884cda57a8cSWang Nan 	return 0;
885cda57a8cSWang Nan }
886cda57a8cSWang Nan 
887cda57a8cSWang Nan static int record__mmap(struct record *rec)
888cda57a8cSWang Nan {
889cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
890cda57a8cSWang Nan }
891cda57a8cSWang Nan 
8928c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
893dd7927f4SArnaldo Carvalho de Melo {
894d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
89532dcd021SJiri Olsa 	struct evsel *pos;
89663503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
897d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
898b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
8998d3eca20SDavid Ahern 	int rc = 0;
900dd7927f4SArnaldo Carvalho de Melo 
901d3dbf43cSArnaldo Carvalho de Melo 	/*
902b91e5492SKan Liang 	 * For initial_delay, system wide or a hybrid system, we need to add a
903b91e5492SKan Liang 	 * dummy event so that we can track PERF_RECORD_MMAP to cover the delay
904b91e5492SKan Liang 	 * of waiting or event synthesis.
905d3dbf43cSArnaldo Carvalho de Melo 	 */
906b91e5492SKan Liang 	if (opts->initial_delay || target__has_cpu(&opts->target) ||
907b91e5492SKan Liang 	    perf_pmu__has_hybrid()) {
908e80db255SArnaldo Carvalho de Melo 		pos = evlist__get_tracking_event(evlist);
909442ad225SAdrian Hunter 		if (!evsel__is_dummy_event(pos)) {
910442ad225SAdrian Hunter 			/* Set up dummy event. */
911e251abeeSArnaldo Carvalho de Melo 			if (evlist__add_dummy(evlist))
912d3dbf43cSArnaldo Carvalho de Melo 				return -ENOMEM;
913515dbe48SJiri Olsa 			pos = evlist__last(evlist);
914e80db255SArnaldo Carvalho de Melo 			evlist__set_tracking_event(evlist, pos);
915442ad225SAdrian Hunter 		}
916442ad225SAdrian Hunter 
9170a892c1cSIan Rogers 		/*
9180a892c1cSIan Rogers 		 * Enable the dummy event when the process is forked for
9190a892c1cSIan Rogers 		 * initial_delay, immediately for system wide.
9200a892c1cSIan Rogers 		 */
921bb07d62eSNamhyung Kim 		if (opts->initial_delay && !pos->immediate &&
922bb07d62eSNamhyung Kim 		    !target__has_cpu(&opts->target))
9231fc632ceSJiri Olsa 			pos->core.attr.enable_on_exec = 1;
9240a892c1cSIan Rogers 		else
9250a892c1cSIan Rogers 			pos->immediate = 1;
926d3dbf43cSArnaldo Carvalho de Melo 	}
927d3dbf43cSArnaldo Carvalho de Melo 
92878e1bc25SArnaldo Carvalho de Melo 	evlist__config(evlist, opts, &callchain_param);
929cac21425SJiri Olsa 
930e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
9313da297a6SIngo Molnar try_again:
932af663bd0SJiri Olsa 		if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
933ae430892SArnaldo Carvalho de Melo 			if (evsel__fallback(pos, errno, msg, sizeof(msg))) {
934bb963e16SNamhyung Kim 				if (verbose > 0)
935c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
9363da297a6SIngo Molnar 				goto try_again;
9373da297a6SIngo Molnar 			}
938cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
939fba7c866SJiri Olsa 			    pos->core.leader != &pos->core &&
940cf99ad14SAndi Kleen 			    pos->weak_group) {
94164b4778bSArnaldo Carvalho de Melo 			        pos = evlist__reset_weak_group(evlist, pos, true);
942cf99ad14SAndi Kleen 				goto try_again;
943cf99ad14SAndi Kleen 			}
94456e52e85SArnaldo Carvalho de Melo 			rc = -errno;
9452bb72dbbSArnaldo Carvalho de Melo 			evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg));
94656e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
9478d3eca20SDavid Ahern 			goto out;
9487c6a1c65SPeter Zijlstra 		}
949bfd8f72cSAndi Kleen 
950bfd8f72cSAndi Kleen 		pos->supported = true;
9517c6a1c65SPeter Zijlstra 	}
9527c6a1c65SPeter Zijlstra 
95378e1bc25SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) {
954c8b567c8SArnaldo Carvalho de Melo 		pr_warning(
955c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
956c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
957c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
958c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
959c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
960c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
961c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
962c8b567c8SArnaldo Carvalho de Melo 	}
963c8b567c8SArnaldo Carvalho de Melo 
96424bf91a7SArnaldo Carvalho de Melo 	if (evlist__apply_filters(evlist, &pos)) {
96562d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
9668ab2e96dSArnaldo Carvalho de Melo 			pos->filter, evsel__name(pos), errno,
967c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
9688d3eca20SDavid Ahern 		rc = -1;
9698d3eca20SDavid Ahern 		goto out;
9700a102479SFrederic Weisbecker 	}
9710a102479SFrederic Weisbecker 
972cda57a8cSWang Nan 	rc = record__mmap(rec);
973cda57a8cSWang Nan 	if (rc)
9748d3eca20SDavid Ahern 		goto out;
9750a27d7f9SArnaldo Carvalho de Melo 
976a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
9777b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
9788d3eca20SDavid Ahern out:
9798d3eca20SDavid Ahern 	return rc;
980a91e5431SArnaldo Carvalho de Melo }
981a91e5431SArnaldo Carvalho de Melo 
98266286ed3SAdrian Hunter static void set_timestamp_boundary(struct record *rec, u64 sample_time)
98366286ed3SAdrian Hunter {
98466286ed3SAdrian Hunter 	if (rec->evlist->first_sample_time == 0)
98566286ed3SAdrian Hunter 		rec->evlist->first_sample_time = sample_time;
98666286ed3SAdrian Hunter 
98766286ed3SAdrian Hunter 	if (sample_time)
98866286ed3SAdrian Hunter 		rec->evlist->last_sample_time = sample_time;
98966286ed3SAdrian Hunter }
99066286ed3SAdrian Hunter 
991e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
992e3d59112SNamhyung Kim 				union perf_event *event,
993e3d59112SNamhyung Kim 				struct perf_sample *sample,
99432dcd021SJiri Olsa 				struct evsel *evsel,
995e3d59112SNamhyung Kim 				struct machine *machine)
996e3d59112SNamhyung Kim {
997e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
998e3d59112SNamhyung Kim 
99966286ed3SAdrian Hunter 	set_timestamp_boundary(rec, sample->time);
100068588bafSJin Yao 
100168588bafSJin Yao 	if (rec->buildid_all)
100268588bafSJin Yao 		return 0;
100368588bafSJin Yao 
100468588bafSJin Yao 	rec->samples++;
1005e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
1006e3d59112SNamhyung Kim }
1007e3d59112SNamhyung Kim 
10088c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
10096122e4e4SArnaldo Carvalho de Melo {
1010f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
10116122e4e4SArnaldo Carvalho de Melo 
101245112e89SJiri Olsa 	if (perf_data__size(&rec->data) == 0)
10139f591fd7SArnaldo Carvalho de Melo 		return 0;
10149f591fd7SArnaldo Carvalho de Melo 
101500dc8657SNamhyung Kim 	/*
101600dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
101700dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
101800dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
101900dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
102000dc8657SNamhyung Kim 	 *
102100dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
102200dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
102300dc8657SNamhyung Kim 	 */
102400dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
102500dc8657SNamhyung Kim 
10266156681bSNamhyung Kim 	/*
10276156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
102868588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
102968588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
103068588bafSJin Yao 	 * first/last samples.
10316156681bSNamhyung Kim 	 */
103268588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
10336156681bSNamhyung Kim 		rec->tool.sample = NULL;
10346156681bSNamhyung Kim 
1035b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
10366122e4e4SArnaldo Carvalho de Melo }
10376122e4e4SArnaldo Carvalho de Melo 
10388115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
1039a1645ce1SZhang, Yanmin {
1040a1645ce1SZhang, Yanmin 	int err;
104145694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
1042a1645ce1SZhang, Yanmin 	/*
1043a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
1044a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
1045a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
1046a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
1047a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
1048a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
1049a1645ce1SZhang, Yanmin 	 */
105045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
1051743eb868SArnaldo Carvalho de Melo 					     machine);
1052a1645ce1SZhang, Yanmin 	if (err < 0)
1053a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
105423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
1055a1645ce1SZhang, Yanmin 
1056a1645ce1SZhang, Yanmin 	/*
1057a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
1058a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
1059a1645ce1SZhang, Yanmin 	 */
106045694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
10610ae617beSAdrian Hunter 						 machine);
1062a1645ce1SZhang, Yanmin 	if (err < 0)
1063a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
106423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
1065a1645ce1SZhang, Yanmin }
1066a1645ce1SZhang, Yanmin 
106798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
106898402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
106998402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
107098402807SFrederic Weisbecker };
107198402807SFrederic Weisbecker 
1072a5830532SJiri Olsa static void record__adjust_affinity(struct record *rec, struct mmap *map)
1073f13de660SAlexey Budankov {
1074f13de660SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS &&
10758384a260SAlexey Budankov 	    !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits,
10768384a260SAlexey Budankov 			  rec->affinity_mask.nbits)) {
10778384a260SAlexey Budankov 		bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits);
10788384a260SAlexey Budankov 		bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits,
10798384a260SAlexey Budankov 			  map->affinity_mask.bits, rec->affinity_mask.nbits);
10808384a260SAlexey Budankov 		sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask),
10818384a260SAlexey Budankov 				  (cpu_set_t *)rec->affinity_mask.bits);
10828384a260SAlexey Budankov 		if (verbose == 2)
10838384a260SAlexey Budankov 			mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread");
1084f13de660SAlexey Budankov 	}
1085f13de660SAlexey Budankov }
1086f13de660SAlexey Budankov 
10875d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment)
10885d7f4116SAlexey Budankov {
108972932371SJiri Olsa 	struct perf_record_compressed *event = record;
10905d7f4116SAlexey Budankov 	size_t size = sizeof(*event);
10915d7f4116SAlexey Budankov 
10925d7f4116SAlexey Budankov 	if (increment) {
10935d7f4116SAlexey Budankov 		event->header.size += increment;
10945d7f4116SAlexey Budankov 		return increment;
10955d7f4116SAlexey Budankov 	}
10965d7f4116SAlexey Budankov 
10975d7f4116SAlexey Budankov 	event->header.type = PERF_RECORD_COMPRESSED;
10985d7f4116SAlexey Budankov 	event->header.size = size;
10995d7f4116SAlexey Budankov 
11005d7f4116SAlexey Budankov 	return size;
11015d7f4116SAlexey Budankov }
11025d7f4116SAlexey Budankov 
11035d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
11045d7f4116SAlexey Budankov 			    void *src, size_t src_size)
11055d7f4116SAlexey Budankov {
11065d7f4116SAlexey Budankov 	size_t compressed;
110772932371SJiri Olsa 	size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1;
11085d7f4116SAlexey Budankov 
11095d7f4116SAlexey Budankov 	compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size,
11105d7f4116SAlexey Budankov 						     max_record_size, process_comp_header);
11115d7f4116SAlexey Budankov 
11125d7f4116SAlexey Budankov 	session->bytes_transferred += src_size;
11135d7f4116SAlexey Budankov 	session->bytes_compressed  += compressed;
11145d7f4116SAlexey Budankov 
11155d7f4116SAlexey Budankov 	return compressed;
11165d7f4116SAlexey Budankov }
11175d7f4116SAlexey Budankov 
111863503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
1119470530bbSAlexey Budankov 				    bool overwrite, bool synch)
112098402807SFrederic Weisbecker {
1121dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
11220e2e63ddSPeter Zijlstra 	int i;
11238d3eca20SDavid Ahern 	int rc = 0;
1124a5830532SJiri Olsa 	struct mmap *maps;
1125d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
1126ef781128SAlexey Budankov 	off_t off = 0;
112798402807SFrederic Weisbecker 
1128cb21686bSWang Nan 	if (!evlist)
1129cb21686bSWang Nan 		return 0;
1130ef149c25SAdrian Hunter 
11310b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
1132a4ea0ec4SWang Nan 	if (!maps)
1133a4ea0ec4SWang Nan 		return 0;
1134cb21686bSWang Nan 
11350b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
113654cc54deSWang Nan 		return 0;
113754cc54deSWang Nan 
1138d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
1139d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
1140d3d1af6fSAlexey Budankov 
1141c976ee11SJiri Olsa 	for (i = 0; i < evlist->core.nr_mmaps; i++) {
1142470530bbSAlexey Budankov 		u64 flush = 0;
1143a5830532SJiri Olsa 		struct mmap *map = &maps[i];
1144a4ea0ec4SWang Nan 
1145547740f7SJiri Olsa 		if (map->core.base) {
1146f13de660SAlexey Budankov 			record__adjust_affinity(rec, map);
1147470530bbSAlexey Budankov 			if (synch) {
114865aa2e6bSJiri Olsa 				flush = map->core.flush;
114965aa2e6bSJiri Olsa 				map->core.flush = 1;
1150470530bbSAlexey Budankov 			}
1151d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
1152ef781128SAlexey Budankov 				if (perf_mmap__push(map, rec, record__pushfn) < 0) {
1153470530bbSAlexey Budankov 					if (synch)
115465aa2e6bSJiri Olsa 						map->core.flush = flush;
11558d3eca20SDavid Ahern 					rc = -1;
11568d3eca20SDavid Ahern 					goto out;
11578d3eca20SDavid Ahern 				}
1158d3d1af6fSAlexey Budankov 			} else {
1159ef781128SAlexey Budankov 				if (record__aio_push(rec, map, &off) < 0) {
1160d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
1161470530bbSAlexey Budankov 					if (synch)
116265aa2e6bSJiri Olsa 						map->core.flush = flush;
1163d3d1af6fSAlexey Budankov 					rc = -1;
1164d3d1af6fSAlexey Budankov 					goto out;
1165d3d1af6fSAlexey Budankov 				}
1166d3d1af6fSAlexey Budankov 			}
1167470530bbSAlexey Budankov 			if (synch)
116865aa2e6bSJiri Olsa 				map->core.flush = flush;
11698d3eca20SDavid Ahern 		}
1170ef149c25SAdrian Hunter 
1171e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
1172c0a6de06SAdrian Hunter 		    !rec->opts.auxtrace_sample_mode &&
1173e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
1174ef149c25SAdrian Hunter 			rc = -1;
1175ef149c25SAdrian Hunter 			goto out;
1176ef149c25SAdrian Hunter 		}
117798402807SFrederic Weisbecker 	}
117898402807SFrederic Weisbecker 
1179d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
1180d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
1181d3d1af6fSAlexey Budankov 
1182dcabb507SJiri Olsa 	/*
1183dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
1184dcabb507SJiri Olsa 	 * at least one event.
1185dcabb507SJiri Olsa 	 */
1186dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
1187ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
11888d3eca20SDavid Ahern 
11890b72d69aSWang Nan 	if (overwrite)
1190ade9d208SArnaldo Carvalho de Melo 		evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
11918d3eca20SDavid Ahern out:
11928d3eca20SDavid Ahern 	return rc;
119398402807SFrederic Weisbecker }
119498402807SFrederic Weisbecker 
1195470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
1196cb21686bSWang Nan {
1197cb21686bSWang Nan 	int err;
1198cb21686bSWang Nan 
1199470530bbSAlexey Budankov 	err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
1200cb21686bSWang Nan 	if (err)
1201cb21686bSWang Nan 		return err;
1202cb21686bSWang Nan 
1203470530bbSAlexey Budankov 	return record__mmap_read_evlist(rec, rec->evlist, true, synch);
1204cb21686bSWang Nan }
1205cb21686bSWang Nan 
12068c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
120757706abcSDavid Ahern {
120857706abcSDavid Ahern 	struct perf_session *session = rec->session;
120957706abcSDavid Ahern 	int feat;
121057706abcSDavid Ahern 
121157706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
121257706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
121357706abcSDavid Ahern 
121457706abcSDavid Ahern 	if (rec->no_buildid)
121557706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
121657706abcSDavid Ahern 
1217ce9036a6SJiri Olsa 	if (!have_tracepoints(&rec->evlist->core.entries))
121857706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
121957706abcSDavid Ahern 
122057706abcSDavid Ahern 	if (!rec->opts.branch_stack)
122157706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1222ef149c25SAdrian Hunter 
1223ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
1224ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1225ffa517adSJiri Olsa 
1226cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
1227cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
1228cf790516SAlexey Budankov 
1229d1e325cfSJiri Olsa 	if (!rec->opts.use_clockid)
1230d1e325cfSJiri Olsa 		perf_header__clear_feat(&session->header, HEADER_CLOCK_DATA);
1231d1e325cfSJiri Olsa 
1232258031c0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
123342e1fd80SAlexey Budankov 	if (!record__comp_enabled(rec))
123442e1fd80SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
1235258031c0SJiri Olsa 
1236ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
123757706abcSDavid Ahern }
123857706abcSDavid Ahern 
1239e1ab48baSWang Nan static void
1240e1ab48baSWang Nan record__finish_output(struct record *rec)
1241e1ab48baSWang Nan {
12428ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
12438ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1244e1ab48baSWang Nan 
12458ceb41d7SJiri Olsa 	if (data->is_pipe)
1246e1ab48baSWang Nan 		return;
1247e1ab48baSWang Nan 
1248e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
124945112e89SJiri Olsa 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
1250e1ab48baSWang Nan 
1251e1ab48baSWang Nan 	if (!rec->no_buildid) {
1252e1ab48baSWang Nan 		process_buildids(rec);
1253e1ab48baSWang Nan 
1254e1ab48baSWang Nan 		if (rec->buildid_all)
1255e1ab48baSWang Nan 			dsos__hit_all(rec->session);
1256e1ab48baSWang Nan 	}
1257e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
1258e1ab48baSWang Nan 
1259e1ab48baSWang Nan 	return;
1260e1ab48baSWang Nan }
1261e1ab48baSWang Nan 
12624ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
1263be7b0c9eSWang Nan {
12649d6aae72SArnaldo Carvalho de Melo 	int err;
12659749b90eSJiri Olsa 	struct perf_thread_map *thread_map;
126641b740b6SNamhyung Kim 	bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP;
1267be7b0c9eSWang Nan 
12684ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
12694ea648aeSWang Nan 		return 0;
12704ea648aeSWang Nan 
12719d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
12729d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
12739d6aae72SArnaldo Carvalho de Melo 		return -1;
12749d6aae72SArnaldo Carvalho de Melo 
12759d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
1276be7b0c9eSWang Nan 						 process_synthesized_event,
1277be7b0c9eSWang Nan 						 &rec->session->machines.host,
127841b740b6SNamhyung Kim 						 needs_mmap,
12793fcb10e4SMark Drayton 						 rec->opts.sample_address);
12807836e52eSJiri Olsa 	perf_thread_map__put(thread_map);
12819d6aae72SArnaldo Carvalho de Melo 	return err;
1282be7b0c9eSWang Nan }
1283be7b0c9eSWang Nan 
12844ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
12853c1cb7e3SWang Nan 
1286ecfd7a9cSWang Nan static int
1287ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
1288ecfd7a9cSWang Nan {
12898ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1290ecfd7a9cSWang Nan 	int fd, err;
129103724b2eSAndi Kleen 	char *new_filename;
1292ecfd7a9cSWang Nan 
1293ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
1294ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
1295ecfd7a9cSWang Nan 
1296d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1297d3d1af6fSAlexey Budankov 
12984ea648aeSWang Nan 	record__synthesize(rec, true);
12994ea648aeSWang Nan 	if (target__none(&rec->opts.target))
13004ea648aeSWang Nan 		record__synthesize_workload(rec, true);
13014ea648aeSWang Nan 
1302ecfd7a9cSWang Nan 	rec->samples = 0;
1303ecfd7a9cSWang Nan 	record__finish_output(rec);
1304ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
1305ecfd7a9cSWang Nan 	if (err) {
1306ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
1307ecfd7a9cSWang Nan 		return -EINVAL;
1308ecfd7a9cSWang Nan 	}
1309ecfd7a9cSWang Nan 
13108ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
1311ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
131203724b2eSAndi Kleen 				    at_exit, &new_filename);
1313ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
1314ecfd7a9cSWang Nan 		rec->bytes_written = 0;
1315ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
1316ecfd7a9cSWang Nan 	}
1317ecfd7a9cSWang Nan 
1318ecfd7a9cSWang Nan 	if (!quiet)
1319ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
13202d4f2799SJiri Olsa 			data->path, timestamp);
13213c1cb7e3SWang Nan 
132203724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
132303724b2eSAndi Kleen 		int n = rec->switch_output.cur_file + 1;
132403724b2eSAndi Kleen 
132503724b2eSAndi Kleen 		if (n >= rec->switch_output.num_files)
132603724b2eSAndi Kleen 			n = 0;
132703724b2eSAndi Kleen 		rec->switch_output.cur_file = n;
132803724b2eSAndi Kleen 		if (rec->switch_output.filenames[n]) {
132903724b2eSAndi Kleen 			remove(rec->switch_output.filenames[n]);
1330d8f9da24SArnaldo Carvalho de Melo 			zfree(&rec->switch_output.filenames[n]);
133103724b2eSAndi Kleen 		}
133203724b2eSAndi Kleen 		rec->switch_output.filenames[n] = new_filename;
133303724b2eSAndi Kleen 	} else {
133403724b2eSAndi Kleen 		free(new_filename);
133503724b2eSAndi Kleen 	}
133603724b2eSAndi Kleen 
13373c1cb7e3SWang Nan 	/* Output tracking events */
1338be7b0c9eSWang Nan 	if (!at_exit) {
13394ea648aeSWang Nan 		record__synthesize(rec, false);
13403c1cb7e3SWang Nan 
1341be7b0c9eSWang Nan 		/*
1342be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
1343be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
1344be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
1345be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
1346be7b0c9eSWang Nan 		 * contain map and comm information.
1347be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
1348be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
1349be7b0c9eSWang Nan 		 */
1350be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
13514ea648aeSWang Nan 			record__synthesize_workload(rec, false);
1352be7b0c9eSWang Nan 	}
1353ecfd7a9cSWang Nan 	return fd;
1354ecfd7a9cSWang Nan }
1355ecfd7a9cSWang Nan 
1356f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
1357f33cbe72SArnaldo Carvalho de Melo 
1358f33cbe72SArnaldo Carvalho de Melo /*
13597b392ef0SArnaldo Carvalho de Melo  * evlist__prepare_workload will send a SIGUSR1
1360f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
1361f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
1362f33cbe72SArnaldo Carvalho de Melo  */
136345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
136445604710SNamhyung Kim 					siginfo_t *info,
1365f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
1366f33cbe72SArnaldo Carvalho de Melo {
1367f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
1368f33cbe72SArnaldo Carvalho de Melo 	done = 1;
1369f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
1370f33cbe72SArnaldo Carvalho de Melo }
1371f33cbe72SArnaldo Carvalho de Melo 
13722dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1373bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
13742dd6d8a1SAdrian Hunter 
1375db0ea13cSArnaldo Carvalho de Melo static const struct perf_event_mmap_page *evlist__pick_pc(struct evlist *evlist)
1376ee667f94SWang Nan {
1377b2cb615dSWang Nan 	if (evlist) {
1378547740f7SJiri Olsa 		if (evlist->mmap && evlist->mmap[0].core.base)
1379547740f7SJiri Olsa 			return evlist->mmap[0].core.base;
1380547740f7SJiri Olsa 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base)
1381547740f7SJiri Olsa 			return evlist->overwrite_mmap[0].core.base;
1382b2cb615dSWang Nan 	}
1383ee667f94SWang Nan 	return NULL;
1384ee667f94SWang Nan }
1385ee667f94SWang Nan 
1386c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1387c45628b0SWang Nan {
1388db0ea13cSArnaldo Carvalho de Melo 	const struct perf_event_mmap_page *pc = evlist__pick_pc(rec->evlist);
1389ee667f94SWang Nan 	if (pc)
1390ee667f94SWang Nan 		return pc;
1391c45628b0SWang Nan 	return NULL;
1392c45628b0SWang Nan }
1393c45628b0SWang Nan 
13944ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1395c45c86ebSWang Nan {
1396c45c86ebSWang Nan 	struct perf_session *session = rec->session;
1397c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
13988ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1399c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
1400c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
1401c45c86ebSWang Nan 	int err = 0;
1402d99c22eaSStephane Eranian 	event_op f = process_synthesized_event;
1403c45c86ebSWang Nan 
14044ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
14054ea648aeSWang Nan 		return 0;
14064ea648aeSWang Nan 
14078ceb41d7SJiri Olsa 	if (data->is_pipe) {
1408c3a057dcSNamhyung Kim 		err = perf_event__synthesize_for_pipe(tool, session, data,
1409c45c86ebSWang Nan 						      process_synthesized_event);
1410c3a057dcSNamhyung Kim 		if (err < 0)
1411c45c86ebSWang Nan 			goto out;
1412c45c86ebSWang Nan 
1413c45c86ebSWang Nan 		rec->bytes_written += err;
1414c45c86ebSWang Nan 	}
1415c45c86ebSWang Nan 
1416c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
141746bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
141846bc29b9SAdrian Hunter 	if (err)
141946bc29b9SAdrian Hunter 		goto out;
142046bc29b9SAdrian Hunter 
1421c0a6de06SAdrian Hunter 	/* Synthesize id_index before auxtrace_info */
142261750473SAdrian Hunter 	if (rec->opts.auxtrace_sample_mode || rec->opts.full_auxtrace) {
1423c0a6de06SAdrian Hunter 		err = perf_event__synthesize_id_index(tool,
1424c0a6de06SAdrian Hunter 						      process_synthesized_event,
1425c0a6de06SAdrian Hunter 						      session->evlist, machine);
1426c0a6de06SAdrian Hunter 		if (err)
1427c0a6de06SAdrian Hunter 			goto out;
1428c0a6de06SAdrian Hunter 	}
1429c0a6de06SAdrian Hunter 
1430c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1431c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1432c45c86ebSWang Nan 					session, process_synthesized_event);
1433c45c86ebSWang Nan 		if (err)
1434c45c86ebSWang Nan 			goto out;
1435c45c86ebSWang Nan 	}
1436c45c86ebSWang Nan 
143778e1bc25SArnaldo Carvalho de Melo 	if (!evlist__exclude_kernel(rec->evlist)) {
1438c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1439c45c86ebSWang Nan 							 machine);
1440c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1441c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1442c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1443c45c86ebSWang Nan 
1444c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1445c45c86ebSWang Nan 						     machine);
1446c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1447c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1448c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
14496c443954SArnaldo Carvalho de Melo 	}
1450c45c86ebSWang Nan 
1451c45c86ebSWang Nan 	if (perf_guest) {
1452c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1453c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1454c45c86ebSWang Nan 	}
1455c45c86ebSWang Nan 
1456bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1457bfd8f72cSAndi Kleen 						rec->evlist,
1458bfd8f72cSAndi Kleen 						process_synthesized_event,
1459bfd8f72cSAndi Kleen 						data->is_pipe);
1460bfd8f72cSAndi Kleen 	if (err)
1461bfd8f72cSAndi Kleen 		goto out;
1462bfd8f72cSAndi Kleen 
146303617c22SJiri Olsa 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads,
1464373565d2SAndi Kleen 						 process_synthesized_event,
1465373565d2SAndi Kleen 						NULL);
1466373565d2SAndi Kleen 	if (err < 0) {
1467373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1468373565d2SAndi Kleen 		return err;
1469373565d2SAndi Kleen 	}
1470373565d2SAndi Kleen 
1471f72f901dSJiri Olsa 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus,
1472373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1473373565d2SAndi Kleen 	if (err < 0) {
1474373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1475373565d2SAndi Kleen 		return err;
1476373565d2SAndi Kleen 	}
1477373565d2SAndi Kleen 
1478e5416950SSong Liu 	err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
14797b612e29SSong Liu 						machine, opts);
14807b612e29SSong Liu 	if (err < 0)
14817b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
14827b612e29SSong Liu 
148341b740b6SNamhyung Kim 	if (rec->opts.synth & PERF_SYNTH_CGROUP) {
1484ab64069fSNamhyung Kim 		err = perf_event__synthesize_cgroups(tool, process_synthesized_event,
1485ab64069fSNamhyung Kim 						     machine);
1486ab64069fSNamhyung Kim 		if (err < 0)
1487ab64069fSNamhyung Kim 			pr_warning("Couldn't synthesize cgroup events.\n");
148841b740b6SNamhyung Kim 	}
1489ab64069fSNamhyung Kim 
1490d99c22eaSStephane Eranian 	if (rec->opts.nr_threads_synthesize > 1) {
1491d99c22eaSStephane Eranian 		perf_set_multithreaded();
1492d99c22eaSStephane Eranian 		f = process_locked_synthesized_event;
1493d99c22eaSStephane Eranian 	}
1494d99c22eaSStephane Eranian 
149541b740b6SNamhyung Kim 	if (rec->opts.synth & PERF_SYNTH_TASK) {
149641b740b6SNamhyung Kim 		bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP;
149741b740b6SNamhyung Kim 
149884111b9cSNamhyung Kim 		err = __machine__synthesize_threads(machine, tool, &opts->target,
149984111b9cSNamhyung Kim 						    rec->evlist->core.threads,
150041b740b6SNamhyung Kim 						    f, needs_mmap, opts->sample_address,
1501d99c22eaSStephane Eranian 						    rec->opts.nr_threads_synthesize);
150241b740b6SNamhyung Kim 	}
1503d99c22eaSStephane Eranian 
1504d99c22eaSStephane Eranian 	if (rec->opts.nr_threads_synthesize > 1)
1505d99c22eaSStephane Eranian 		perf_set_singlethreaded();
1506d99c22eaSStephane Eranian 
1507c45c86ebSWang Nan out:
1508c45c86ebSWang Nan 	return err;
1509c45c86ebSWang Nan }
1510c45c86ebSWang Nan 
1511899e5ffbSArnaldo Carvalho de Melo static int record__process_signal_event(union perf_event *event __maybe_unused, void *data)
1512899e5ffbSArnaldo Carvalho de Melo {
1513899e5ffbSArnaldo Carvalho de Melo 	struct record *rec = data;
1514899e5ffbSArnaldo Carvalho de Melo 	pthread_kill(rec->thread_id, SIGUSR2);
1515899e5ffbSArnaldo Carvalho de Melo 	return 0;
1516899e5ffbSArnaldo Carvalho de Melo }
1517899e5ffbSArnaldo Carvalho de Melo 
151823cbb41cSArnaldo Carvalho de Melo static int record__setup_sb_evlist(struct record *rec)
151923cbb41cSArnaldo Carvalho de Melo {
152023cbb41cSArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
152123cbb41cSArnaldo Carvalho de Melo 
152223cbb41cSArnaldo Carvalho de Melo 	if (rec->sb_evlist != NULL) {
152323cbb41cSArnaldo Carvalho de Melo 		/*
152423cbb41cSArnaldo Carvalho de Melo 		 * We get here if --switch-output-event populated the
152523cbb41cSArnaldo Carvalho de Melo 		 * sb_evlist, so associate a callback that will send a SIGUSR2
152623cbb41cSArnaldo Carvalho de Melo 		 * to the main thread.
152723cbb41cSArnaldo Carvalho de Melo 		 */
152823cbb41cSArnaldo Carvalho de Melo 		evlist__set_cb(rec->sb_evlist, record__process_signal_event, rec);
152923cbb41cSArnaldo Carvalho de Melo 		rec->thread_id = pthread_self();
153023cbb41cSArnaldo Carvalho de Melo 	}
15311101c872SJin Yao #ifdef HAVE_LIBBPF_SUPPORT
153223cbb41cSArnaldo Carvalho de Melo 	if (!opts->no_bpf_event) {
153323cbb41cSArnaldo Carvalho de Melo 		if (rec->sb_evlist == NULL) {
153423cbb41cSArnaldo Carvalho de Melo 			rec->sb_evlist = evlist__new();
153523cbb41cSArnaldo Carvalho de Melo 
153623cbb41cSArnaldo Carvalho de Melo 			if (rec->sb_evlist == NULL) {
153723cbb41cSArnaldo Carvalho de Melo 				pr_err("Couldn't create side band evlist.\n.");
153823cbb41cSArnaldo Carvalho de Melo 				return -1;
153923cbb41cSArnaldo Carvalho de Melo 			}
154023cbb41cSArnaldo Carvalho de Melo 		}
154123cbb41cSArnaldo Carvalho de Melo 
154223cbb41cSArnaldo Carvalho de Melo 		if (evlist__add_bpf_sb_event(rec->sb_evlist, &rec->session->header.env)) {
154323cbb41cSArnaldo Carvalho de Melo 			pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n.");
154423cbb41cSArnaldo Carvalho de Melo 			return -1;
154523cbb41cSArnaldo Carvalho de Melo 		}
154623cbb41cSArnaldo Carvalho de Melo 	}
15471101c872SJin Yao #endif
154808c83997SArnaldo Carvalho de Melo 	if (evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) {
154923cbb41cSArnaldo Carvalho de Melo 		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
155023cbb41cSArnaldo Carvalho de Melo 		opts->no_bpf_event = true;
155123cbb41cSArnaldo Carvalho de Melo 	}
155223cbb41cSArnaldo Carvalho de Melo 
155323cbb41cSArnaldo Carvalho de Melo 	return 0;
155423cbb41cSArnaldo Carvalho de Melo }
155523cbb41cSArnaldo Carvalho de Melo 
1556d1e325cfSJiri Olsa static int record__init_clock(struct record *rec)
1557d1e325cfSJiri Olsa {
1558d1e325cfSJiri Olsa 	struct perf_session *session = rec->session;
1559d1e325cfSJiri Olsa 	struct timespec ref_clockid;
1560d1e325cfSJiri Olsa 	struct timeval ref_tod;
1561d1e325cfSJiri Olsa 	u64 ref;
1562d1e325cfSJiri Olsa 
1563d1e325cfSJiri Olsa 	if (!rec->opts.use_clockid)
1564d1e325cfSJiri Olsa 		return 0;
1565d1e325cfSJiri Olsa 
15669d88a1a1SJiri Olsa 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
15679d88a1a1SJiri Olsa 		session->header.env.clock.clockid_res_ns = rec->opts.clockid_res_ns;
15689d88a1a1SJiri Olsa 
1569d1e325cfSJiri Olsa 	session->header.env.clock.clockid = rec->opts.clockid;
1570d1e325cfSJiri Olsa 
1571d1e325cfSJiri Olsa 	if (gettimeofday(&ref_tod, NULL) != 0) {
1572d1e325cfSJiri Olsa 		pr_err("gettimeofday failed, cannot set reference time.\n");
1573d1e325cfSJiri Olsa 		return -1;
1574d1e325cfSJiri Olsa 	}
1575d1e325cfSJiri Olsa 
1576d1e325cfSJiri Olsa 	if (clock_gettime(rec->opts.clockid, &ref_clockid)) {
1577d1e325cfSJiri Olsa 		pr_err("clock_gettime failed, cannot set reference time.\n");
1578d1e325cfSJiri Olsa 		return -1;
1579d1e325cfSJiri Olsa 	}
1580d1e325cfSJiri Olsa 
1581d1e325cfSJiri Olsa 	ref = (u64) ref_tod.tv_sec * NSEC_PER_SEC +
1582d1e325cfSJiri Olsa 	      (u64) ref_tod.tv_usec * NSEC_PER_USEC;
1583d1e325cfSJiri Olsa 
1584d1e325cfSJiri Olsa 	session->header.env.clock.tod_ns = ref;
1585d1e325cfSJiri Olsa 
1586d1e325cfSJiri Olsa 	ref = (u64) ref_clockid.tv_sec * NSEC_PER_SEC +
1587d1e325cfSJiri Olsa 	      (u64) ref_clockid.tv_nsec;
1588d1e325cfSJiri Olsa 
1589d1e325cfSJiri Olsa 	session->header.env.clock.clockid_ns = ref;
1590d1e325cfSJiri Olsa 	return 0;
1591d1e325cfSJiri Olsa }
1592d1e325cfSJiri Olsa 
1593d20aff15SAdrian Hunter static void hit_auxtrace_snapshot_trigger(struct record *rec)
1594d20aff15SAdrian Hunter {
1595d20aff15SAdrian Hunter 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1596d20aff15SAdrian Hunter 		trigger_hit(&auxtrace_snapshot_trigger);
1597d20aff15SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
1598d20aff15SAdrian Hunter 		if (auxtrace_record__snapshot_start(rec->itr))
1599d20aff15SAdrian Hunter 			trigger_error(&auxtrace_snapshot_trigger);
1600d20aff15SAdrian Hunter 	}
1601d20aff15SAdrian Hunter }
1602d20aff15SAdrian Hunter 
160391c0f5ecSJin Yao static void record__uniquify_name(struct record *rec)
160491c0f5ecSJin Yao {
160591c0f5ecSJin Yao 	struct evsel *pos;
160691c0f5ecSJin Yao 	struct evlist *evlist = rec->evlist;
160791c0f5ecSJin Yao 	char *new_name;
160891c0f5ecSJin Yao 	int ret;
160991c0f5ecSJin Yao 
161091c0f5ecSJin Yao 	if (!perf_pmu__has_hybrid())
161191c0f5ecSJin Yao 		return;
161291c0f5ecSJin Yao 
161391c0f5ecSJin Yao 	evlist__for_each_entry(evlist, pos) {
161491c0f5ecSJin Yao 		if (!evsel__is_hybrid(pos))
161591c0f5ecSJin Yao 			continue;
161691c0f5ecSJin Yao 
161791c0f5ecSJin Yao 		if (strchr(pos->name, '/'))
161891c0f5ecSJin Yao 			continue;
161991c0f5ecSJin Yao 
162091c0f5ecSJin Yao 		ret = asprintf(&new_name, "%s/%s/",
162191c0f5ecSJin Yao 			       pos->pmu_name, pos->name);
162291c0f5ecSJin Yao 		if (ret) {
162391c0f5ecSJin Yao 			free(pos->name);
162491c0f5ecSJin Yao 			pos->name = new_name;
162591c0f5ecSJin Yao 		}
162691c0f5ecSJin Yao 	}
162791c0f5ecSJin Yao }
162891c0f5ecSJin Yao 
16298c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
163086470930SIngo Molnar {
163157706abcSDavid Ahern 	int err;
163245604710SNamhyung Kim 	int status = 0;
16338b412664SPeter Zijlstra 	unsigned long waking = 0;
163446be604bSZhang, Yanmin 	const bool forks = argc > 0;
163545694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1636b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
16378ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1638d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
16396dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
164042aa276fSNamhyung Kim 	int fd;
1641d3c8c08eSAlexey Budankov 	float ratio = 0;
1642acce0223SAlexey Budankov 	enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;
164386470930SIngo Molnar 
164445604710SNamhyung Kim 	atexit(record__sig_exit);
1645f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1646f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1647804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1648a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1649c0bdc1c4SWang Nan 
1650f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1651f3b3614aSHari Bathini 		tool->namespace_events = true;
1652f3b3614aSHari Bathini 
16538fb4b679SNamhyung Kim 	if (rec->opts.record_cgroup) {
16548fb4b679SNamhyung Kim #ifdef HAVE_FILE_HANDLE
16558fb4b679SNamhyung Kim 		tool->cgroup_events = true;
16568fb4b679SNamhyung Kim #else
16578fb4b679SNamhyung Kim 		pr_err("cgroup tracking is not supported\n");
16588fb4b679SNamhyung Kim 		return -1;
16598fb4b679SNamhyung Kim #endif
16608fb4b679SNamhyung Kim 	}
16618fb4b679SNamhyung Kim 
1662dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
16632dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
16643c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
16655f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1666dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
16673c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1668c0bdc1c4SWang Nan 	} else {
16692dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1670c0bdc1c4SWang Nan 	}
1671f5970550SPeter Zijlstra 
16722681bd85SNamhyung Kim 	session = perf_session__new(data, tool);
16736ef81c55SMamatha Inamdar 	if (IS_ERR(session)) {
1674ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
16756ef81c55SMamatha Inamdar 		return PTR_ERR(session);
1676a9a70bbcSArnaldo Carvalho de Melo 	}
1677a9a70bbcSArnaldo Carvalho de Melo 
16788ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1679d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1680d20deb64SArnaldo Carvalho de Melo 
16815d7f4116SAlexey Budankov 	if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
16825d7f4116SAlexey Budankov 		pr_err("Compression initialization failed.\n");
16835d7f4116SAlexey Budankov 		return -1;
16845d7f4116SAlexey Budankov 	}
1685da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
1686da231338SAnand K Mistry 	done_fd = eventfd(0, EFD_NONBLOCK);
1687da231338SAnand K Mistry 	if (done_fd < 0) {
1688da231338SAnand K Mistry 		pr_err("Failed to create wakeup eventfd, error: %m\n");
1689da231338SAnand K Mistry 		status = -1;
1690da231338SAnand K Mistry 		goto out_delete_session;
1691da231338SAnand K Mistry 	}
1692e16c2ce7SYang Jihong 	err = evlist__add_wakeup_eventfd(rec->evlist, done_fd);
1693da231338SAnand K Mistry 	if (err < 0) {
1694da231338SAnand K Mistry 		pr_err("Failed to add wakeup eventfd to poll list\n");
1695da231338SAnand K Mistry 		status = err;
1696da231338SAnand K Mistry 		goto out_delete_session;
1697da231338SAnand K Mistry 	}
1698da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT
16995d7f4116SAlexey Budankov 
17005d7f4116SAlexey Budankov 	session->header.env.comp_type  = PERF_COMP_ZSTD;
17015d7f4116SAlexey Budankov 	session->header.env.comp_level = rec->opts.comp_level;
17025d7f4116SAlexey Budankov 
1703eeb399b5SAdrian Hunter 	if (rec->opts.kcore &&
1704eeb399b5SAdrian Hunter 	    !record__kcore_readable(&session->machines.host)) {
1705eeb399b5SAdrian Hunter 		pr_err("ERROR: kcore is not readable.\n");
1706eeb399b5SAdrian Hunter 		return -1;
1707eeb399b5SAdrian Hunter 	}
1708eeb399b5SAdrian Hunter 
1709d1e325cfSJiri Olsa 	if (record__init_clock(rec))
1710d1e325cfSJiri Olsa 		return -1;
1711d1e325cfSJiri Olsa 
17128c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1713330aa675SStephane Eranian 
1714d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
17157b392ef0SArnaldo Carvalho de Melo 		err = evlist__prepare_workload(rec->evlist, &opts->target, argv, data->is_pipe,
1716735f7e0bSArnaldo Carvalho de Melo 					       workload_exec_failed_signal);
171735b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
171835b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
171945604710SNamhyung Kim 			status = err;
172035b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1721856e9660SPeter Zijlstra 		}
1722856e9660SPeter Zijlstra 	}
1723856e9660SPeter Zijlstra 
1724ad46e48cSJiri Olsa 	/*
1725ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1726ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1727ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1728ad46e48cSJiri Olsa 	 * and need the id for that.
1729ad46e48cSJiri Olsa 	 */
17306484d2f9SJiri Olsa 	if (data->is_pipe && rec->evlist->core.nr_entries == 1)
1731ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1732ad46e48cSJiri Olsa 
173391c0f5ecSJin Yao 	record__uniquify_name(rec);
173491c0f5ecSJin Yao 
17358c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
17368d3eca20SDavid Ahern 		err = -1;
173745604710SNamhyung Kim 		goto out_child;
17388d3eca20SDavid Ahern 	}
1739f6fa4375SJiri Olsa 	session->header.env.comp_mmap_len = session->evlist->core.mmap_len;
174086470930SIngo Molnar 
1741eeb399b5SAdrian Hunter 	if (rec->opts.kcore) {
1742eeb399b5SAdrian Hunter 		err = record__kcore_copy(&session->machines.host, data);
1743eeb399b5SAdrian Hunter 		if (err) {
1744eeb399b5SAdrian Hunter 			pr_err("ERROR: Failed to copy kcore\n");
1745eeb399b5SAdrian Hunter 			goto out_child;
1746eeb399b5SAdrian Hunter 		}
1747eeb399b5SAdrian Hunter 	}
1748eeb399b5SAdrian Hunter 
17498690a2a7SWang Nan 	err = bpf__apply_obj_config();
17508690a2a7SWang Nan 	if (err) {
17518690a2a7SWang Nan 		char errbuf[BUFSIZ];
17528690a2a7SWang Nan 
17538690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
17548690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
17558690a2a7SWang Nan 			 errbuf);
17568690a2a7SWang Nan 		goto out_child;
17578690a2a7SWang Nan 	}
17588690a2a7SWang Nan 
1759cca8482cSAdrian Hunter 	/*
1760cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1761cca8482cSAdrian Hunter 	 * evlist.
1762cca8482cSAdrian Hunter 	 */
17638cedf3a5SArnaldo Carvalho de Melo 	if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) {
1764cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1765cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1766cca8482cSAdrian Hunter 	}
1767cca8482cSAdrian Hunter 
17683a683120SJiri Olsa 	if (!rec->evlist->core.nr_groups)
1769a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1770a8bb559bSNamhyung Kim 
17718ceb41d7SJiri Olsa 	if (data->is_pipe) {
177242aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1773529870e3STom Zanussi 		if (err < 0)
177445604710SNamhyung Kim 			goto out_child;
1775563aecb2SJiri Olsa 	} else {
177642aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1777d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
177845604710SNamhyung Kim 			goto out_child;
1779d5eed904SArnaldo Carvalho de Melo 	}
17807c6a1c65SPeter Zijlstra 
1781b38d85efSArnaldo Carvalho de Melo 	err = -1;
1782d3665498SDavid Ahern 	if (!rec->no_buildid
1783e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1784d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1785e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
178645604710SNamhyung Kim 		goto out_child;
1787e20960c0SRobert Richter 	}
1788e20960c0SRobert Richter 
178923cbb41cSArnaldo Carvalho de Melo 	err = record__setup_sb_evlist(rec);
179023cbb41cSArnaldo Carvalho de Melo 	if (err)
1791b38d85efSArnaldo Carvalho de Melo 		goto out_child;
1792657ee553SSong Liu 
17934ea648aeSWang Nan 	err = record__synthesize(rec, false);
1794c45c86ebSWang Nan 	if (err < 0)
179545604710SNamhyung Kim 		goto out_child;
17968d3eca20SDavid Ahern 
1797d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
179886470930SIngo Molnar 		struct sched_param param;
179986470930SIngo Molnar 
1800d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
180186470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
18026beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
18038d3eca20SDavid Ahern 			err = -1;
180445604710SNamhyung Kim 			goto out_child;
180586470930SIngo Molnar 		}
180686470930SIngo Molnar 	}
180786470930SIngo Molnar 
1808774cb499SJiri Olsa 	/*
1809774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1810774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1811774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1812774cb499SJiri Olsa 	 */
18136619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
18141c87f165SJiri Olsa 		evlist__enable(rec->evlist);
1815764e16a3SDavid Ahern 
1816856e9660SPeter Zijlstra 	/*
1817856e9660SPeter Zijlstra 	 * Let the child rip
1818856e9660SPeter Zijlstra 	 */
1819e803cf97SNamhyung Kim 	if (forks) {
182020a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1821e5bed564SNamhyung Kim 		union perf_event *event;
1822e907caf3SHari Bathini 		pid_t tgid;
1823e5bed564SNamhyung Kim 
1824e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1825e5bed564SNamhyung Kim 		if (event == NULL) {
1826e5bed564SNamhyung Kim 			err = -ENOMEM;
1827e5bed564SNamhyung Kim 			goto out_child;
1828e5bed564SNamhyung Kim 		}
1829e5bed564SNamhyung Kim 
1830e803cf97SNamhyung Kim 		/*
1831e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1832e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1833e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1834e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1835e803cf97SNamhyung Kim 		 */
1836e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1837e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1838e803cf97SNamhyung Kim 						   process_synthesized_event,
1839e803cf97SNamhyung Kim 						   machine);
1840e5bed564SNamhyung Kim 		free(event);
1841e803cf97SNamhyung Kim 
1842e907caf3SHari Bathini 		if (tgid == -1)
1843e907caf3SHari Bathini 			goto out_child;
1844e907caf3SHari Bathini 
1845e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1846e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1847e907caf3SHari Bathini 			       machine->id_hdr_size);
1848e907caf3SHari Bathini 		if (event == NULL) {
1849e907caf3SHari Bathini 			err = -ENOMEM;
1850e907caf3SHari Bathini 			goto out_child;
1851e907caf3SHari Bathini 		}
1852e907caf3SHari Bathini 
1853e907caf3SHari Bathini 		/*
1854e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1855e907caf3SHari Bathini 		 */
1856e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1857e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1858e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1859e907caf3SHari Bathini 						  machine);
1860e907caf3SHari Bathini 		free(event);
1861e907caf3SHari Bathini 
18627b392ef0SArnaldo Carvalho de Melo 		evlist__start_workload(rec->evlist);
1863e803cf97SNamhyung Kim 	}
1864856e9660SPeter Zijlstra 
18651d078ccbSAlexey Budankov 	if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack))
18661d078ccbSAlexey Budankov 		goto out_child;
18671d078ccbSAlexey Budankov 
18686619a53eSAndi Kleen 	if (opts->initial_delay) {
186968cd3b45SAlexey Budankov 		pr_info(EVLIST_DISABLED_MSG);
187068cd3b45SAlexey Budankov 		if (opts->initial_delay > 0) {
18710693e680SArnaldo Carvalho de Melo 			usleep(opts->initial_delay * USEC_PER_MSEC);
18721c87f165SJiri Olsa 			evlist__enable(rec->evlist);
187368cd3b45SAlexey Budankov 			pr_info(EVLIST_ENABLED_MSG);
187468cd3b45SAlexey Budankov 		}
18756619a53eSAndi Kleen 	}
18766619a53eSAndi Kleen 
18775f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
18783c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1879a074865eSWang Nan 	perf_hooks__invoke_record_start();
1880649c48a9SPeter Zijlstra 	for (;;) {
18819f065194SYang Shi 		unsigned long long hits = rec->samples;
188286470930SIngo Molnar 
188305737464SWang Nan 		/*
188405737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
188505737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
188605737464SWang Nan 		 * hits != rec->samples in previous round.
188705737464SWang Nan 		 *
1888ade9d208SArnaldo Carvalho de Melo 		 * evlist__toggle_bkw_mmap ensure we never
188905737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
189005737464SWang Nan 		 */
189105737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
1892ade9d208SArnaldo Carvalho de Melo 			evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
189305737464SWang Nan 
1894470530bbSAlexey Budankov 		if (record__mmap_read_all(rec, false) < 0) {
18955f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
18963c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
18978d3eca20SDavid Ahern 			err = -1;
189845604710SNamhyung Kim 			goto out_child;
18998d3eca20SDavid Ahern 		}
190086470930SIngo Molnar 
19012dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
19022dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
19035f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
1904ce7b0e42SAlexander Shishkin 				record__read_auxtrace_snapshot(rec, false);
19055f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
19062dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
19072dd6d8a1SAdrian Hunter 				err = -1;
19082dd6d8a1SAdrian Hunter 				goto out_child;
19092dd6d8a1SAdrian Hunter 			}
19102dd6d8a1SAdrian Hunter 		}
19112dd6d8a1SAdrian Hunter 
19123c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
191305737464SWang Nan 			/*
191405737464SWang Nan 			 * If switch_output_trigger is hit, the data in
191505737464SWang Nan 			 * overwritable ring buffer should have been collected,
191605737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
191705737464SWang Nan 			 *
191805737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
191905737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
192005737464SWang Nan 			 * overwritable ring buffer. Read again.
192105737464SWang Nan 			 */
192205737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
192305737464SWang Nan 				continue;
19243c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
19253c1cb7e3SWang Nan 
192605737464SWang Nan 			/*
192705737464SWang Nan 			 * Reenable events in overwrite ring buffer after
192805737464SWang Nan 			 * record__mmap_read_all(): we should have collected
192905737464SWang Nan 			 * data from it.
193005737464SWang Nan 			 */
1931ade9d208SArnaldo Carvalho de Melo 			evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
193205737464SWang Nan 
19333c1cb7e3SWang Nan 			if (!quiet)
19343c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
19353c1cb7e3SWang Nan 					waking);
19363c1cb7e3SWang Nan 			waking = 0;
19373c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
19383c1cb7e3SWang Nan 			if (fd < 0) {
19393c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
19403c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
19413c1cb7e3SWang Nan 				err = fd;
19423c1cb7e3SWang Nan 				goto out_child;
19433c1cb7e3SWang Nan 			}
1944bfacbe3bSJiri Olsa 
1945bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1946bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1947bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
19483c1cb7e3SWang Nan 		}
19493c1cb7e3SWang Nan 
1950d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
19516dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1952649c48a9SPeter Zijlstra 				break;
195380ab2987SJiri Olsa 			err = evlist__poll(rec->evlist, -1);
1954a515114fSJiri Olsa 			/*
1955a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1956a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1957a515114fSJiri Olsa 			 */
1958a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
195945604710SNamhyung Kim 				err = 0;
19608b412664SPeter Zijlstra 			waking++;
19616dcf45efSArnaldo Carvalho de Melo 
1962f4009e7bSJiri Olsa 			if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
19636dcf45efSArnaldo Carvalho de Melo 				draining = true;
19648b412664SPeter Zijlstra 		}
19658b412664SPeter Zijlstra 
1966acce0223SAlexey Budankov 		if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) {
1967acce0223SAlexey Budankov 			switch (cmd) {
1968d20aff15SAdrian Hunter 			case EVLIST_CTL_CMD_SNAPSHOT:
1969d20aff15SAdrian Hunter 				hit_auxtrace_snapshot_trigger(rec);
1970d20aff15SAdrian Hunter 				evlist__ctlfd_ack(rec->evlist);
1971d20aff15SAdrian Hunter 				break;
1972f186cd61SJiri Olsa 			case EVLIST_CTL_CMD_STOP:
1973f186cd61SJiri Olsa 				done = 1;
1974f186cd61SJiri Olsa 				break;
1975acce0223SAlexey Budankov 			case EVLIST_CTL_CMD_ACK:
1976acce0223SAlexey Budankov 			case EVLIST_CTL_CMD_UNSUPPORTED:
1977991ae4ebSJiri Olsa 			case EVLIST_CTL_CMD_ENABLE:
1978991ae4ebSJiri Olsa 			case EVLIST_CTL_CMD_DISABLE:
1979142544a9SJiri Olsa 			case EVLIST_CTL_CMD_EVLIST:
198047fddcb4SJiri Olsa 			case EVLIST_CTL_CMD_PING:
1981acce0223SAlexey Budankov 			default:
1982acce0223SAlexey Budankov 				break;
1983acce0223SAlexey Budankov 			}
1984acce0223SAlexey Budankov 		}
1985acce0223SAlexey Budankov 
1986774cb499SJiri Olsa 		/*
1987774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1988774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1989774cb499SJiri Olsa 		 * disable events in this case.
1990774cb499SJiri Olsa 		 */
1991602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
19925f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
1993e74676deSJiri Olsa 			evlist__disable(rec->evlist);
19942711926aSJiri Olsa 			disabled = true;
19952711926aSJiri Olsa 		}
19968b412664SPeter Zijlstra 	}
1997ce7b0e42SAlexander Shishkin 
19985f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
19993c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
20008b412664SPeter Zijlstra 
2001ce7b0e42SAlexander Shishkin 	if (opts->auxtrace_snapshot_on_exit)
2002ce7b0e42SAlexander Shishkin 		record__auxtrace_snapshot_exit(rec);
2003ce7b0e42SAlexander Shishkin 
2004f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
20053535a696SArnaldo Carvalho de Melo 		char msg[STRERR_BUFSIZE], strevsels[2048];
2006c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
20073535a696SArnaldo Carvalho de Melo 
20083535a696SArnaldo Carvalho de Melo 		evlist__scnprintf_evsels(rec->evlist, sizeof(strevsels), strevsels);
20093535a696SArnaldo Carvalho de Melo 
20103535a696SArnaldo Carvalho de Melo 		pr_err("Failed to collect '%s' for the '%s' workload: %s\n",
20113535a696SArnaldo Carvalho de Melo 			strevsels, argv[0], emsg);
2012f33cbe72SArnaldo Carvalho de Melo 		err = -1;
201345604710SNamhyung Kim 		goto out_child;
2014f33cbe72SArnaldo Carvalho de Melo 	}
2015f33cbe72SArnaldo Carvalho de Melo 
2016e3d59112SNamhyung Kim 	if (!quiet)
20178b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
201886470930SIngo Molnar 
20194ea648aeSWang Nan 	if (target__none(&rec->opts.target))
20204ea648aeSWang Nan 		record__synthesize_workload(rec, true);
20214ea648aeSWang Nan 
202245604710SNamhyung Kim out_child:
20231d078ccbSAlexey Budankov 	evlist__finalize_ctlfd(rec->evlist);
2024470530bbSAlexey Budankov 	record__mmap_read_all(rec, true);
2025d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
2026d3d1af6fSAlexey Budankov 
2027d3c8c08eSAlexey Budankov 	if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
2028d3c8c08eSAlexey Budankov 		ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
2029d3c8c08eSAlexey Budankov 		session->header.env.comp_ratio = ratio + 0.5;
2030d3c8c08eSAlexey Budankov 	}
2031d3c8c08eSAlexey Budankov 
203245604710SNamhyung Kim 	if (forks) {
203345604710SNamhyung Kim 		int exit_status;
203445604710SNamhyung Kim 
203545604710SNamhyung Kim 		if (!child_finished)
203645604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
203745604710SNamhyung Kim 
203845604710SNamhyung Kim 		wait(&exit_status);
203945604710SNamhyung Kim 
204045604710SNamhyung Kim 		if (err < 0)
204145604710SNamhyung Kim 			status = err;
204245604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
204345604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
204445604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
204545604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
204645604710SNamhyung Kim 	} else
204745604710SNamhyung Kim 		status = err;
204845604710SNamhyung Kim 
20494ea648aeSWang Nan 	record__synthesize(rec, true);
2050e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
2051e3d59112SNamhyung Kim 	rec->samples = 0;
2052e3d59112SNamhyung Kim 
2053ecfd7a9cSWang Nan 	if (!err) {
2054ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
2055e1ab48baSWang Nan 			record__finish_output(rec);
2056ecfd7a9cSWang Nan 		} else {
2057ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
2058ecfd7a9cSWang Nan 			if (fd < 0) {
2059ecfd7a9cSWang Nan 				status = fd;
2060ecfd7a9cSWang Nan 				goto out_delete_session;
2061ecfd7a9cSWang Nan 			}
2062ecfd7a9cSWang Nan 		}
2063ecfd7a9cSWang Nan 	}
206439d17dacSArnaldo Carvalho de Melo 
2065a074865eSWang Nan 	perf_hooks__invoke_record_end();
2066a074865eSWang Nan 
2067e3d59112SNamhyung Kim 	if (!err && !quiet) {
2068e3d59112SNamhyung Kim 		char samples[128];
2069ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
2070ecfd7a9cSWang Nan 					".<timestamp>" : "";
2071e3d59112SNamhyung Kim 
2072ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
2073e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
2074e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
2075e3d59112SNamhyung Kim 		else
2076e3d59112SNamhyung Kim 			samples[0] = '\0';
2077e3d59112SNamhyung Kim 
2078d3c8c08eSAlexey Budankov 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s",
20798ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
20802d4f2799SJiri Olsa 			data->path, postfix, samples);
2081d3c8c08eSAlexey Budankov 		if (ratio) {
2082d3c8c08eSAlexey Budankov 			fprintf(stderr,	", compressed (original %.3f MB, ratio is %.3f)",
2083d3c8c08eSAlexey Budankov 					rec->session->bytes_transferred / 1024.0 / 1024.0,
2084d3c8c08eSAlexey Budankov 					ratio);
2085d3c8c08eSAlexey Budankov 		}
2086d3c8c08eSAlexey Budankov 		fprintf(stderr, " ]\n");
2087e3d59112SNamhyung Kim 	}
2088e3d59112SNamhyung Kim 
208939d17dacSArnaldo Carvalho de Melo out_delete_session:
2090da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
2091da231338SAnand K Mistry 	if (done_fd >= 0)
2092da231338SAnand K Mistry 		close(done_fd);
2093da231338SAnand K Mistry #endif
20945d7f4116SAlexey Budankov 	zstd_fini(&session->zstd_data);
209539d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
2096657ee553SSong Liu 
2097657ee553SSong Liu 	if (!opts->no_bpf_event)
209808c83997SArnaldo Carvalho de Melo 		evlist__stop_sb_thread(rec->sb_evlist);
209945604710SNamhyung Kim 	return status;
210086470930SIngo Molnar }
210186470930SIngo Molnar 
21020883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
210309b0fd45SJiri Olsa {
2104aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
2105a601fdffSJiri Olsa 
21060883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
210726d33022SJiri Olsa 
21080883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
210909b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
21100883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
21110883e820SArnaldo Carvalho de Melo }
21120883e820SArnaldo Carvalho de Melo 
21130883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
21140883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
21150883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
21160883e820SArnaldo Carvalho de Melo {
21170883e820SArnaldo Carvalho de Melo 	int ret;
21180883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
21190883e820SArnaldo Carvalho de Melo 
21200883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
21210883e820SArnaldo Carvalho de Melo 	if (unset) {
21220883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
21230883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
21240883e820SArnaldo Carvalho de Melo 		return 0;
21250883e820SArnaldo Carvalho de Melo 	}
21260883e820SArnaldo Carvalho de Melo 
21270883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
21280883e820SArnaldo Carvalho de Melo 	if (!ret) {
21290883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
21300883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
21310883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
21320883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
21330883e820SArnaldo Carvalho de Melo 	}
21340883e820SArnaldo Carvalho de Melo 
21350883e820SArnaldo Carvalho de Melo 	return ret;
213609b0fd45SJiri Olsa }
213709b0fd45SJiri Olsa 
2138c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
213909b0fd45SJiri Olsa 			       const char *arg,
214009b0fd45SJiri Olsa 			       int unset)
214109b0fd45SJiri Olsa {
21420883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
214326d33022SJiri Olsa }
214426d33022SJiri Olsa 
2145c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
214609b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
214709b0fd45SJiri Olsa 			 int unset __maybe_unused)
214809b0fd45SJiri Olsa {
21492ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
2150c421e80bSKan Liang 
21512ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
215209b0fd45SJiri Olsa 
21532ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
21542ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
2155eb853e80SJiri Olsa 
21562ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
215709b0fd45SJiri Olsa 	return 0;
215809b0fd45SJiri Olsa }
215909b0fd45SJiri Olsa 
2160eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
2161eb853e80SJiri Olsa {
21627a29c087SNamhyung Kim 	struct record *rec = cb;
21637a29c087SNamhyung Kim 
21647a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
21657a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
21667a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
21677a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
21687a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
21697a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
21707a29c087SNamhyung Kim 			rec->no_buildid = true;
2171e29386c8SJiri Olsa 		else if (!strcmp(value, "mmap"))
2172e29386c8SJiri Olsa 			rec->buildid_mmap = true;
21737a29c087SNamhyung Kim 		else
21747a29c087SNamhyung Kim 			return -1;
21757a29c087SNamhyung Kim 		return 0;
21767a29c087SNamhyung Kim 	}
2177cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
2178cff17205SYisheng Xie 		var = "call-graph.record-mode";
2179eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
2180eb853e80SJiri Olsa 	}
218193f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
218293f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
218393f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
218493f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
218593f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
218693f20c0fSAlexey Budankov 	}
218793f20c0fSAlexey Budankov #endif
21889bce13eaSJiri Olsa 	if (!strcmp(var, "record.debuginfod")) {
21899bce13eaSJiri Olsa 		rec->debuginfod.urls = strdup(value);
21909bce13eaSJiri Olsa 		if (!rec->debuginfod.urls)
21919bce13eaSJiri Olsa 			return -ENOMEM;
21929bce13eaSJiri Olsa 		rec->debuginfod.set = true;
21939bce13eaSJiri Olsa 	}
2194eb853e80SJiri Olsa 
2195cff17205SYisheng Xie 	return 0;
2196cff17205SYisheng Xie }
2197cff17205SYisheng Xie 
2198814c8c38SPeter Zijlstra 
2199f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
2200f4fe11b7SAlexey Budankov {
2201f4fe11b7SAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
2202f4fe11b7SAlexey Budankov 
2203f4fe11b7SAlexey Budankov 	if (unset || !str)
2204f4fe11b7SAlexey Budankov 		return 0;
2205f4fe11b7SAlexey Budankov 
2206f4fe11b7SAlexey Budankov 	if (!strcasecmp(str, "node"))
2207f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_NODE;
2208f4fe11b7SAlexey Budankov 	else if (!strcasecmp(str, "cpu"))
2209f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_CPU;
2210f4fe11b7SAlexey Budankov 
2211f4fe11b7SAlexey Budankov 	return 0;
2212f4fe11b7SAlexey Budankov }
2213f4fe11b7SAlexey Budankov 
2214*7954f716SAlexey Bayduraev static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits)
2215*7954f716SAlexey Bayduraev {
2216*7954f716SAlexey Bayduraev 	mask->nbits = nr_bits;
2217*7954f716SAlexey Bayduraev 	mask->bits = bitmap_zalloc(mask->nbits);
2218*7954f716SAlexey Bayduraev 	if (!mask->bits)
2219*7954f716SAlexey Bayduraev 		return -ENOMEM;
2220*7954f716SAlexey Bayduraev 
2221*7954f716SAlexey Bayduraev 	return 0;
2222*7954f716SAlexey Bayduraev }
2223*7954f716SAlexey Bayduraev 
2224*7954f716SAlexey Bayduraev static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask)
2225*7954f716SAlexey Bayduraev {
2226*7954f716SAlexey Bayduraev 	bitmap_free(mask->bits);
2227*7954f716SAlexey Bayduraev 	mask->nbits = 0;
2228*7954f716SAlexey Bayduraev }
2229*7954f716SAlexey Bayduraev 
2230*7954f716SAlexey Bayduraev static int record__thread_mask_alloc(struct thread_mask *mask, int nr_bits)
2231*7954f716SAlexey Bayduraev {
2232*7954f716SAlexey Bayduraev 	int ret;
2233*7954f716SAlexey Bayduraev 
2234*7954f716SAlexey Bayduraev 	ret = record__mmap_cpu_mask_alloc(&mask->maps, nr_bits);
2235*7954f716SAlexey Bayduraev 	if (ret) {
2236*7954f716SAlexey Bayduraev 		mask->affinity.bits = NULL;
2237*7954f716SAlexey Bayduraev 		return ret;
2238*7954f716SAlexey Bayduraev 	}
2239*7954f716SAlexey Bayduraev 
2240*7954f716SAlexey Bayduraev 	ret = record__mmap_cpu_mask_alloc(&mask->affinity, nr_bits);
2241*7954f716SAlexey Bayduraev 	if (ret) {
2242*7954f716SAlexey Bayduraev 		record__mmap_cpu_mask_free(&mask->maps);
2243*7954f716SAlexey Bayduraev 		mask->maps.bits = NULL;
2244*7954f716SAlexey Bayduraev 	}
2245*7954f716SAlexey Bayduraev 
2246*7954f716SAlexey Bayduraev 	return ret;
2247*7954f716SAlexey Bayduraev }
2248*7954f716SAlexey Bayduraev 
2249*7954f716SAlexey Bayduraev static void record__thread_mask_free(struct thread_mask *mask)
2250*7954f716SAlexey Bayduraev {
2251*7954f716SAlexey Bayduraev 	record__mmap_cpu_mask_free(&mask->maps);
2252*7954f716SAlexey Bayduraev 	record__mmap_cpu_mask_free(&mask->affinity);
2253*7954f716SAlexey Bayduraev }
2254*7954f716SAlexey Bayduraev 
22556d575816SJiwei Sun static int parse_output_max_size(const struct option *opt,
22566d575816SJiwei Sun 				 const char *str, int unset)
22576d575816SJiwei Sun {
22586d575816SJiwei Sun 	unsigned long *s = (unsigned long *)opt->value;
22596d575816SJiwei Sun 	static struct parse_tag tags_size[] = {
22606d575816SJiwei Sun 		{ .tag  = 'B', .mult = 1       },
22616d575816SJiwei Sun 		{ .tag  = 'K', .mult = 1 << 10 },
22626d575816SJiwei Sun 		{ .tag  = 'M', .mult = 1 << 20 },
22636d575816SJiwei Sun 		{ .tag  = 'G', .mult = 1 << 30 },
22646d575816SJiwei Sun 		{ .tag  = 0 },
22656d575816SJiwei Sun 	};
22666d575816SJiwei Sun 	unsigned long val;
22676d575816SJiwei Sun 
22686d575816SJiwei Sun 	if (unset) {
22696d575816SJiwei Sun 		*s = 0;
22706d575816SJiwei Sun 		return 0;
22716d575816SJiwei Sun 	}
22726d575816SJiwei Sun 
22736d575816SJiwei Sun 	val = parse_tag_value(str, tags_size);
22746d575816SJiwei Sun 	if (val != (unsigned long) -1) {
22756d575816SJiwei Sun 		*s = val;
22766d575816SJiwei Sun 		return 0;
22776d575816SJiwei Sun 	}
22786d575816SJiwei Sun 
22796d575816SJiwei Sun 	return -1;
22806d575816SJiwei Sun }
22816d575816SJiwei Sun 
2282e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
2283e9db1310SAdrian Hunter 				    const char *str,
2284e9db1310SAdrian Hunter 				    int unset __maybe_unused)
2285e9db1310SAdrian Hunter {
2286e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
2287e9db1310SAdrian Hunter 	char *s, *p;
2288e9db1310SAdrian Hunter 	unsigned int mmap_pages;
2289e9db1310SAdrian Hunter 	int ret;
2290e9db1310SAdrian Hunter 
2291e9db1310SAdrian Hunter 	if (!str)
2292e9db1310SAdrian Hunter 		return -EINVAL;
2293e9db1310SAdrian Hunter 
2294e9db1310SAdrian Hunter 	s = strdup(str);
2295e9db1310SAdrian Hunter 	if (!s)
2296e9db1310SAdrian Hunter 		return -ENOMEM;
2297e9db1310SAdrian Hunter 
2298e9db1310SAdrian Hunter 	p = strchr(s, ',');
2299e9db1310SAdrian Hunter 	if (p)
2300e9db1310SAdrian Hunter 		*p = '\0';
2301e9db1310SAdrian Hunter 
2302e9db1310SAdrian Hunter 	if (*s) {
230325f84702SArnaldo Carvalho de Melo 		ret = __evlist__parse_mmap_pages(&mmap_pages, s);
2304e9db1310SAdrian Hunter 		if (ret)
2305e9db1310SAdrian Hunter 			goto out_free;
2306e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
2307e9db1310SAdrian Hunter 	}
2308e9db1310SAdrian Hunter 
2309e9db1310SAdrian Hunter 	if (!p) {
2310e9db1310SAdrian Hunter 		ret = 0;
2311e9db1310SAdrian Hunter 		goto out_free;
2312e9db1310SAdrian Hunter 	}
2313e9db1310SAdrian Hunter 
231425f84702SArnaldo Carvalho de Melo 	ret = __evlist__parse_mmap_pages(&mmap_pages, p + 1);
2315e9db1310SAdrian Hunter 	if (ret)
2316e9db1310SAdrian Hunter 		goto out_free;
2317e9db1310SAdrian Hunter 
2318e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
2319e9db1310SAdrian Hunter 
2320e9db1310SAdrian Hunter out_free:
2321e9db1310SAdrian Hunter 	free(s);
2322e9db1310SAdrian Hunter 	return ret;
2323e9db1310SAdrian Hunter }
2324e9db1310SAdrian Hunter 
23257248e308SAlexandre Truong void __weak arch__add_leaf_frame_record_opts(struct record_opts *opts __maybe_unused)
23267248e308SAlexandre Truong {
23277248e308SAlexandre Truong }
23287248e308SAlexandre Truong 
23291d078ccbSAlexey Budankov static int parse_control_option(const struct option *opt,
23301d078ccbSAlexey Budankov 				const char *str,
23311d078ccbSAlexey Budankov 				int unset __maybe_unused)
23321d078ccbSAlexey Budankov {
23339864a66dSAdrian Hunter 	struct record_opts *opts = opt->value;
23341d078ccbSAlexey Budankov 
2335a8fcbd26SAdrian Hunter 	return evlist__parse_control(str, &opts->ctl_fd, &opts->ctl_fd_ack, &opts->ctl_fd_close);
2336a8fcbd26SAdrian Hunter }
2337a8fcbd26SAdrian Hunter 
23380c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
23390c582449SJiri Olsa {
23409521b5f2SJiri Olsa 	u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages);
23410c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
23420c582449SJiri Olsa 
23430c582449SJiri Olsa 	wakeup_size /= 2;
23440c582449SJiri Olsa 
23450c582449SJiri Olsa 	if (s->size < wakeup_size) {
23460c582449SJiri Olsa 		char buf[100];
23470c582449SJiri Olsa 
23480c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
23490c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
23500c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
23510c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
23520c582449SJiri Olsa 	}
23530c582449SJiri Olsa }
23540c582449SJiri Olsa 
2355cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
2356cb4e1ebbSJiri Olsa {
2357cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
2358dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
2359dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
2360dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
2361dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
2362dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
2363dc0c6127SJiri Olsa 		{ .tag  = 0 },
2364dc0c6127SJiri Olsa 	};
2365bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
2366bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
2367bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
2368bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
2369bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
2370bfacbe3bSJiri Olsa 		{ .tag  = 0 },
2371bfacbe3bSJiri Olsa 	};
2372dc0c6127SJiri Olsa 	unsigned long val;
2373cb4e1ebbSJiri Olsa 
2374899e5ffbSArnaldo Carvalho de Melo 	/*
2375899e5ffbSArnaldo Carvalho de Melo 	 * If we're using --switch-output-events, then we imply its
2376899e5ffbSArnaldo Carvalho de Melo 	 * --switch-output=signal, as we'll send a SIGUSR2 from the side band
2377899e5ffbSArnaldo Carvalho de Melo 	 *  thread to its parent.
2378899e5ffbSArnaldo Carvalho de Melo 	 */
2379899e5ffbSArnaldo Carvalho de Melo 	if (rec->switch_output_event_set)
2380899e5ffbSArnaldo Carvalho de Melo 		goto do_signal;
2381899e5ffbSArnaldo Carvalho de Melo 
2382cb4e1ebbSJiri Olsa 	if (!s->set)
2383cb4e1ebbSJiri Olsa 		return 0;
2384cb4e1ebbSJiri Olsa 
2385cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
2386899e5ffbSArnaldo Carvalho de Melo do_signal:
2387cb4e1ebbSJiri Olsa 		s->signal = true;
2388cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
2389dc0c6127SJiri Olsa 		goto enabled;
2390dc0c6127SJiri Olsa 	}
2391dc0c6127SJiri Olsa 
2392dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
2393dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
2394dc0c6127SJiri Olsa 		s->size = val;
2395dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
2396dc0c6127SJiri Olsa 		goto enabled;
2397cb4e1ebbSJiri Olsa 	}
2398cb4e1ebbSJiri Olsa 
2399bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
2400bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
2401bfacbe3bSJiri Olsa 		s->time = val;
2402bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
2403bfacbe3bSJiri Olsa 			 s->str, s->time);
2404bfacbe3bSJiri Olsa 		goto enabled;
2405bfacbe3bSJiri Olsa 	}
2406bfacbe3bSJiri Olsa 
2407cb4e1ebbSJiri Olsa 	return -1;
2408dc0c6127SJiri Olsa 
2409dc0c6127SJiri Olsa enabled:
2410dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
2411dc0c6127SJiri Olsa 	s->enabled              = true;
24120c582449SJiri Olsa 
24130c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
24140c582449SJiri Olsa 		switch_output_size_warn(rec);
24150c582449SJiri Olsa 
2416dc0c6127SJiri Olsa 	return 0;
2417cb4e1ebbSJiri Olsa }
2418cb4e1ebbSJiri Olsa 
2419e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
242086470930SIngo Molnar 	"perf record [<options>] [<command>]",
242186470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
242286470930SIngo Molnar 	NULL
242386470930SIngo Molnar };
2424e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
242586470930SIngo Molnar 
24266e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap(struct perf_tool *tool, union perf_event *event,
24276e0a9b3dSArnaldo Carvalho de Melo 				  struct perf_sample *sample, struct machine *machine)
24286e0a9b3dSArnaldo Carvalho de Melo {
24296e0a9b3dSArnaldo Carvalho de Melo 	/*
24306e0a9b3dSArnaldo Carvalho de Melo 	 * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
24316e0a9b3dSArnaldo Carvalho de Melo 	 * no need to add them twice.
24326e0a9b3dSArnaldo Carvalho de Melo 	 */
24336e0a9b3dSArnaldo Carvalho de Melo 	if (!(event->header.misc & PERF_RECORD_MISC_USER))
24346e0a9b3dSArnaldo Carvalho de Melo 		return 0;
24356e0a9b3dSArnaldo Carvalho de Melo 	return perf_event__process_mmap(tool, event, sample, machine);
24366e0a9b3dSArnaldo Carvalho de Melo }
24376e0a9b3dSArnaldo Carvalho de Melo 
24386e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event,
24396e0a9b3dSArnaldo Carvalho de Melo 				   struct perf_sample *sample, struct machine *machine)
24406e0a9b3dSArnaldo Carvalho de Melo {
24416e0a9b3dSArnaldo Carvalho de Melo 	/*
24426e0a9b3dSArnaldo Carvalho de Melo 	 * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
24436e0a9b3dSArnaldo Carvalho de Melo 	 * no need to add them twice.
24446e0a9b3dSArnaldo Carvalho de Melo 	 */
24456e0a9b3dSArnaldo Carvalho de Melo 	if (!(event->header.misc & PERF_RECORD_MISC_USER))
24466e0a9b3dSArnaldo Carvalho de Melo 		return 0;
24476e0a9b3dSArnaldo Carvalho de Melo 
24486e0a9b3dSArnaldo Carvalho de Melo 	return perf_event__process_mmap2(tool, event, sample, machine);
24496e0a9b3dSArnaldo Carvalho de Melo }
24506e0a9b3dSArnaldo Carvalho de Melo 
245166286ed3SAdrian Hunter static int process_timestamp_boundary(struct perf_tool *tool,
245266286ed3SAdrian Hunter 				      union perf_event *event __maybe_unused,
245366286ed3SAdrian Hunter 				      struct perf_sample *sample,
245466286ed3SAdrian Hunter 				      struct machine *machine __maybe_unused)
245566286ed3SAdrian Hunter {
245666286ed3SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
245766286ed3SAdrian Hunter 
245866286ed3SAdrian Hunter 	set_timestamp_boundary(rec, sample->time);
245966286ed3SAdrian Hunter 	return 0;
246066286ed3SAdrian Hunter }
246166286ed3SAdrian Hunter 
246241b740b6SNamhyung Kim static int parse_record_synth_option(const struct option *opt,
246341b740b6SNamhyung Kim 				     const char *str,
246441b740b6SNamhyung Kim 				     int unset __maybe_unused)
246541b740b6SNamhyung Kim {
246641b740b6SNamhyung Kim 	struct record_opts *opts = opt->value;
246741b740b6SNamhyung Kim 	char *p = strdup(str);
246841b740b6SNamhyung Kim 
246941b740b6SNamhyung Kim 	if (p == NULL)
247041b740b6SNamhyung Kim 		return -1;
247141b740b6SNamhyung Kim 
247241b740b6SNamhyung Kim 	opts->synth = parse_synth_opt(p);
247341b740b6SNamhyung Kim 	free(p);
247441b740b6SNamhyung Kim 
247541b740b6SNamhyung Kim 	if (opts->synth < 0) {
247641b740b6SNamhyung Kim 		pr_err("Invalid synth option: %s\n", str);
247741b740b6SNamhyung Kim 		return -1;
247841b740b6SNamhyung Kim 	}
247941b740b6SNamhyung Kim 	return 0;
248041b740b6SNamhyung Kim }
248141b740b6SNamhyung Kim 
2482d20deb64SArnaldo Carvalho de Melo /*
24838c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
24848c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
2485d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
2486d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
2487d20deb64SArnaldo Carvalho de Melo  *
2488d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
2489d20deb64SArnaldo Carvalho de Melo  *
2490d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
2491d20deb64SArnaldo Carvalho de Melo  */
24928c6f45a7SArnaldo Carvalho de Melo static struct record record = {
2493d20deb64SArnaldo Carvalho de Melo 	.opts = {
24948affc2b8SAndi Kleen 		.sample_time	     = true,
2495d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
2496d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
2497d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
2498447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
2499d1cb9fceSNamhyung Kim 		.target		     = {
2500d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
25013aa5939dSAdrian Hunter 			.default_per_cpu = true,
2502d1cb9fceSNamhyung Kim 		},
2503470530bbSAlexey Budankov 		.mmap_flush          = MMAP_FLUSH_DEFAULT,
2504d99c22eaSStephane Eranian 		.nr_threads_synthesize = 1,
25051d078ccbSAlexey Budankov 		.ctl_fd              = -1,
25061d078ccbSAlexey Budankov 		.ctl_fd_ack          = -1,
250741b740b6SNamhyung Kim 		.synth               = PERF_SYNTH_ALL,
2508d20deb64SArnaldo Carvalho de Melo 	},
2509e3d59112SNamhyung Kim 	.tool = {
2510e3d59112SNamhyung Kim 		.sample		= process_sample_event,
2511e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
2512cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
2513e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
2514f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
25156e0a9b3dSArnaldo Carvalho de Melo 		.mmap		= build_id__process_mmap,
25166e0a9b3dSArnaldo Carvalho de Melo 		.mmap2		= build_id__process_mmap2,
251766286ed3SAdrian Hunter 		.itrace_start	= process_timestamp_boundary,
251866286ed3SAdrian Hunter 		.aux		= process_timestamp_boundary,
2519cca8482cSAdrian Hunter 		.ordered_events	= true,
2520e3d59112SNamhyung Kim 	},
2521d20deb64SArnaldo Carvalho de Melo };
25227865e817SFrederic Weisbecker 
252376a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
252476a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
252561eaa3beSArnaldo Carvalho de Melo 
25260aab2136SWang Nan static bool dry_run;
25270aab2136SWang Nan 
2528d20deb64SArnaldo Carvalho de Melo /*
2529d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
2530d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
2531b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
25327b392ef0SArnaldo Carvalho de Melo  * evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
2533d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
2534d20deb64SArnaldo Carvalho de Melo  */
2535efd21307SJiri Olsa static struct option __record_options[] = {
2536d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
253786470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
2538f120f9d5SJiri Olsa 		     parse_events_option),
2539d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
2540c171b552SLi Zefan 		     "event filter", parse_filter),
25414ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
25424ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
25434ba1faa1SWang Nan 			   exclude_perf),
2544bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
2545d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
2546bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
2547d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
2548d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
254986470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
2550509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
2551acac03faSKirill Smelkov 		    "collect data without buffering"),
2552d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
2553daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
2554bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
255586470930SIngo Molnar 			    "system-wide collection from all CPUs"),
2556bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
2557c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
2558d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
25592d4f2799SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
256086470930SIngo Molnar 		    "output file name"),
256169e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
256269e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
25632e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
25644ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
25654ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
2566626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
2567a060c1f1SWei Li 	OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "do not record bpf events"),
2568b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
2569b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
257067230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
257167230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
257267230479SArnaldo Carvalho de Melo 		      record__parse_freq),
2573e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
2574e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
2575e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
2576470530bbSAlexey Budankov 	OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
2577470530bbSAlexey Budankov 		     "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
2578470530bbSAlexey Budankov 		     record__mmap_flush_parse),
2579d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
258043bece79SLin Ming 		    "put the counters into a counter group"),
25812ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
258209b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
258309b0fd45SJiri Olsa 			   &record_callchain_opt),
258409b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
258576a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
258609b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
2587c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
25883da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
2589b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
2590d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
2591649c48a9SPeter Zijlstra 		    "per thread counts"),
259256100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
25933b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
25943b0a5daaSKan Liang 		    "Record the sample physical addresses"),
2595542b88fdSKan Liang 	OPT_BOOLEAN(0, "data-page-size", &record.opts.sample_data_page_size,
2596542b88fdSKan Liang 		    "Record the sampled data address data page size"),
2597c1de7f3dSKan Liang 	OPT_BOOLEAN(0, "code-page-size", &record.opts.sample_code_page_size,
2598c1de7f3dSKan Liang 		    "Record the sampled code address (ip) page size"),
2599b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
26003abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
26013abebc55SAdrian Hunter 			&record.opts.sample_time_set,
26023abebc55SAdrian Hunter 			"Record the sample timestamps"),
2603f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
2604f290aa1fSJiri Olsa 			"Record the sample period"),
2605d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
2606649c48a9SPeter Zijlstra 		    "don't sample"),
2607d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
2608d2db9a98SWang Nan 			&record.no_buildid_cache_set,
2609a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
2610d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
2611d2db9a98SWang Nan 			&record.no_buildid_set,
2612baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
2613d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
2614023695d9SStephane Eranian 		     "monitor event in cgroup name only",
2615023695d9SStephane Eranian 		     parse_cgroups),
261668cd3b45SAlexey Budankov 	OPT_INTEGER('D', "delay", &record.opts.initial_delay,
261768cd3b45SAlexey Budankov 		  "ms to wait before starting measurement after program start (-1: start with events disabled)"),
2618eeb399b5SAdrian Hunter 	OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"),
2619bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
2620bea03405SNamhyung Kim 		   "user to profile"),
2621a5aabdacSStephane Eranian 
2622a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
2623a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
2624a5aabdacSStephane Eranian 		     parse_branch_stack),
2625a5aabdacSStephane Eranian 
2626a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
2627a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
2628bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
262905484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
263005484298SAndi Kleen 		    "sample by weight (on special events only)"),
2631475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
2632475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
26333aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
26343aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
2635bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
2636bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
2637aeea9062SKan Liang 		    " use '-I?' to list register names", parse_intr_regs),
263884c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
263984c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
2640aeea9062SKan Liang 		    " use '--user-regs=?' to list register names", parse_user_regs),
264185c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
264285c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
2643814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
2644814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
2645814c8c38SPeter Zijlstra 	parse_clockid),
26462dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
26472dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
2648c0a6de06SAdrian Hunter 	OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts,
2649c0a6de06SAdrian Hunter 			  "opts", "sample AUX area", ""),
26503fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
26519d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
2652f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
2653f3b3614aSHari Bathini 		    "Record namespaces events"),
26548fb4b679SNamhyung Kim 	OPT_BOOLEAN(0, "all-cgroups", &record.opts.record_cgroup,
26558fb4b679SNamhyung Kim 		    "Record cgroup events"),
265616b4b4e1SAdrian Hunter 	OPT_BOOLEAN_SET(0, "switch-events", &record.opts.record_switch_events,
265716b4b4e1SAdrian Hunter 			&record.opts.record_switch_events_set,
2658b757bb09SAdrian Hunter 			"Record context switch events"),
265985723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
266085723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
266185723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
266285723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
266385723885SJiri Olsa 			 "Configure all used events to run in user space.",
266485723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
266553651b28Syuzhoujian 	OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains,
266653651b28Syuzhoujian 		    "collect kernel callchains"),
266753651b28Syuzhoujian 	OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains,
266853651b28Syuzhoujian 		    "collect user callchains"),
266971dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
267071dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
267171dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
267271dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
26737efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
26747efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
26756156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
26766156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
2677e29386c8SJiri Olsa 	OPT_BOOLEAN(0, "buildid-mmap", &record.buildid_mmap,
2678e29386c8SJiri Olsa 		    "Record build-id in map events"),
2679ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
2680ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
268168588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
268268588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
2683cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
2684c38dab7dSAndi Kleen 			  &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
2685c38dab7dSAndi Kleen 			  "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
2686dc0c6127SJiri Olsa 			  "signal"),
2687899e5ffbSArnaldo Carvalho de Melo 	OPT_CALLBACK_SET(0, "switch-output-event", &record.sb_evlist, &record.switch_output_event_set, "switch output event",
2688899e5ffbSArnaldo Carvalho de Melo 			 "switch output event selector. use 'perf list' to list available events",
2689899e5ffbSArnaldo Carvalho de Melo 			 parse_events_option_new_evlist),
269003724b2eSAndi Kleen 	OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
269103724b2eSAndi Kleen 		   "Limit number of switch output generated files"),
26920aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
26930aab2136SWang Nan 		    "Parse options then exit"),
2694d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
269593f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
269693f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
2697d3d1af6fSAlexey Budankov 		     record__aio_parse),
2698d3d1af6fSAlexey Budankov #endif
2699f4fe11b7SAlexey Budankov 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
2700f4fe11b7SAlexey Budankov 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
2701f4fe11b7SAlexey Budankov 		     record__parse_affinity),
2702504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
2703504c1ad1SAlexey Budankov 	OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default,
2704504c1ad1SAlexey Budankov 			    "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)",
2705504c1ad1SAlexey Budankov 			    record__parse_comp_level),
2706504c1ad1SAlexey Budankov #endif
27076d575816SJiwei Sun 	OPT_CALLBACK(0, "max-size", &record.output_max_size,
27086d575816SJiwei Sun 		     "size", "Limit the maximum size of the output file", parse_output_max_size),
2709d99c22eaSStephane Eranian 	OPT_UINTEGER(0, "num-thread-synthesize",
2710d99c22eaSStephane Eranian 		     &record.opts.nr_threads_synthesize,
2711d99c22eaSStephane Eranian 		     "number of threads to run for event synthesis"),
271270943490SStephane Eranian #ifdef HAVE_LIBPFM
271370943490SStephane Eranian 	OPT_CALLBACK(0, "pfm-events", &record.evlist, "event",
271470943490SStephane Eranian 		"libpfm4 event selector. use 'perf list' to list available events",
271570943490SStephane Eranian 		parse_libpfm_events_option),
271670943490SStephane Eranian #endif
2717a8fcbd26SAdrian Hunter 	OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]",
2718d20aff15SAdrian Hunter 		     "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events,\n"
2719d20aff15SAdrian Hunter 		     "\t\t\t  'snapshot': AUX area tracing snapshot).\n"
2720a8fcbd26SAdrian Hunter 		     "\t\t\t  Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n"
2721a8fcbd26SAdrian Hunter 		     "\t\t\t  Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",
27221d078ccbSAlexey Budankov 		      parse_control_option),
272341b740b6SNamhyung Kim 	OPT_CALLBACK(0, "synth", &record.opts, "no|all|task|mmap|cgroup",
272441b740b6SNamhyung Kim 		     "Fine-tune event synthesis: default=all", parse_record_synth_option),
27259bce13eaSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "debuginfod", &record.debuginfod.urls,
27269bce13eaSJiri Olsa 			  &record.debuginfod.set, "debuginfod urls",
27279bce13eaSJiri Olsa 			  "Enable debuginfod data retrieval from DEBUGINFOD_URLS or specified urls",
27289bce13eaSJiri Olsa 			  "system"),
272986470930SIngo Molnar 	OPT_END()
273086470930SIngo Molnar };
273186470930SIngo Molnar 
2732e5b2c207SNamhyung Kim struct option *record_options = __record_options;
2733e5b2c207SNamhyung Kim 
2734*7954f716SAlexey Bayduraev static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
2735*7954f716SAlexey Bayduraev {
2736*7954f716SAlexey Bayduraev 	int c;
2737*7954f716SAlexey Bayduraev 
2738*7954f716SAlexey Bayduraev 	for (c = 0; c < cpus->nr; c++)
2739*7954f716SAlexey Bayduraev 		set_bit(cpus->map[c].cpu, mask->bits);
2740*7954f716SAlexey Bayduraev }
2741*7954f716SAlexey Bayduraev 
2742*7954f716SAlexey Bayduraev static void record__free_thread_masks(struct record *rec, int nr_threads)
2743*7954f716SAlexey Bayduraev {
2744*7954f716SAlexey Bayduraev 	int t;
2745*7954f716SAlexey Bayduraev 
2746*7954f716SAlexey Bayduraev 	if (rec->thread_masks)
2747*7954f716SAlexey Bayduraev 		for (t = 0; t < nr_threads; t++)
2748*7954f716SAlexey Bayduraev 			record__thread_mask_free(&rec->thread_masks[t]);
2749*7954f716SAlexey Bayduraev 
2750*7954f716SAlexey Bayduraev 	zfree(&rec->thread_masks);
2751*7954f716SAlexey Bayduraev }
2752*7954f716SAlexey Bayduraev 
2753*7954f716SAlexey Bayduraev static int record__alloc_thread_masks(struct record *rec, int nr_threads, int nr_bits)
2754*7954f716SAlexey Bayduraev {
2755*7954f716SAlexey Bayduraev 	int t, ret;
2756*7954f716SAlexey Bayduraev 
2757*7954f716SAlexey Bayduraev 	rec->thread_masks = zalloc(nr_threads * sizeof(*(rec->thread_masks)));
2758*7954f716SAlexey Bayduraev 	if (!rec->thread_masks) {
2759*7954f716SAlexey Bayduraev 		pr_err("Failed to allocate thread masks\n");
2760*7954f716SAlexey Bayduraev 		return -ENOMEM;
2761*7954f716SAlexey Bayduraev 	}
2762*7954f716SAlexey Bayduraev 
2763*7954f716SAlexey Bayduraev 	for (t = 0; t < nr_threads; t++) {
2764*7954f716SAlexey Bayduraev 		ret = record__thread_mask_alloc(&rec->thread_masks[t], nr_bits);
2765*7954f716SAlexey Bayduraev 		if (ret) {
2766*7954f716SAlexey Bayduraev 			pr_err("Failed to allocate thread masks[%d]\n", t);
2767*7954f716SAlexey Bayduraev 			goto out_free;
2768*7954f716SAlexey Bayduraev 		}
2769*7954f716SAlexey Bayduraev 	}
2770*7954f716SAlexey Bayduraev 
2771*7954f716SAlexey Bayduraev 	return 0;
2772*7954f716SAlexey Bayduraev 
2773*7954f716SAlexey Bayduraev out_free:
2774*7954f716SAlexey Bayduraev 	record__free_thread_masks(rec, nr_threads);
2775*7954f716SAlexey Bayduraev 
2776*7954f716SAlexey Bayduraev 	return ret;
2777*7954f716SAlexey Bayduraev }
2778*7954f716SAlexey Bayduraev 
2779*7954f716SAlexey Bayduraev static int record__init_thread_default_masks(struct record *rec, struct perf_cpu_map *cpus)
2780*7954f716SAlexey Bayduraev {
2781*7954f716SAlexey Bayduraev 	int ret;
2782*7954f716SAlexey Bayduraev 
2783*7954f716SAlexey Bayduraev 	ret = record__alloc_thread_masks(rec, 1, cpu__max_cpu().cpu);
2784*7954f716SAlexey Bayduraev 	if (ret)
2785*7954f716SAlexey Bayduraev 		return ret;
2786*7954f716SAlexey Bayduraev 
2787*7954f716SAlexey Bayduraev 	record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus);
2788*7954f716SAlexey Bayduraev 
2789*7954f716SAlexey Bayduraev 	rec->nr_threads = 1;
2790*7954f716SAlexey Bayduraev 
2791*7954f716SAlexey Bayduraev 	return 0;
2792*7954f716SAlexey Bayduraev }
2793*7954f716SAlexey Bayduraev 
2794*7954f716SAlexey Bayduraev static int record__init_thread_masks(struct record *rec)
2795*7954f716SAlexey Bayduraev {
2796*7954f716SAlexey Bayduraev 	struct perf_cpu_map *cpus = rec->evlist->core.cpus;
2797*7954f716SAlexey Bayduraev 
2798*7954f716SAlexey Bayduraev 	return record__init_thread_default_masks(rec, cpus);
2799*7954f716SAlexey Bayduraev }
2800*7954f716SAlexey Bayduraev 
2801b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
280286470930SIngo Molnar {
2803ef149c25SAdrian Hunter 	int err;
28048c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
280516ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
280686470930SIngo Molnar 
280767230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
280867230479SArnaldo Carvalho de Melo 
280948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
281048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
281148e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
281248e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
281348e1cab1SWang Nan # undef set_nobuild
281448e1cab1SWang Nan #endif
281548e1cab1SWang Nan 
28167efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
28177efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
28187efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
28197efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
28207efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
28217efe0e03SHe Kuang # else
28227efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
28237efe0e03SHe Kuang # endif
28247efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
28257efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
28267efe0e03SHe Kuang # undef set_nobuild
28277efe0e03SHe Kuang # undef REASON
28287efe0e03SHe Kuang #endif
28297efe0e03SHe Kuang 
28309d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
28319d2ed645SAlexey Budankov 
28320f98b11cSJiri Olsa 	rec->evlist = evlist__new();
28333e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
2834361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
2835361c99a6SArnaldo Carvalho de Melo 
2836ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
2837ecc4c561SArnaldo Carvalho de Melo 	if (err)
2838ecc4c561SArnaldo Carvalho de Melo 		return err;
2839eb853e80SJiri Olsa 
2840bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
2841a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
284268ba3235SNamhyung Kim 	if (quiet)
284368ba3235SNamhyung Kim 		perf_quiet_option();
2844483635a9SJiri Olsa 
28457cc72553SJames Clark 	err = symbol__validate_sym_arguments();
28467cc72553SJames Clark 	if (err)
28477cc72553SJames Clark 		return err;
28487cc72553SJames Clark 
28499bce13eaSJiri Olsa 	perf_debuginfod_setup(&record.debuginfod);
28509bce13eaSJiri Olsa 
2851483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2852602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2853483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
285486470930SIngo Molnar 
2855bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2856c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2857c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2858c7118369SNamhyung Kim 
2859023695d9SStephane Eranian 	}
2860504c1ad1SAlexey Budankov 
2861e29386c8SJiri Olsa 	if (rec->buildid_mmap) {
2862e29386c8SJiri Olsa 		if (!perf_can_record_build_id()) {
2863e29386c8SJiri Olsa 			pr_err("Failed: no support to record build id in mmap events, update your kernel.\n");
2864e29386c8SJiri Olsa 			err = -EINVAL;
2865e29386c8SJiri Olsa 			goto out_opts;
2866e29386c8SJiri Olsa 		}
2867e29386c8SJiri Olsa 		pr_debug("Enabling build id in mmap2 events.\n");
2868e29386c8SJiri Olsa 		/* Enable mmap build id synthesizing. */
2869e29386c8SJiri Olsa 		symbol_conf.buildid_mmap2 = true;
2870e29386c8SJiri Olsa 		/* Enable perf_event_attr::build_id bit. */
2871e29386c8SJiri Olsa 		rec->opts.build_id = true;
2872e29386c8SJiri Olsa 		/* Disable build id cache. */
2873e29386c8SJiri Olsa 		rec->no_buildid = true;
2874e29386c8SJiri Olsa 	}
2875e29386c8SJiri Olsa 
28764f2abe91SNamhyung Kim 	if (rec->opts.record_cgroup && !perf_can_record_cgroup()) {
28774f2abe91SNamhyung Kim 		pr_err("Kernel has no cgroup sampling support.\n");
28784f2abe91SNamhyung Kim 		err = -EINVAL;
28794f2abe91SNamhyung Kim 		goto out_opts;
28804f2abe91SNamhyung Kim 	}
28814f2abe91SNamhyung Kim 
2882eeb399b5SAdrian Hunter 	if (rec->opts.kcore)
2883eeb399b5SAdrian Hunter 		rec->data.is_dir = true;
2884eeb399b5SAdrian Hunter 
2885504c1ad1SAlexey Budankov 	if (rec->opts.comp_level != 0) {
2886504c1ad1SAlexey Budankov 		pr_debug("Compression enabled, disabling build id collection at the end of the session.\n");
2887504c1ad1SAlexey Budankov 		rec->no_buildid = true;
2888504c1ad1SAlexey Budankov 	}
2889504c1ad1SAlexey Budankov 
2890b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2891b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2892c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2893c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2894a8fcbd26SAdrian Hunter 		err = -EINVAL;
2895a8fcbd26SAdrian Hunter 		goto out_opts;
2896b757bb09SAdrian Hunter 	}
2897023695d9SStephane Eranian 
2898cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2899cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2900a8fcbd26SAdrian Hunter 		err = -EINVAL;
2901a8fcbd26SAdrian Hunter 		goto out_opts;
2902cb4e1ebbSJiri Olsa 	}
2903cb4e1ebbSJiri Olsa 
2904bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2905bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2906bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2907bfacbe3bSJiri Olsa 	}
2908bfacbe3bSJiri Olsa 
290903724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
291003724b2eSAndi Kleen 		rec->switch_output.filenames = calloc(sizeof(char *),
291103724b2eSAndi Kleen 						      rec->switch_output.num_files);
2912a8fcbd26SAdrian Hunter 		if (!rec->switch_output.filenames) {
2913a8fcbd26SAdrian Hunter 			err = -EINVAL;
2914a8fcbd26SAdrian Hunter 			goto out_opts;
2915a8fcbd26SAdrian Hunter 		}
291603724b2eSAndi Kleen 	}
291703724b2eSAndi Kleen 
29181b36c03eSAdrian Hunter 	/*
29191b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
29201b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
29211b36c03eSAdrian Hunter 	 */
29221b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
29231b36c03eSAdrian Hunter 
29241b36c03eSAdrian Hunter 	symbol__init(NULL);
29251b36c03eSAdrian Hunter 
29268384a260SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS) {
29276d18804bSIan Rogers 		rec->affinity_mask.nbits = cpu__max_cpu().cpu;
29287fc5b571SAndy Shevchenko 		rec->affinity_mask.bits = bitmap_zalloc(rec->affinity_mask.nbits);
29298384a260SAlexey Budankov 		if (!rec->affinity_mask.bits) {
29308384a260SAlexey Budankov 			pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits);
2931a8fcbd26SAdrian Hunter 			err = -ENOMEM;
2932a8fcbd26SAdrian Hunter 			goto out_opts;
29338384a260SAlexey Budankov 		}
29348384a260SAlexey Budankov 		pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits);
29358384a260SAlexey Budankov 	}
29368384a260SAlexey Budankov 
29374b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
29381b36c03eSAdrian Hunter 	if (err)
29391b36c03eSAdrian Hunter 		goto out;
29401b36c03eSAdrian Hunter 
29410aab2136SWang Nan 	if (dry_run)
29425c01ad60SAdrian Hunter 		goto out;
29430aab2136SWang Nan 
2944d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2945d7888573SWang Nan 	if (err) {
2946d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2947d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2948d7888573SWang Nan 			 errbuf);
29495c01ad60SAdrian Hunter 		goto out;
2950d7888573SWang Nan 	}
2951d7888573SWang Nan 
2952ef149c25SAdrian Hunter 	err = -ENOMEM;
2953ef149c25SAdrian Hunter 
29540c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2955a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2956dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
29570c1d46a8SWang Nan 		/*
29580c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
29590c1d46a8SWang Nan 		 * generation by default to reduce data file switching
29600c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
29610c1d46a8SWang Nan 		 * explicitly using
29620c1d46a8SWang Nan 		 *
296360437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
29640c1d46a8SWang Nan 		 *              --no-no-buildid-cache
29650c1d46a8SWang Nan 		 *
29660c1d46a8SWang Nan 		 * Following code equals to:
29670c1d46a8SWang Nan 		 *
29680c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
29690c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
29700c1d46a8SWang Nan 		 *         disable_buildid_cache();
29710c1d46a8SWang Nan 		 */
29720c1d46a8SWang Nan 		bool disable = true;
29730c1d46a8SWang Nan 
29740c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
29750c1d46a8SWang Nan 			disable = false;
29760c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
29770c1d46a8SWang Nan 			disable = false;
29780c1d46a8SWang Nan 		if (disable) {
29790c1d46a8SWang Nan 			rec->no_buildid = true;
29800c1d46a8SWang Nan 			rec->no_buildid_cache = true;
29810c1d46a8SWang Nan 			disable_buildid_cache();
29820c1d46a8SWang Nan 		}
29830c1d46a8SWang Nan 	}
2984655000e7SArnaldo Carvalho de Melo 
29854ea648aeSWang Nan 	if (record.opts.overwrite)
29864ea648aeSWang Nan 		record.opts.tail_synthesize = true;
29874ea648aeSWang Nan 
2988b53a0755SJin Yao 	if (rec->evlist->core.nr_entries == 0) {
2989b53a0755SJin Yao 		if (perf_pmu__has_hybrid()) {
2990b53a0755SJin Yao 			err = evlist__add_default_hybrid(rec->evlist,
2991b53a0755SJin Yao 							 !record.opts.no_samples);
2992b53a0755SJin Yao 		} else {
2993b53a0755SJin Yao 			err = __evlist__add_default(rec->evlist,
2994b53a0755SJin Yao 						    !record.opts.no_samples);
2995b53a0755SJin Yao 		}
2996b53a0755SJin Yao 
2997b53a0755SJin Yao 		if (err < 0) {
299869aad6f1SArnaldo Carvalho de Melo 			pr_err("Not enough memory for event selector list\n");
2999394c01edSAdrian Hunter 			goto out;
3000bbd36e5eSPeter Zijlstra 		}
3001b53a0755SJin Yao 	}
300286470930SIngo Molnar 
300369e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
300469e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
300569e7e5b0SAdrian Hunter 
3006602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
300716ad2ffbSNamhyung Kim 	if (err) {
3008602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
3009c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
301016ad2ffbSNamhyung Kim 	}
30114bd0f2d2SNamhyung Kim 
3012602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
301316ad2ffbSNamhyung Kim 	if (err) {
301416ad2ffbSNamhyung Kim 		int saved_errno = errno;
301516ad2ffbSNamhyung Kim 
3016602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
30173780f488SNamhyung Kim 		ui__error("%s", errbuf);
301816ad2ffbSNamhyung Kim 
301916ad2ffbSNamhyung Kim 		err = -saved_errno;
3020394c01edSAdrian Hunter 		goto out;
302116ad2ffbSNamhyung Kim 	}
30220d37aa34SArnaldo Carvalho de Melo 
3023ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
3024ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
302523dc4f15SJiri Olsa 
30261d3351e6SJin Yao 	if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) {
30271d3351e6SJin Yao 		pr_err("failed to use cpu list %s\n",
30281d3351e6SJin Yao 		       rec->opts.target.cpu_list);
30291d3351e6SJin Yao 		goto out;
30301d3351e6SJin Yao 	}
30311d3351e6SJin Yao 
30321d3351e6SJin Yao 	rec->opts.target.hybrid = perf_pmu__has_hybrid();
30337248e308SAlexandre Truong 
30347248e308SAlexandre Truong 	if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP)
30357248e308SAlexandre Truong 		arch__add_leaf_frame_record_opts(&rec->opts);
30367248e308SAlexandre Truong 
303716ad2ffbSNamhyung Kim 	err = -ENOMEM;
30387748bb71SArnaldo Carvalho de Melo 	if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
3039dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
304069aad6f1SArnaldo Carvalho de Melo 
3041ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
3042ef149c25SAdrian Hunter 	if (err)
3043394c01edSAdrian Hunter 		goto out;
3044ef149c25SAdrian Hunter 
30456156681bSNamhyung Kim 	/*
30466156681bSNamhyung Kim 	 * We take all buildids when the file contains
30476156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
30486156681bSNamhyung Kim 	 * trace because it would take too long.
30496156681bSNamhyung Kim 	 */
30506156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
30516156681bSNamhyung Kim 		rec->buildid_all = true;
30526156681bSNamhyung Kim 
3053246eba8eSAdrian Hunter 	if (rec->opts.text_poke) {
3054246eba8eSAdrian Hunter 		err = record__config_text_poke(rec->evlist);
3055246eba8eSAdrian Hunter 		if (err) {
3056246eba8eSAdrian Hunter 			pr_err("record__config_text_poke failed, error %d\n", err);
3057246eba8eSAdrian Hunter 			goto out;
3058246eba8eSAdrian Hunter 		}
3059246eba8eSAdrian Hunter 	}
3060246eba8eSAdrian Hunter 
3061b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
306239d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
3063394c01edSAdrian Hunter 		goto out;
30647e4ff9e3SMike Galbraith 	}
30657e4ff9e3SMike Galbraith 
3066*7954f716SAlexey Bayduraev 	err = record__init_thread_masks(rec);
3067*7954f716SAlexey Bayduraev 	if (err) {
3068*7954f716SAlexey Bayduraev 		pr_err("Failed to initialize parallel data streaming masks\n");
3069*7954f716SAlexey Bayduraev 		goto out;
3070*7954f716SAlexey Bayduraev 	}
3071*7954f716SAlexey Bayduraev 
307293f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
307393f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
30745d7f4116SAlexey Budankov 	pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks);
3075d3d1af6fSAlexey Budankov 
30769d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
3077470530bbSAlexey Budankov 	pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
30789d2ed645SAlexey Budankov 
307951255a8aSAlexey Budankov 	if (rec->opts.comp_level > comp_level_max)
308051255a8aSAlexey Budankov 		rec->opts.comp_level = comp_level_max;
308151255a8aSAlexey Budankov 	pr_debug("comp level: %d\n", rec->opts.comp_level);
308251255a8aSAlexey Budankov 
3083d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
3084394c01edSAdrian Hunter out:
30858384a260SAlexey Budankov 	bitmap_free(rec->affinity_mask.bits);
3086c12995a5SJiri Olsa 	evlist__delete(rec->evlist);
3087d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
3088ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
3089a8fcbd26SAdrian Hunter out_opts:
3090*7954f716SAlexey Bayduraev 	record__free_thread_masks(rec, rec->nr_threads);
3091*7954f716SAlexey Bayduraev 	rec->nr_threads = 0;
3092ee7fe31eSAdrian Hunter 	evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close);
309339d17dacSArnaldo Carvalho de Melo 	return err;
309486470930SIngo Molnar }
30952dd6d8a1SAdrian Hunter 
30962dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
30972dd6d8a1SAdrian Hunter {
3098dc0c6127SJiri Olsa 	struct record *rec = &record;
3099dc0c6127SJiri Olsa 
3100d20aff15SAdrian Hunter 	hit_auxtrace_snapshot_trigger(rec);
31013c1cb7e3SWang Nan 
3102dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
31033c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
31042dd6d8a1SAdrian Hunter }
3105bfacbe3bSJiri Olsa 
3106bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
3107bfacbe3bSJiri Olsa {
3108bfacbe3bSJiri Olsa 	struct record *rec = &record;
3109bfacbe3bSJiri Olsa 
3110bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
3111bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
3112bfacbe3bSJiri Olsa }
3113