xref: /openbmc/linux/tools/perf/builtin-record.c (revision 8e5bc76f2ce39ffd48350d6dd9318d78d07b0bfa)
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 
1186470930SIngo Molnar #include "perf.h"
1286470930SIngo Molnar 
136122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1486470930SIngo Molnar #include "util/util.h"
154b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1686470930SIngo Molnar #include "util/parse-events.h"
1741840d21STaeung Song #include "util/config.h"
1886470930SIngo Molnar 
198f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
20f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
217c6a1c65SPeter Zijlstra #include "util/header.h"
2266e274f3SFrederic Weisbecker #include "util/event.h"
23361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2469aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
258f28827aSFrederic Weisbecker #include "util/debug.h"
2694c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
288d06367fSArnaldo Carvalho de Melo #include "util/symbol.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"
3771dc2326SWang Nan #include "util/llvm-utils.h"
388690a2a7SWang Nan #include "util/bpf-loader.h"
395f9cf599SWang Nan #include "util/trigger.h"
40a074865eSWang Nan #include "util/perf-hooks.h"
41f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
447b612e29SSong Liu #include "util/bpf-event.h"
45d8871ea7SWang Nan #include "asm/bug.h"
467c6a1c65SPeter Zijlstra 
47a43783aeSArnaldo Carvalho de Melo #include <errno.h>
48fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
4967230479SArnaldo Carvalho de Melo #include <locale.h>
504208735dSArnaldo Carvalho de Melo #include <poll.h>
5186470930SIngo Molnar #include <unistd.h>
5286470930SIngo Molnar #include <sched.h>
539607ad3aSArnaldo Carvalho de Melo #include <signal.h>
54a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
554208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
560693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
5778da39faSBernhard Rosenkraenzer 
581b43b704SJiri Olsa struct switch_output {
59dc0c6127SJiri Olsa 	bool		 enabled;
601b43b704SJiri Olsa 	bool		 signal;
61dc0c6127SJiri Olsa 	unsigned long	 size;
62bfacbe3bSJiri Olsa 	unsigned long	 time;
63cb4e1ebbSJiri Olsa 	const char	*str;
64cb4e1ebbSJiri Olsa 	bool		 set;
6503724b2eSAndi Kleen 	char		 **filenames;
6603724b2eSAndi Kleen 	int		 num_files;
6703724b2eSAndi Kleen 	int		 cur_file;
681b43b704SJiri Olsa };
691b43b704SJiri Olsa 
708c6f45a7SArnaldo Carvalho de Melo struct record {
7145694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
72b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
73d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
748ceb41d7SJiri Olsa 	struct perf_data	data;
75ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
76d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
77d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
78d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
79d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
80d2db9a98SWang Nan 	bool			no_buildid_set;
81d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
82d2db9a98SWang Nan 	bool			no_buildid_cache_set;
836156681bSNamhyung Kim 	bool			buildid_all;
84ecfd7a9cSWang Nan 	bool			timestamp_filename;
8568588bafSJin Yao 	bool			timestamp_boundary;
861b43b704SJiri Olsa 	struct switch_output	switch_output;
879f065194SYang Shi 	unsigned long long	samples;
889d2ed645SAlexey Budankov 	cpu_set_t		affinity_mask;
890f82ebc4SArnaldo Carvalho de Melo };
9086470930SIngo Molnar 
91dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
92dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
93dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
94dc0c6127SJiri Olsa 
959d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
969d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
979d2ed645SAlexey Budankov };
989d2ed645SAlexey Budankov 
99dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
100dc0c6127SJiri Olsa {
101dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
102dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
103dc0c6127SJiri Olsa }
104dc0c6127SJiri Olsa 
105dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
106dc0c6127SJiri Olsa {
107dc0c6127SJiri Olsa 	return rec->switch_output.size &&
108dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
109dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
110dc0c6127SJiri Olsa }
111dc0c6127SJiri Olsa 
112bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
113bfacbe3bSJiri Olsa {
114bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
115bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
116bfacbe3bSJiri Olsa }
117bfacbe3bSJiri Olsa 
118ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
119ded2b8feSJiri Olsa 			 void *bf, size_t size)
120f5970550SPeter Zijlstra {
121ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
122ded2b8feSJiri Olsa 
123ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1244f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1258d3eca20SDavid Ahern 		return -1;
1268d3eca20SDavid Ahern 	}
127f5970550SPeter Zijlstra 
128cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
129dc0c6127SJiri Olsa 
130dc0c6127SJiri Olsa 	if (switch_output_size(rec))
131dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
132dc0c6127SJiri Olsa 
1338d3eca20SDavid Ahern 	return 0;
134f5970550SPeter Zijlstra }
135f5970550SPeter Zijlstra 
136d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
137d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
138d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
139d3d1af6fSAlexey Budankov {
140d3d1af6fSAlexey Budankov 	int rc;
141d3d1af6fSAlexey Budankov 
142d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
143d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
144d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
145d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
146d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
147d3d1af6fSAlexey Budankov 
148d3d1af6fSAlexey Budankov 	do {
149d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
150d3d1af6fSAlexey Budankov 		if (rc == 0) {
151d3d1af6fSAlexey Budankov 			break;
152d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
153d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
154d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
155d3d1af6fSAlexey Budankov 			break;
156d3d1af6fSAlexey Budankov 		}
157d3d1af6fSAlexey Budankov 	} while (1);
158d3d1af6fSAlexey Budankov 
159d3d1af6fSAlexey Budankov 	return rc;
160d3d1af6fSAlexey Budankov }
161d3d1af6fSAlexey Budankov 
162d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock)
163d3d1af6fSAlexey Budankov {
164d3d1af6fSAlexey Budankov 	void *rem_buf;
165d3d1af6fSAlexey Budankov 	off_t rem_off;
166d3d1af6fSAlexey Budankov 	size_t rem_size;
167d3d1af6fSAlexey Budankov 	int rc, aio_errno;
168d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
169d3d1af6fSAlexey Budankov 
170d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
171d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
172d3d1af6fSAlexey Budankov 		return 0;
173d3d1af6fSAlexey Budankov 
174d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
175d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
176d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
177d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
178d3d1af6fSAlexey Budankov 		written = 0;
179d3d1af6fSAlexey Budankov 	}
180d3d1af6fSAlexey Budankov 
181d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
182d3d1af6fSAlexey Budankov 
183d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
184d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
185d3d1af6fSAlexey Budankov 		/*
186d3d1af6fSAlexey Budankov 		 * md->refcount is incremented in perf_mmap__push() for
187d3d1af6fSAlexey Budankov 		 * every enqueued aio write request so decrement it because
188d3d1af6fSAlexey Budankov 		 * the request is now complete.
189d3d1af6fSAlexey Budankov 		 */
190d3d1af6fSAlexey Budankov 		perf_mmap__put(md);
191d3d1af6fSAlexey Budankov 		rc = 1;
192d3d1af6fSAlexey Budankov 	} else {
193d3d1af6fSAlexey Budankov 		/*
194d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
195d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
196d3d1af6fSAlexey Budankov 		 * chunk at once.
197d3d1af6fSAlexey Budankov 		 */
198d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
199d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
200d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
201d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
202d3d1af6fSAlexey Budankov 		rc = 0;
203d3d1af6fSAlexey Budankov 	}
204d3d1af6fSAlexey Budankov 
205d3d1af6fSAlexey Budankov 	return rc;
206d3d1af6fSAlexey Budankov }
207d3d1af6fSAlexey Budankov 
20893f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all)
209d3d1af6fSAlexey Budankov {
21093f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
21193f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
212d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
21393f20c0fSAlexey Budankov 	int i, do_suspend;
214d3d1af6fSAlexey Budankov 
215d3d1af6fSAlexey Budankov 	do {
21693f20c0fSAlexey Budankov 		do_suspend = 0;
21793f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
21893f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
21993f20c0fSAlexey Budankov 				if (sync_all)
22093f20c0fSAlexey Budankov 					aiocb[i] = NULL;
22193f20c0fSAlexey Budankov 				else
22293f20c0fSAlexey Budankov 					return i;
22393f20c0fSAlexey Budankov 			} else {
22493f20c0fSAlexey Budankov 				/*
22593f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
22693f20c0fSAlexey Budankov 				 * so it has to be waited before the
22793f20c0fSAlexey Budankov 				 * next allocation.
22893f20c0fSAlexey Budankov 				 */
22993f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
23093f20c0fSAlexey Budankov 				do_suspend = 1;
23193f20c0fSAlexey Budankov 			}
23293f20c0fSAlexey Budankov 		}
23393f20c0fSAlexey Budankov 		if (!do_suspend)
23493f20c0fSAlexey Budankov 			return -1;
235d3d1af6fSAlexey Budankov 
23693f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
237d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
238d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
239d3d1af6fSAlexey Budankov 		}
240d3d1af6fSAlexey Budankov 	} while (1);
241d3d1af6fSAlexey Budankov }
242d3d1af6fSAlexey Budankov 
243d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off)
244d3d1af6fSAlexey Budankov {
245d3d1af6fSAlexey Budankov 	struct record *rec = to;
246d3d1af6fSAlexey Budankov 	int ret, trace_fd = rec->session->data->file.fd;
247d3d1af6fSAlexey Budankov 
248d3d1af6fSAlexey Budankov 	rec->samples++;
249d3d1af6fSAlexey Budankov 
250d3d1af6fSAlexey Budankov 	ret = record__aio_write(cblock, trace_fd, bf, size, off);
251d3d1af6fSAlexey Budankov 	if (!ret) {
252d3d1af6fSAlexey Budankov 		rec->bytes_written += size;
253d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
254d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
255d3d1af6fSAlexey Budankov 	}
256d3d1af6fSAlexey Budankov 
257d3d1af6fSAlexey Budankov 	return ret;
258d3d1af6fSAlexey Budankov }
259d3d1af6fSAlexey Budankov 
260d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
261d3d1af6fSAlexey Budankov {
262d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
263d3d1af6fSAlexey Budankov }
264d3d1af6fSAlexey Budankov 
265d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
266d3d1af6fSAlexey Budankov {
267d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
268d3d1af6fSAlexey Budankov }
269d3d1af6fSAlexey Budankov 
270d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
271d3d1af6fSAlexey Budankov {
272d3d1af6fSAlexey Budankov 	int i;
273d3d1af6fSAlexey Budankov 	struct perf_evlist *evlist = rec->evlist;
274d3d1af6fSAlexey Budankov 	struct perf_mmap *maps = evlist->mmap;
275d3d1af6fSAlexey Budankov 
276d3d1af6fSAlexey Budankov 	if (!rec->opts.nr_cblocks)
277d3d1af6fSAlexey Budankov 		return;
278d3d1af6fSAlexey Budankov 
279d3d1af6fSAlexey Budankov 	for (i = 0; i < evlist->nr_mmaps; i++) {
280d3d1af6fSAlexey Budankov 		struct perf_mmap *map = &maps[i];
281d3d1af6fSAlexey Budankov 
282d3d1af6fSAlexey Budankov 		if (map->base)
28393f20c0fSAlexey Budankov 			record__aio_sync(map, true);
284d3d1af6fSAlexey Budankov 	}
285d3d1af6fSAlexey Budankov }
286d3d1af6fSAlexey Budankov 
287d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
28893f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
289d3d1af6fSAlexey Budankov 
290d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
29193f20c0fSAlexey Budankov 			     const char *str,
292d3d1af6fSAlexey Budankov 			     int unset)
293d3d1af6fSAlexey Budankov {
294d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
295d3d1af6fSAlexey Budankov 
29693f20c0fSAlexey Budankov 	if (unset) {
297d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
29893f20c0fSAlexey Budankov 	} else {
29993f20c0fSAlexey Budankov 		if (str)
30093f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
30193f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
302d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
30393f20c0fSAlexey Budankov 	}
304d3d1af6fSAlexey Budankov 
305d3d1af6fSAlexey Budankov 	return 0;
306d3d1af6fSAlexey Budankov }
307d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
30893f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
30993f20c0fSAlexey Budankov 
31093f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused)
311d3d1af6fSAlexey Budankov {
31293f20c0fSAlexey Budankov 	return -1;
313d3d1af6fSAlexey Budankov }
314d3d1af6fSAlexey Budankov 
315d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused,
316d3d1af6fSAlexey Budankov 		void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused)
317d3d1af6fSAlexey Budankov {
318d3d1af6fSAlexey Budankov 	return -1;
319d3d1af6fSAlexey Budankov }
320d3d1af6fSAlexey Budankov 
321d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
322d3d1af6fSAlexey Budankov {
323d3d1af6fSAlexey Budankov 	return -1;
324d3d1af6fSAlexey Budankov }
325d3d1af6fSAlexey Budankov 
326d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
327d3d1af6fSAlexey Budankov {
328d3d1af6fSAlexey Budankov }
329d3d1af6fSAlexey Budankov 
330d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
331d3d1af6fSAlexey Budankov {
332d3d1af6fSAlexey Budankov }
333d3d1af6fSAlexey Budankov #endif
334d3d1af6fSAlexey Budankov 
335d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
336d3d1af6fSAlexey Budankov {
337d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
338d3d1af6fSAlexey Budankov }
339d3d1af6fSAlexey Budankov 
340470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
341470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
342470530bbSAlexey Budankov 				    const char *str,
343470530bbSAlexey Budankov 				    int unset)
344470530bbSAlexey Budankov {
345470530bbSAlexey Budankov 	int flush_max;
346470530bbSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
347470530bbSAlexey Budankov 	static struct parse_tag tags[] = {
348470530bbSAlexey Budankov 			{ .tag  = 'B', .mult = 1       },
349470530bbSAlexey Budankov 			{ .tag  = 'K', .mult = 1 << 10 },
350470530bbSAlexey Budankov 			{ .tag  = 'M', .mult = 1 << 20 },
351470530bbSAlexey Budankov 			{ .tag  = 'G', .mult = 1 << 30 },
352470530bbSAlexey Budankov 			{ .tag  = 0 },
353470530bbSAlexey Budankov 	};
354470530bbSAlexey Budankov 
355470530bbSAlexey Budankov 	if (unset)
356470530bbSAlexey Budankov 		return 0;
357470530bbSAlexey Budankov 
358470530bbSAlexey Budankov 	if (str) {
359470530bbSAlexey Budankov 		opts->mmap_flush = parse_tag_value(str, tags);
360470530bbSAlexey Budankov 		if (opts->mmap_flush == (int)-1)
361470530bbSAlexey Budankov 			opts->mmap_flush = strtol(str, NULL, 0);
362470530bbSAlexey Budankov 	}
363470530bbSAlexey Budankov 
364470530bbSAlexey Budankov 	if (!opts->mmap_flush)
365470530bbSAlexey Budankov 		opts->mmap_flush = MMAP_FLUSH_DEFAULT;
366470530bbSAlexey Budankov 
367470530bbSAlexey Budankov 	flush_max = perf_evlist__mmap_size(opts->mmap_pages);
368470530bbSAlexey Budankov 	flush_max /= 4;
369470530bbSAlexey Budankov 	if (opts->mmap_flush > flush_max)
370470530bbSAlexey Budankov 		opts->mmap_flush = flush_max;
371470530bbSAlexey Budankov 
372470530bbSAlexey Budankov 	return 0;
373470530bbSAlexey Budankov }
374470530bbSAlexey Budankov 
37545694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
376d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
3771d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
3781d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
379234fbbf5SArnaldo Carvalho de Melo {
3808c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
381ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
382234fbbf5SArnaldo Carvalho de Melo }
383234fbbf5SArnaldo Carvalho de Melo 
384ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
385d37f1586SArnaldo Carvalho de Melo {
386d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
387d37f1586SArnaldo Carvalho de Melo 
388d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
389ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
390d37f1586SArnaldo Carvalho de Melo }
391d37f1586SArnaldo Carvalho de Melo 
3922dd6d8a1SAdrian Hunter static volatile int done;
3932dd6d8a1SAdrian Hunter static volatile int signr = -1;
3942dd6d8a1SAdrian Hunter static volatile int child_finished;
395c0bdc1c4SWang Nan 
3962dd6d8a1SAdrian Hunter static void sig_handler(int sig)
3972dd6d8a1SAdrian Hunter {
3982dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
3992dd6d8a1SAdrian Hunter 		child_finished = 1;
4002dd6d8a1SAdrian Hunter 	else
4012dd6d8a1SAdrian Hunter 		signr = sig;
4022dd6d8a1SAdrian Hunter 
4032dd6d8a1SAdrian Hunter 	done = 1;
4042dd6d8a1SAdrian Hunter }
4052dd6d8a1SAdrian Hunter 
406a074865eSWang Nan static void sigsegv_handler(int sig)
407a074865eSWang Nan {
408a074865eSWang Nan 	perf_hooks__recover();
409a074865eSWang Nan 	sighandler_dump_stack(sig);
410a074865eSWang Nan }
411a074865eSWang Nan 
4122dd6d8a1SAdrian Hunter static void record__sig_exit(void)
4132dd6d8a1SAdrian Hunter {
4142dd6d8a1SAdrian Hunter 	if (signr == -1)
4152dd6d8a1SAdrian Hunter 		return;
4162dd6d8a1SAdrian Hunter 
4172dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
4182dd6d8a1SAdrian Hunter 	raise(signr);
4192dd6d8a1SAdrian Hunter }
4202dd6d8a1SAdrian Hunter 
421e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
422e31f0d01SAdrian Hunter 
423ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
424ded2b8feSJiri Olsa 				    struct perf_mmap *map,
425ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
426ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
427ef149c25SAdrian Hunter {
428ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
4298ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
430ef149c25SAdrian Hunter 	size_t padding;
431ef149c25SAdrian Hunter 	u8 pad[8] = {0};
432ef149c25SAdrian Hunter 
433cd3dd8ddSJiri Olsa 	if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) {
43499fa2984SAdrian Hunter 		off_t file_offset;
4358ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
43699fa2984SAdrian Hunter 		int err;
43799fa2984SAdrian Hunter 
43899fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
43999fa2984SAdrian Hunter 		if (file_offset == -1)
44099fa2984SAdrian Hunter 			return -1;
44199fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
44299fa2984SAdrian Hunter 						     event, file_offset);
44399fa2984SAdrian Hunter 		if (err)
44499fa2984SAdrian Hunter 			return err;
44599fa2984SAdrian Hunter 	}
44699fa2984SAdrian Hunter 
447ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
448ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
449ef149c25SAdrian Hunter 	if (padding)
450ef149c25SAdrian Hunter 		padding = 8 - padding;
451ef149c25SAdrian Hunter 
452ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
453ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
454ef149c25SAdrian Hunter 	if (len2)
455ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
456ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
457ef149c25SAdrian Hunter 
458ef149c25SAdrian Hunter 	return 0;
459ef149c25SAdrian Hunter }
460ef149c25SAdrian Hunter 
461ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
462e035f4caSJiri Olsa 				      struct perf_mmap *map)
463ef149c25SAdrian Hunter {
464ef149c25SAdrian Hunter 	int ret;
465ef149c25SAdrian Hunter 
466e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
467ef149c25SAdrian Hunter 				  record__process_auxtrace);
468ef149c25SAdrian Hunter 	if (ret < 0)
469ef149c25SAdrian Hunter 		return ret;
470ef149c25SAdrian Hunter 
471ef149c25SAdrian Hunter 	if (ret)
472ef149c25SAdrian Hunter 		rec->samples++;
473ef149c25SAdrian Hunter 
474ef149c25SAdrian Hunter 	return 0;
475ef149c25SAdrian Hunter }
476ef149c25SAdrian Hunter 
4772dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
478e035f4caSJiri Olsa 					       struct perf_mmap *map)
4792dd6d8a1SAdrian Hunter {
4802dd6d8a1SAdrian Hunter 	int ret;
4812dd6d8a1SAdrian Hunter 
482e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
4832dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
4842dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
4852dd6d8a1SAdrian Hunter 	if (ret < 0)
4862dd6d8a1SAdrian Hunter 		return ret;
4872dd6d8a1SAdrian Hunter 
4882dd6d8a1SAdrian Hunter 	if (ret)
4892dd6d8a1SAdrian Hunter 		rec->samples++;
4902dd6d8a1SAdrian Hunter 
4912dd6d8a1SAdrian Hunter 	return 0;
4922dd6d8a1SAdrian Hunter }
4932dd6d8a1SAdrian Hunter 
4942dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
4952dd6d8a1SAdrian Hunter {
4962dd6d8a1SAdrian Hunter 	int i;
4972dd6d8a1SAdrian Hunter 	int rc = 0;
4982dd6d8a1SAdrian Hunter 
4992dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
500e035f4caSJiri Olsa 		struct perf_mmap *map = &rec->evlist->mmap[i];
5012dd6d8a1SAdrian Hunter 
502e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
5032dd6d8a1SAdrian Hunter 			continue;
5042dd6d8a1SAdrian Hunter 
505e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
5062dd6d8a1SAdrian Hunter 			rc = -1;
5072dd6d8a1SAdrian Hunter 			goto out;
5082dd6d8a1SAdrian Hunter 		}
5092dd6d8a1SAdrian Hunter 	}
5102dd6d8a1SAdrian Hunter out:
5112dd6d8a1SAdrian Hunter 	return rc;
5122dd6d8a1SAdrian Hunter }
5132dd6d8a1SAdrian Hunter 
5142dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
5152dd6d8a1SAdrian Hunter {
5162dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
5172dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
5185f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
5192dd6d8a1SAdrian Hunter 	} else {
5205f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
5215f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
5225f9cf599SWang Nan 		else
5235f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
5242dd6d8a1SAdrian Hunter 	}
5252dd6d8a1SAdrian Hunter }
5262dd6d8a1SAdrian Hunter 
5274b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
5284b5ea3bdSAdrian Hunter {
5294b5ea3bdSAdrian Hunter 	int err;
5304b5ea3bdSAdrian Hunter 
5314b5ea3bdSAdrian Hunter 	if (!rec->itr) {
5324b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
5334b5ea3bdSAdrian Hunter 		if (err)
5344b5ea3bdSAdrian Hunter 			return err;
5354b5ea3bdSAdrian Hunter 	}
5364b5ea3bdSAdrian Hunter 
5374b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
5384b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
5394b5ea3bdSAdrian Hunter 	if (err)
5404b5ea3bdSAdrian Hunter 		return err;
5414b5ea3bdSAdrian Hunter 
5424b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
5434b5ea3bdSAdrian Hunter }
5444b5ea3bdSAdrian Hunter 
545e31f0d01SAdrian Hunter #else
546e31f0d01SAdrian Hunter 
547e31f0d01SAdrian Hunter static inline
548e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
549e035f4caSJiri Olsa 			       struct perf_mmap *map __maybe_unused)
550e31f0d01SAdrian Hunter {
551e31f0d01SAdrian Hunter 	return 0;
552e31f0d01SAdrian Hunter }
553e31f0d01SAdrian Hunter 
5542dd6d8a1SAdrian Hunter static inline
5552dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
5562dd6d8a1SAdrian Hunter {
5572dd6d8a1SAdrian Hunter }
5582dd6d8a1SAdrian Hunter 
5592dd6d8a1SAdrian Hunter static inline
5602dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
5612dd6d8a1SAdrian Hunter {
5622dd6d8a1SAdrian Hunter 	return 0;
5632dd6d8a1SAdrian Hunter }
5642dd6d8a1SAdrian Hunter 
5654b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
5664b5ea3bdSAdrian Hunter {
5674b5ea3bdSAdrian Hunter 	return 0;
5684b5ea3bdSAdrian Hunter }
5694b5ea3bdSAdrian Hunter 
570e31f0d01SAdrian Hunter #endif
571e31f0d01SAdrian Hunter 
572cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
573cda57a8cSWang Nan 			       struct perf_evlist *evlist)
574cda57a8cSWang Nan {
575cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
576cda57a8cSWang Nan 	char msg[512];
577cda57a8cSWang Nan 
578f13de660SAlexey Budankov 	if (opts->affinity != PERF_AFFINITY_SYS)
579f13de660SAlexey Budankov 		cpu__setup_cpunode_map();
580f13de660SAlexey Budankov 
5817a276ff6SWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
582cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
5839d2ed645SAlexey Budankov 				 opts->auxtrace_snapshot_mode,
584470530bbSAlexey Budankov 				 opts->nr_cblocks, opts->affinity,
585470530bbSAlexey Budankov 				 opts->mmap_flush) < 0) {
586cda57a8cSWang Nan 		if (errno == EPERM) {
587cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
588cda57a8cSWang Nan 			       "Consider increasing "
589cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
590cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
591cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
592cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
593cda57a8cSWang Nan 			return -errno;
594cda57a8cSWang Nan 		} else {
595cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
596c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
597cda57a8cSWang Nan 			if (errno)
598cda57a8cSWang Nan 				return -errno;
599cda57a8cSWang Nan 			else
600cda57a8cSWang Nan 				return -EINVAL;
601cda57a8cSWang Nan 		}
602cda57a8cSWang Nan 	}
603cda57a8cSWang Nan 	return 0;
604cda57a8cSWang Nan }
605cda57a8cSWang Nan 
606cda57a8cSWang Nan static int record__mmap(struct record *rec)
607cda57a8cSWang Nan {
608cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
609cda57a8cSWang Nan }
610cda57a8cSWang Nan 
6118c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
612dd7927f4SArnaldo Carvalho de Melo {
613d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
6146a4bb04cSJiri Olsa 	struct perf_evsel *pos;
615d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
616d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
617b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
6188d3eca20SDavid Ahern 	int rc = 0;
619dd7927f4SArnaldo Carvalho de Melo 
620d3dbf43cSArnaldo Carvalho de Melo 	/*
621d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
622d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
623d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
624d3dbf43cSArnaldo Carvalho de Melo 	 */
625d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
626d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
627d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
628d3dbf43cSArnaldo Carvalho de Melo 
629d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__first(evlist);
630d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
631d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__last(evlist);
632d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
633d3dbf43cSArnaldo Carvalho de Melo 		pos->attr.enable_on_exec = 1;
634d3dbf43cSArnaldo Carvalho de Melo 	}
635d3dbf43cSArnaldo Carvalho de Melo 
636e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
637cac21425SJiri Olsa 
638e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
6393da297a6SIngo Molnar try_again:
640d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
64156e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
642bb963e16SNamhyung Kim 				if (verbose > 0)
643c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
6443da297a6SIngo Molnar 				goto try_again;
6453da297a6SIngo Molnar 			}
646cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
647cf99ad14SAndi Kleen 			    pos->leader != pos &&
648cf99ad14SAndi Kleen 			    pos->weak_group) {
649cf99ad14SAndi Kleen 			        pos = perf_evlist__reset_weak_group(evlist, pos);
650cf99ad14SAndi Kleen 				goto try_again;
651cf99ad14SAndi Kleen 			}
65256e52e85SArnaldo Carvalho de Melo 			rc = -errno;
65356e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
65456e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
65556e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
6568d3eca20SDavid Ahern 			goto out;
6577c6a1c65SPeter Zijlstra 		}
658bfd8f72cSAndi Kleen 
659bfd8f72cSAndi Kleen 		pos->supported = true;
6607c6a1c65SPeter Zijlstra 	}
6617c6a1c65SPeter Zijlstra 
66223d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
66362d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
66423d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
665c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
6668d3eca20SDavid Ahern 		rc = -1;
6678d3eca20SDavid Ahern 		goto out;
6680a102479SFrederic Weisbecker 	}
6690a102479SFrederic Weisbecker 
670cda57a8cSWang Nan 	rc = record__mmap(rec);
671cda57a8cSWang Nan 	if (rc)
6728d3eca20SDavid Ahern 		goto out;
6730a27d7f9SArnaldo Carvalho de Melo 
674a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
6757b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
6768d3eca20SDavid Ahern out:
6778d3eca20SDavid Ahern 	return rc;
678a91e5431SArnaldo Carvalho de Melo }
679a91e5431SArnaldo Carvalho de Melo 
680e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
681e3d59112SNamhyung Kim 				union perf_event *event,
682e3d59112SNamhyung Kim 				struct perf_sample *sample,
683e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
684e3d59112SNamhyung Kim 				struct machine *machine)
685e3d59112SNamhyung Kim {
686e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
687e3d59112SNamhyung Kim 
68868588bafSJin Yao 	if (rec->evlist->first_sample_time == 0)
68968588bafSJin Yao 		rec->evlist->first_sample_time = sample->time;
690e3d59112SNamhyung Kim 
69168588bafSJin Yao 	rec->evlist->last_sample_time = sample->time;
69268588bafSJin Yao 
69368588bafSJin Yao 	if (rec->buildid_all)
69468588bafSJin Yao 		return 0;
69568588bafSJin Yao 
69668588bafSJin Yao 	rec->samples++;
697e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
698e3d59112SNamhyung Kim }
699e3d59112SNamhyung Kim 
7008c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
7016122e4e4SArnaldo Carvalho de Melo {
702f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
7036122e4e4SArnaldo Carvalho de Melo 
70445112e89SJiri Olsa 	if (perf_data__size(&rec->data) == 0)
7059f591fd7SArnaldo Carvalho de Melo 		return 0;
7069f591fd7SArnaldo Carvalho de Melo 
70700dc8657SNamhyung Kim 	/*
70800dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
70900dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
71000dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
71100dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
71200dc8657SNamhyung Kim 	 *
71300dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
71400dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
71500dc8657SNamhyung Kim 	 */
71600dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
71700dc8657SNamhyung Kim 
7186156681bSNamhyung Kim 	/*
7196156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
72068588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
72168588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
72268588bafSJin Yao 	 * first/last samples.
7236156681bSNamhyung Kim 	 */
72468588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
7256156681bSNamhyung Kim 		rec->tool.sample = NULL;
7266156681bSNamhyung Kim 
727b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
7286122e4e4SArnaldo Carvalho de Melo }
7296122e4e4SArnaldo Carvalho de Melo 
7308115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
731a1645ce1SZhang, Yanmin {
732a1645ce1SZhang, Yanmin 	int err;
73345694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
734a1645ce1SZhang, Yanmin 	/*
735a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
736a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
737a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
738a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
739a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
740a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
741a1645ce1SZhang, Yanmin 	 */
74245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
743743eb868SArnaldo Carvalho de Melo 					     machine);
744a1645ce1SZhang, Yanmin 	if (err < 0)
745a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
74623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
747a1645ce1SZhang, Yanmin 
748a1645ce1SZhang, Yanmin 	/*
749a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
750a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
751a1645ce1SZhang, Yanmin 	 */
75245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
7530ae617beSAdrian Hunter 						 machine);
754a1645ce1SZhang, Yanmin 	if (err < 0)
755a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
75623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
757a1645ce1SZhang, Yanmin }
758a1645ce1SZhang, Yanmin 
75998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
76098402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
76198402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
76298402807SFrederic Weisbecker };
76398402807SFrederic Weisbecker 
764f13de660SAlexey Budankov static void record__adjust_affinity(struct record *rec, struct perf_mmap *map)
765f13de660SAlexey Budankov {
766f13de660SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS &&
767f13de660SAlexey Budankov 	    !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
768f13de660SAlexey Budankov 		CPU_ZERO(&rec->affinity_mask);
769f13de660SAlexey Budankov 		CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
770f13de660SAlexey Budankov 		sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
771f13de660SAlexey Budankov 	}
772f13de660SAlexey Budankov }
773f13de660SAlexey Budankov 
774a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
775470530bbSAlexey Budankov 				    bool overwrite, bool synch)
77698402807SFrederic Weisbecker {
777dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
7780e2e63ddSPeter Zijlstra 	int i;
7798d3eca20SDavid Ahern 	int rc = 0;
780a4ea0ec4SWang Nan 	struct perf_mmap *maps;
781d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
782d3d1af6fSAlexey Budankov 	off_t off;
78398402807SFrederic Weisbecker 
784cb21686bSWang Nan 	if (!evlist)
785cb21686bSWang Nan 		return 0;
786ef149c25SAdrian Hunter 
7870b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
788a4ea0ec4SWang Nan 	if (!maps)
789a4ea0ec4SWang Nan 		return 0;
790cb21686bSWang Nan 
7910b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
79254cc54deSWang Nan 		return 0;
79354cc54deSWang Nan 
794d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
795d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
796d3d1af6fSAlexey Budankov 
797a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
798470530bbSAlexey Budankov 		u64 flush = 0;
799e035f4caSJiri Olsa 		struct perf_mmap *map = &maps[i];
800a4ea0ec4SWang Nan 
801e035f4caSJiri Olsa 		if (map->base) {
802f13de660SAlexey Budankov 			record__adjust_affinity(rec, map);
803470530bbSAlexey Budankov 			if (synch) {
804470530bbSAlexey Budankov 				flush = map->flush;
805470530bbSAlexey Budankov 				map->flush = 1;
806470530bbSAlexey Budankov 			}
807d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
808e035f4caSJiri Olsa 				if (perf_mmap__push(map, rec, record__pushfn) != 0) {
809470530bbSAlexey Budankov 					if (synch)
810470530bbSAlexey Budankov 						map->flush = flush;
8118d3eca20SDavid Ahern 					rc = -1;
8128d3eca20SDavid Ahern 					goto out;
8138d3eca20SDavid Ahern 				}
814d3d1af6fSAlexey Budankov 			} else {
81593f20c0fSAlexey Budankov 				int idx;
816d3d1af6fSAlexey Budankov 				/*
817d3d1af6fSAlexey Budankov 				 * Call record__aio_sync() to wait till map->data buffer
818d3d1af6fSAlexey Budankov 				 * becomes available after previous aio write request.
819d3d1af6fSAlexey Budankov 				 */
82093f20c0fSAlexey Budankov 				idx = record__aio_sync(map, false);
82193f20c0fSAlexey Budankov 				if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) {
822d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
823470530bbSAlexey Budankov 					if (synch)
824470530bbSAlexey Budankov 						map->flush = flush;
825d3d1af6fSAlexey Budankov 					rc = -1;
826d3d1af6fSAlexey Budankov 					goto out;
827d3d1af6fSAlexey Budankov 				}
828d3d1af6fSAlexey Budankov 			}
829470530bbSAlexey Budankov 			if (synch)
830470530bbSAlexey Budankov 				map->flush = flush;
8318d3eca20SDavid Ahern 		}
832ef149c25SAdrian Hunter 
833e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
834e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
835ef149c25SAdrian Hunter 			rc = -1;
836ef149c25SAdrian Hunter 			goto out;
837ef149c25SAdrian Hunter 		}
83898402807SFrederic Weisbecker 	}
83998402807SFrederic Weisbecker 
840d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
841d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
842d3d1af6fSAlexey Budankov 
843dcabb507SJiri Olsa 	/*
844dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
845dcabb507SJiri Olsa 	 * at least one event.
846dcabb507SJiri Olsa 	 */
847dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
848ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
8498d3eca20SDavid Ahern 
8500b72d69aSWang Nan 	if (overwrite)
85154cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
8528d3eca20SDavid Ahern out:
8538d3eca20SDavid Ahern 	return rc;
85498402807SFrederic Weisbecker }
85598402807SFrederic Weisbecker 
856470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
857cb21686bSWang Nan {
858cb21686bSWang Nan 	int err;
859cb21686bSWang Nan 
860470530bbSAlexey Budankov 	err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
861cb21686bSWang Nan 	if (err)
862cb21686bSWang Nan 		return err;
863cb21686bSWang Nan 
864470530bbSAlexey Budankov 	return record__mmap_read_evlist(rec, rec->evlist, true, synch);
865cb21686bSWang Nan }
866cb21686bSWang Nan 
8678c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
86857706abcSDavid Ahern {
86957706abcSDavid Ahern 	struct perf_session *session = rec->session;
87057706abcSDavid Ahern 	int feat;
87157706abcSDavid Ahern 
87257706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
87357706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
87457706abcSDavid Ahern 
87557706abcSDavid Ahern 	if (rec->no_buildid)
87657706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
87757706abcSDavid Ahern 
8783e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
87957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
88057706abcSDavid Ahern 
88157706abcSDavid Ahern 	if (!rec->opts.branch_stack)
88257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
883ef149c25SAdrian Hunter 
884ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
885ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
886ffa517adSJiri Olsa 
887cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
888cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
889cf790516SAlexey Budankov 
890258031c0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
891258031c0SJiri Olsa 
892ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
89357706abcSDavid Ahern }
89457706abcSDavid Ahern 
895e1ab48baSWang Nan static void
896e1ab48baSWang Nan record__finish_output(struct record *rec)
897e1ab48baSWang Nan {
8988ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
8998ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
900e1ab48baSWang Nan 
9018ceb41d7SJiri Olsa 	if (data->is_pipe)
902e1ab48baSWang Nan 		return;
903e1ab48baSWang Nan 
904e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
90545112e89SJiri Olsa 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
906e1ab48baSWang Nan 
907e1ab48baSWang Nan 	if (!rec->no_buildid) {
908e1ab48baSWang Nan 		process_buildids(rec);
909e1ab48baSWang Nan 
910e1ab48baSWang Nan 		if (rec->buildid_all)
911e1ab48baSWang Nan 			dsos__hit_all(rec->session);
912e1ab48baSWang Nan 	}
913e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
914e1ab48baSWang Nan 
915e1ab48baSWang Nan 	return;
916e1ab48baSWang Nan }
917e1ab48baSWang Nan 
9184ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
919be7b0c9eSWang Nan {
9209d6aae72SArnaldo Carvalho de Melo 	int err;
9219d6aae72SArnaldo Carvalho de Melo 	struct thread_map *thread_map;
922be7b0c9eSWang Nan 
9234ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
9244ea648aeSWang Nan 		return 0;
9254ea648aeSWang Nan 
9269d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
9279d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
9289d6aae72SArnaldo Carvalho de Melo 		return -1;
9299d6aae72SArnaldo Carvalho de Melo 
9309d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
931be7b0c9eSWang Nan 						 process_synthesized_event,
932be7b0c9eSWang Nan 						 &rec->session->machines.host,
9333fcb10e4SMark Drayton 						 rec->opts.sample_address);
9349d6aae72SArnaldo Carvalho de Melo 	thread_map__put(thread_map);
9359d6aae72SArnaldo Carvalho de Melo 	return err;
936be7b0c9eSWang Nan }
937be7b0c9eSWang Nan 
9384ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
9393c1cb7e3SWang Nan 
940ecfd7a9cSWang Nan static int
941ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
942ecfd7a9cSWang Nan {
9438ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
944ecfd7a9cSWang Nan 	int fd, err;
94503724b2eSAndi Kleen 	char *new_filename;
946ecfd7a9cSWang Nan 
947ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
948ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
949ecfd7a9cSWang Nan 
950d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
951d3d1af6fSAlexey Budankov 
9524ea648aeSWang Nan 	record__synthesize(rec, true);
9534ea648aeSWang Nan 	if (target__none(&rec->opts.target))
9544ea648aeSWang Nan 		record__synthesize_workload(rec, true);
9554ea648aeSWang Nan 
956ecfd7a9cSWang Nan 	rec->samples = 0;
957ecfd7a9cSWang Nan 	record__finish_output(rec);
958ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
959ecfd7a9cSWang Nan 	if (err) {
960ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
961ecfd7a9cSWang Nan 		return -EINVAL;
962ecfd7a9cSWang Nan 	}
963ecfd7a9cSWang Nan 
9648ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
965ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
96603724b2eSAndi Kleen 				    at_exit, &new_filename);
967ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
968ecfd7a9cSWang Nan 		rec->bytes_written = 0;
969ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
970ecfd7a9cSWang Nan 	}
971ecfd7a9cSWang Nan 
972ecfd7a9cSWang Nan 	if (!quiet)
973ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
9742d4f2799SJiri Olsa 			data->path, timestamp);
9753c1cb7e3SWang Nan 
97603724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
97703724b2eSAndi Kleen 		int n = rec->switch_output.cur_file + 1;
97803724b2eSAndi Kleen 
97903724b2eSAndi Kleen 		if (n >= rec->switch_output.num_files)
98003724b2eSAndi Kleen 			n = 0;
98103724b2eSAndi Kleen 		rec->switch_output.cur_file = n;
98203724b2eSAndi Kleen 		if (rec->switch_output.filenames[n]) {
98303724b2eSAndi Kleen 			remove(rec->switch_output.filenames[n]);
98403724b2eSAndi Kleen 			free(rec->switch_output.filenames[n]);
98503724b2eSAndi Kleen 		}
98603724b2eSAndi Kleen 		rec->switch_output.filenames[n] = new_filename;
98703724b2eSAndi Kleen 	} else {
98803724b2eSAndi Kleen 		free(new_filename);
98903724b2eSAndi Kleen 	}
99003724b2eSAndi Kleen 
9913c1cb7e3SWang Nan 	/* Output tracking events */
992be7b0c9eSWang Nan 	if (!at_exit) {
9934ea648aeSWang Nan 		record__synthesize(rec, false);
9943c1cb7e3SWang Nan 
995be7b0c9eSWang Nan 		/*
996be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
997be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
998be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
999be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
1000be7b0c9eSWang Nan 		 * contain map and comm information.
1001be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
1002be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
1003be7b0c9eSWang Nan 		 */
1004be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
10054ea648aeSWang Nan 			record__synthesize_workload(rec, false);
1006be7b0c9eSWang Nan 	}
1007ecfd7a9cSWang Nan 	return fd;
1008ecfd7a9cSWang Nan }
1009ecfd7a9cSWang Nan 
1010f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
1011f33cbe72SArnaldo Carvalho de Melo 
1012f33cbe72SArnaldo Carvalho de Melo /*
1013f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
1014f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
1015f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
1016f33cbe72SArnaldo Carvalho de Melo  */
101745604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
101845604710SNamhyung Kim 					siginfo_t *info,
1019f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
1020f33cbe72SArnaldo Carvalho de Melo {
1021f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
1022f33cbe72SArnaldo Carvalho de Melo 	done = 1;
1023f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
1024f33cbe72SArnaldo Carvalho de Melo }
1025f33cbe72SArnaldo Carvalho de Melo 
10262dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1027bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
10282dd6d8a1SAdrian Hunter 
102946bc29b9SAdrian Hunter int __weak
103046bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
103146bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
103246bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
103346bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
103446bc29b9SAdrian Hunter {
103546bc29b9SAdrian Hunter 	return 0;
103646bc29b9SAdrian Hunter }
103746bc29b9SAdrian Hunter 
1038ee667f94SWang Nan static const struct perf_event_mmap_page *
1039ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist)
1040ee667f94SWang Nan {
1041b2cb615dSWang Nan 	if (evlist) {
1042b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
1043ee667f94SWang Nan 			return evlist->mmap[0].base;
10440b72d69aSWang Nan 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
10450b72d69aSWang Nan 			return evlist->overwrite_mmap[0].base;
1046b2cb615dSWang Nan 	}
1047ee667f94SWang Nan 	return NULL;
1048ee667f94SWang Nan }
1049ee667f94SWang Nan 
1050c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1051c45628b0SWang Nan {
1052ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
1053ee667f94SWang Nan 
1054ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
1055ee667f94SWang Nan 	if (pc)
1056ee667f94SWang Nan 		return pc;
1057c45628b0SWang Nan 	return NULL;
1058c45628b0SWang Nan }
1059c45628b0SWang Nan 
10604ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1061c45c86ebSWang Nan {
1062c45c86ebSWang Nan 	struct perf_session *session = rec->session;
1063c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
10648ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1065c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
1066c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
10678ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1068c45c86ebSWang Nan 	int err = 0;
1069c45c86ebSWang Nan 
10704ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
10714ea648aeSWang Nan 		return 0;
10724ea648aeSWang Nan 
10738ceb41d7SJiri Olsa 	if (data->is_pipe) {
1074a2015516SJiri Olsa 		/*
1075a2015516SJiri Olsa 		 * We need to synthesize events first, because some
1076a2015516SJiri Olsa 		 * features works on top of them (on report side).
1077a2015516SJiri Olsa 		 */
1078318ec184SJiri Olsa 		err = perf_event__synthesize_attrs(tool, rec->evlist,
1079c45c86ebSWang Nan 						   process_synthesized_event);
1080c45c86ebSWang Nan 		if (err < 0) {
1081c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
1082c45c86ebSWang Nan 			goto out;
1083c45c86ebSWang Nan 		}
1084c45c86ebSWang Nan 
1085a2015516SJiri Olsa 		err = perf_event__synthesize_features(tool, session, rec->evlist,
1086a2015516SJiri Olsa 						      process_synthesized_event);
1087a2015516SJiri Olsa 		if (err < 0) {
1088a2015516SJiri Olsa 			pr_err("Couldn't synthesize features.\n");
1089a2015516SJiri Olsa 			return err;
1090a2015516SJiri Olsa 		}
1091a2015516SJiri Olsa 
1092c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
1093c45c86ebSWang Nan 			/*
1094c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
1095c45c86ebSWang Nan 			 * there were no tracepoints so its not really
1096c45c86ebSWang Nan 			 * an error, just that we don't need to
1097c45c86ebSWang Nan 			 * synthesize anything.  We really have to
1098c45c86ebSWang Nan 			 * return this more properly and also
1099c45c86ebSWang Nan 			 * propagate errors that now are calling die()
1100c45c86ebSWang Nan 			 */
1101c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
1102c45c86ebSWang Nan 								  process_synthesized_event);
1103c45c86ebSWang Nan 			if (err <= 0) {
1104c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
1105c45c86ebSWang Nan 				goto out;
1106c45c86ebSWang Nan 			}
1107c45c86ebSWang Nan 			rec->bytes_written += err;
1108c45c86ebSWang Nan 		}
1109c45c86ebSWang Nan 	}
1110c45c86ebSWang Nan 
1111c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
111246bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
111346bc29b9SAdrian Hunter 	if (err)
111446bc29b9SAdrian Hunter 		goto out;
111546bc29b9SAdrian Hunter 
1116c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1117c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1118c45c86ebSWang Nan 					session, process_synthesized_event);
1119c45c86ebSWang Nan 		if (err)
1120c45c86ebSWang Nan 			goto out;
1121c45c86ebSWang Nan 	}
1122c45c86ebSWang Nan 
11236c443954SArnaldo Carvalho de Melo 	if (!perf_evlist__exclude_kernel(rec->evlist)) {
1124c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1125c45c86ebSWang Nan 							 machine);
1126c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1127c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1128c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1129c45c86ebSWang Nan 
1130c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1131c45c86ebSWang Nan 						     machine);
1132c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1133c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1134c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
11356c443954SArnaldo Carvalho de Melo 	}
1136c45c86ebSWang Nan 
1137c45c86ebSWang Nan 	if (perf_guest) {
1138c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1139c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1140c45c86ebSWang Nan 	}
1141c45c86ebSWang Nan 
1142bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1143bfd8f72cSAndi Kleen 						rec->evlist,
1144bfd8f72cSAndi Kleen 						process_synthesized_event,
1145bfd8f72cSAndi Kleen 						data->is_pipe);
1146bfd8f72cSAndi Kleen 	if (err)
1147bfd8f72cSAndi Kleen 		goto out;
1148bfd8f72cSAndi Kleen 
1149373565d2SAndi Kleen 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads,
1150373565d2SAndi Kleen 						 process_synthesized_event,
1151373565d2SAndi Kleen 						NULL);
1152373565d2SAndi Kleen 	if (err < 0) {
1153373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1154373565d2SAndi Kleen 		return err;
1155373565d2SAndi Kleen 	}
1156373565d2SAndi Kleen 
1157373565d2SAndi Kleen 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus,
1158373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1159373565d2SAndi Kleen 	if (err < 0) {
1160373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1161373565d2SAndi Kleen 		return err;
1162373565d2SAndi Kleen 	}
1163373565d2SAndi Kleen 
1164e5416950SSong Liu 	err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
11657b612e29SSong Liu 						machine, opts);
11667b612e29SSong Liu 	if (err < 0)
11677b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
11687b612e29SSong Liu 
1169c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
1170c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
11713fcb10e4SMark Drayton 					    1);
1172c45c86ebSWang Nan out:
1173c45c86ebSWang Nan 	return err;
1174c45c86ebSWang Nan }
1175c45c86ebSWang Nan 
11768c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
117786470930SIngo Molnar {
117857706abcSDavid Ahern 	int err;
117945604710SNamhyung Kim 	int status = 0;
11808b412664SPeter Zijlstra 	unsigned long waking = 0;
118146be604bSZhang, Yanmin 	const bool forks = argc > 0;
118245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1183b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
11848ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1185d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
11866dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
1187657ee553SSong Liu 	struct perf_evlist *sb_evlist = NULL;
118842aa276fSNamhyung Kim 	int fd;
118986470930SIngo Molnar 
119045604710SNamhyung Kim 	atexit(record__sig_exit);
1191f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1192f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1193804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1194a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1195c0bdc1c4SWang Nan 
1196f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1197f3b3614aSHari Bathini 		tool->namespace_events = true;
1198f3b3614aSHari Bathini 
1199dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
12002dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
12013c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
12025f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1203dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
12043c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1205c0bdc1c4SWang Nan 	} else {
12062dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1207c0bdc1c4SWang Nan 	}
1208f5970550SPeter Zijlstra 
12098ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
121094c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
1211ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
1212a9a70bbcSArnaldo Carvalho de Melo 		return -1;
1213a9a70bbcSArnaldo Carvalho de Melo 	}
1214a9a70bbcSArnaldo Carvalho de Melo 
12158ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1216d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1217d20deb64SArnaldo Carvalho de Melo 
12188c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1219330aa675SStephane Eranian 
1220cf790516SAlexey Budankov 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
1221cf790516SAlexey Budankov 		session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
1222cf790516SAlexey Budankov 
1223d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
12243e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
12258ceb41d7SJiri Olsa 						    argv, data->is_pipe,
1226735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
122735b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
122835b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
122945604710SNamhyung Kim 			status = err;
123035b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1231856e9660SPeter Zijlstra 		}
1232856e9660SPeter Zijlstra 	}
1233856e9660SPeter Zijlstra 
1234ad46e48cSJiri Olsa 	/*
1235ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1236ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1237ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1238ad46e48cSJiri Olsa 	 * and need the id for that.
1239ad46e48cSJiri Olsa 	 */
1240ad46e48cSJiri Olsa 	if (data->is_pipe && rec->evlist->nr_entries == 1)
1241ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1242ad46e48cSJiri Olsa 
12438c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
12448d3eca20SDavid Ahern 		err = -1;
124545604710SNamhyung Kim 		goto out_child;
12468d3eca20SDavid Ahern 	}
124786470930SIngo Molnar 
12488690a2a7SWang Nan 	err = bpf__apply_obj_config();
12498690a2a7SWang Nan 	if (err) {
12508690a2a7SWang Nan 		char errbuf[BUFSIZ];
12518690a2a7SWang Nan 
12528690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
12538690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
12548690a2a7SWang Nan 			 errbuf);
12558690a2a7SWang Nan 		goto out_child;
12568690a2a7SWang Nan 	}
12578690a2a7SWang Nan 
1258cca8482cSAdrian Hunter 	/*
1259cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1260cca8482cSAdrian Hunter 	 * evlist.
1261cca8482cSAdrian Hunter 	 */
1262cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
1263cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1264cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1265cca8482cSAdrian Hunter 	}
1266cca8482cSAdrian Hunter 
12673e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
1268a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1269a8bb559bSNamhyung Kim 
12708ceb41d7SJiri Olsa 	if (data->is_pipe) {
127142aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1272529870e3STom Zanussi 		if (err < 0)
127345604710SNamhyung Kim 			goto out_child;
1274563aecb2SJiri Olsa 	} else {
127542aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1276d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
127745604710SNamhyung Kim 			goto out_child;
1278d5eed904SArnaldo Carvalho de Melo 	}
12797c6a1c65SPeter Zijlstra 
1280d3665498SDavid Ahern 	if (!rec->no_buildid
1281e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1282d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1283e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
12848d3eca20SDavid Ahern 		err = -1;
128545604710SNamhyung Kim 		goto out_child;
1286e20960c0SRobert Richter 	}
1287e20960c0SRobert Richter 
1288d56354dcSSong Liu 	if (!opts->no_bpf_event)
1289d56354dcSSong Liu 		bpf_event__add_sb_event(&sb_evlist, &session->header.env);
1290d56354dcSSong Liu 
1291657ee553SSong Liu 	if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
1292657ee553SSong Liu 		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1293657ee553SSong Liu 		opts->no_bpf_event = true;
1294657ee553SSong Liu 	}
1295657ee553SSong Liu 
12964ea648aeSWang Nan 	err = record__synthesize(rec, false);
1297c45c86ebSWang Nan 	if (err < 0)
129845604710SNamhyung Kim 		goto out_child;
12998d3eca20SDavid Ahern 
1300d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
130186470930SIngo Molnar 		struct sched_param param;
130286470930SIngo Molnar 
1303d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
130486470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
13056beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
13068d3eca20SDavid Ahern 			err = -1;
130745604710SNamhyung Kim 			goto out_child;
130886470930SIngo Molnar 		}
130986470930SIngo Molnar 	}
131086470930SIngo Molnar 
1311774cb499SJiri Olsa 	/*
1312774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1313774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1314774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1315774cb499SJiri Olsa 	 */
13166619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
13173e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
1318764e16a3SDavid Ahern 
1319856e9660SPeter Zijlstra 	/*
1320856e9660SPeter Zijlstra 	 * Let the child rip
1321856e9660SPeter Zijlstra 	 */
1322e803cf97SNamhyung Kim 	if (forks) {
132320a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1324e5bed564SNamhyung Kim 		union perf_event *event;
1325e907caf3SHari Bathini 		pid_t tgid;
1326e5bed564SNamhyung Kim 
1327e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1328e5bed564SNamhyung Kim 		if (event == NULL) {
1329e5bed564SNamhyung Kim 			err = -ENOMEM;
1330e5bed564SNamhyung Kim 			goto out_child;
1331e5bed564SNamhyung Kim 		}
1332e5bed564SNamhyung Kim 
1333e803cf97SNamhyung Kim 		/*
1334e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1335e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1336e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1337e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1338e803cf97SNamhyung Kim 		 */
1339e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1340e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1341e803cf97SNamhyung Kim 						   process_synthesized_event,
1342e803cf97SNamhyung Kim 						   machine);
1343e5bed564SNamhyung Kim 		free(event);
1344e803cf97SNamhyung Kim 
1345e907caf3SHari Bathini 		if (tgid == -1)
1346e907caf3SHari Bathini 			goto out_child;
1347e907caf3SHari Bathini 
1348e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1349e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1350e907caf3SHari Bathini 			       machine->id_hdr_size);
1351e907caf3SHari Bathini 		if (event == NULL) {
1352e907caf3SHari Bathini 			err = -ENOMEM;
1353e907caf3SHari Bathini 			goto out_child;
1354e907caf3SHari Bathini 		}
1355e907caf3SHari Bathini 
1356e907caf3SHari Bathini 		/*
1357e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1358e907caf3SHari Bathini 		 */
1359e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1360e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1361e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1362e907caf3SHari Bathini 						  machine);
1363e907caf3SHari Bathini 		free(event);
1364e907caf3SHari Bathini 
13653e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
1366e803cf97SNamhyung Kim 	}
1367856e9660SPeter Zijlstra 
13686619a53eSAndi Kleen 	if (opts->initial_delay) {
13690693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
13706619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
13716619a53eSAndi Kleen 	}
13726619a53eSAndi Kleen 
13735f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
13743c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1375a074865eSWang Nan 	perf_hooks__invoke_record_start();
1376649c48a9SPeter Zijlstra 	for (;;) {
13779f065194SYang Shi 		unsigned long long hits = rec->samples;
137886470930SIngo Molnar 
137905737464SWang Nan 		/*
138005737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
138105737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
138205737464SWang Nan 		 * hits != rec->samples in previous round.
138305737464SWang Nan 		 *
138405737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
138505737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
138605737464SWang Nan 		 */
138705737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
138805737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
138905737464SWang Nan 
1390470530bbSAlexey Budankov 		if (record__mmap_read_all(rec, false) < 0) {
13915f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
13923c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
13938d3eca20SDavid Ahern 			err = -1;
139445604710SNamhyung Kim 			goto out_child;
13958d3eca20SDavid Ahern 		}
139686470930SIngo Molnar 
13972dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
13982dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
13995f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
14002dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
14015f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
14022dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
14032dd6d8a1SAdrian Hunter 				err = -1;
14042dd6d8a1SAdrian Hunter 				goto out_child;
14052dd6d8a1SAdrian Hunter 			}
14062dd6d8a1SAdrian Hunter 		}
14072dd6d8a1SAdrian Hunter 
14083c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
140905737464SWang Nan 			/*
141005737464SWang Nan 			 * If switch_output_trigger is hit, the data in
141105737464SWang Nan 			 * overwritable ring buffer should have been collected,
141205737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
141305737464SWang Nan 			 *
141405737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
141505737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
141605737464SWang Nan 			 * overwritable ring buffer. Read again.
141705737464SWang Nan 			 */
141805737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
141905737464SWang Nan 				continue;
14203c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
14213c1cb7e3SWang Nan 
142205737464SWang Nan 			/*
142305737464SWang Nan 			 * Reenable events in overwrite ring buffer after
142405737464SWang Nan 			 * record__mmap_read_all(): we should have collected
142505737464SWang Nan 			 * data from it.
142605737464SWang Nan 			 */
142705737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
142805737464SWang Nan 
14293c1cb7e3SWang Nan 			if (!quiet)
14303c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
14313c1cb7e3SWang Nan 					waking);
14323c1cb7e3SWang Nan 			waking = 0;
14333c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
14343c1cb7e3SWang Nan 			if (fd < 0) {
14353c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
14363c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
14373c1cb7e3SWang Nan 				err = fd;
14383c1cb7e3SWang Nan 				goto out_child;
14393c1cb7e3SWang Nan 			}
1440bfacbe3bSJiri Olsa 
1441bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1442bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1443bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
14443c1cb7e3SWang Nan 		}
14453c1cb7e3SWang Nan 
1446d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
14476dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1448649c48a9SPeter Zijlstra 				break;
1449f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1450a515114fSJiri Olsa 			/*
1451a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1452a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1453a515114fSJiri Olsa 			 */
1454a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
145545604710SNamhyung Kim 				err = 0;
14568b412664SPeter Zijlstra 			waking++;
14576dcf45efSArnaldo Carvalho de Melo 
14586dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
14596dcf45efSArnaldo Carvalho de Melo 				draining = true;
14608b412664SPeter Zijlstra 		}
14618b412664SPeter Zijlstra 
1462774cb499SJiri Olsa 		/*
1463774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1464774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1465774cb499SJiri Olsa 		 * disable events in this case.
1466774cb499SJiri Olsa 		 */
1467602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
14685f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
14693e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
14702711926aSJiri Olsa 			disabled = true;
14712711926aSJiri Olsa 		}
14728b412664SPeter Zijlstra 	}
14735f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
14743c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
14758b412664SPeter Zijlstra 
1476f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
147735550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1478c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1479f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1480f33cbe72SArnaldo Carvalho de Melo 		err = -1;
148145604710SNamhyung Kim 		goto out_child;
1482f33cbe72SArnaldo Carvalho de Melo 	}
1483f33cbe72SArnaldo Carvalho de Melo 
1484e3d59112SNamhyung Kim 	if (!quiet)
14858b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
148686470930SIngo Molnar 
14874ea648aeSWang Nan 	if (target__none(&rec->opts.target))
14884ea648aeSWang Nan 		record__synthesize_workload(rec, true);
14894ea648aeSWang Nan 
149045604710SNamhyung Kim out_child:
1491470530bbSAlexey Budankov 	record__mmap_read_all(rec, true);
1492d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1493d3d1af6fSAlexey Budankov 
149445604710SNamhyung Kim 	if (forks) {
149545604710SNamhyung Kim 		int exit_status;
149645604710SNamhyung Kim 
149745604710SNamhyung Kim 		if (!child_finished)
149845604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
149945604710SNamhyung Kim 
150045604710SNamhyung Kim 		wait(&exit_status);
150145604710SNamhyung Kim 
150245604710SNamhyung Kim 		if (err < 0)
150345604710SNamhyung Kim 			status = err;
150445604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
150545604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
150645604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
150745604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
150845604710SNamhyung Kim 	} else
150945604710SNamhyung Kim 		status = err;
151045604710SNamhyung Kim 
15114ea648aeSWang Nan 	record__synthesize(rec, true);
1512e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1513e3d59112SNamhyung Kim 	rec->samples = 0;
1514e3d59112SNamhyung Kim 
1515ecfd7a9cSWang Nan 	if (!err) {
1516ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1517e1ab48baSWang Nan 			record__finish_output(rec);
1518ecfd7a9cSWang Nan 		} else {
1519ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1520ecfd7a9cSWang Nan 			if (fd < 0) {
1521ecfd7a9cSWang Nan 				status = fd;
1522ecfd7a9cSWang Nan 				goto out_delete_session;
1523ecfd7a9cSWang Nan 			}
1524ecfd7a9cSWang Nan 		}
1525ecfd7a9cSWang Nan 	}
152639d17dacSArnaldo Carvalho de Melo 
1527a074865eSWang Nan 	perf_hooks__invoke_record_end();
1528a074865eSWang Nan 
1529e3d59112SNamhyung Kim 	if (!err && !quiet) {
1530e3d59112SNamhyung Kim 		char samples[128];
1531ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1532ecfd7a9cSWang Nan 					".<timestamp>" : "";
1533e3d59112SNamhyung Kim 
1534ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1535e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1536e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1537e3d59112SNamhyung Kim 		else
1538e3d59112SNamhyung Kim 			samples[0] = '\0';
1539e3d59112SNamhyung Kim 
1540ecfd7a9cSWang Nan 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
15418ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
15422d4f2799SJiri Olsa 			data->path, postfix, samples);
1543e3d59112SNamhyung Kim 	}
1544e3d59112SNamhyung Kim 
154539d17dacSArnaldo Carvalho de Melo out_delete_session:
154639d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
1547657ee553SSong Liu 
1548657ee553SSong Liu 	if (!opts->no_bpf_event)
1549657ee553SSong Liu 		perf_evlist__stop_sb_thread(sb_evlist);
155045604710SNamhyung Kim 	return status;
155186470930SIngo Molnar }
155286470930SIngo Molnar 
15530883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
155409b0fd45SJiri Olsa {
1555aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1556a601fdffSJiri Olsa 
15570883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
155826d33022SJiri Olsa 
15590883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
156009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
15610883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
15620883e820SArnaldo Carvalho de Melo }
15630883e820SArnaldo Carvalho de Melo 
15640883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
15650883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
15660883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
15670883e820SArnaldo Carvalho de Melo {
15680883e820SArnaldo Carvalho de Melo 	int ret;
15690883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
15700883e820SArnaldo Carvalho de Melo 
15710883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
15720883e820SArnaldo Carvalho de Melo 	if (unset) {
15730883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
15740883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
15750883e820SArnaldo Carvalho de Melo 		return 0;
15760883e820SArnaldo Carvalho de Melo 	}
15770883e820SArnaldo Carvalho de Melo 
15780883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
15790883e820SArnaldo Carvalho de Melo 	if (!ret) {
15800883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
15810883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
15820883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
15830883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
15840883e820SArnaldo Carvalho de Melo 	}
15850883e820SArnaldo Carvalho de Melo 
15860883e820SArnaldo Carvalho de Melo 	return ret;
158709b0fd45SJiri Olsa }
158809b0fd45SJiri Olsa 
1589c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
159009b0fd45SJiri Olsa 			       const char *arg,
159109b0fd45SJiri Olsa 			       int unset)
159209b0fd45SJiri Olsa {
15930883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
159426d33022SJiri Olsa }
159526d33022SJiri Olsa 
1596c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
159709b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
159809b0fd45SJiri Olsa 			 int unset __maybe_unused)
159909b0fd45SJiri Olsa {
16002ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1601c421e80bSKan Liang 
16022ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
160309b0fd45SJiri Olsa 
16042ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
16052ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1606eb853e80SJiri Olsa 
16072ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
160809b0fd45SJiri Olsa 	return 0;
160909b0fd45SJiri Olsa }
161009b0fd45SJiri Olsa 
1611eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1612eb853e80SJiri Olsa {
16137a29c087SNamhyung Kim 	struct record *rec = cb;
16147a29c087SNamhyung Kim 
16157a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
16167a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
16177a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
16187a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
16197a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
16207a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
16217a29c087SNamhyung Kim 			rec->no_buildid = true;
16227a29c087SNamhyung Kim 		else
16237a29c087SNamhyung Kim 			return -1;
16247a29c087SNamhyung Kim 		return 0;
16257a29c087SNamhyung Kim 	}
1626cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
1627cff17205SYisheng Xie 		var = "call-graph.record-mode";
1628eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
1629eb853e80SJiri Olsa 	}
163093f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
163193f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
163293f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
163393f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
163493f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
163593f20c0fSAlexey Budankov 	}
163693f20c0fSAlexey Budankov #endif
1637eb853e80SJiri Olsa 
1638cff17205SYisheng Xie 	return 0;
1639cff17205SYisheng Xie }
1640cff17205SYisheng Xie 
1641814c8c38SPeter Zijlstra struct clockid_map {
1642814c8c38SPeter Zijlstra 	const char *name;
1643814c8c38SPeter Zijlstra 	int clockid;
1644814c8c38SPeter Zijlstra };
1645814c8c38SPeter Zijlstra 
1646814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1647814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1648814c8c38SPeter Zijlstra 
1649814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1650814c8c38SPeter Zijlstra 
1651814c8c38SPeter Zijlstra 
1652814c8c38SPeter Zijlstra /*
1653814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1654814c8c38SPeter Zijlstra  */
1655814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1656814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1657814c8c38SPeter Zijlstra #endif
1658814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1659814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1660814c8c38SPeter Zijlstra #endif
1661814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1662814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1663814c8c38SPeter Zijlstra #endif
1664814c8c38SPeter Zijlstra 
1665814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1666814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1667814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1668814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1669814c8c38SPeter Zijlstra 
1670814c8c38SPeter Zijlstra 	/* available for some events */
1671814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1672814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1673814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1674814c8c38SPeter Zijlstra 
1675814c8c38SPeter Zijlstra 	/* available for the lazy */
1676814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1677814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1678814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1679814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1680814c8c38SPeter Zijlstra 
1681814c8c38SPeter Zijlstra 	CLOCKID_END,
1682814c8c38SPeter Zijlstra };
1683814c8c38SPeter Zijlstra 
1684cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1685cf790516SAlexey Budankov {
1686cf790516SAlexey Budankov 	struct timespec res;
1687cf790516SAlexey Budankov 
1688cf790516SAlexey Budankov 	*res_ns = 0;
1689cf790516SAlexey Budankov 	if (!clock_getres(clk_id, &res))
1690cf790516SAlexey Budankov 		*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1691cf790516SAlexey Budankov 	else
1692cf790516SAlexey Budankov 		pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1693cf790516SAlexey Budankov 
1694cf790516SAlexey Budankov 	return 0;
1695cf790516SAlexey Budankov }
1696cf790516SAlexey Budankov 
1697814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1698814c8c38SPeter Zijlstra {
1699814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1700814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1701814c8c38SPeter Zijlstra 	const char *ostr = str;
1702814c8c38SPeter Zijlstra 
1703814c8c38SPeter Zijlstra 	if (unset) {
1704814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1705814c8c38SPeter Zijlstra 		return 0;
1706814c8c38SPeter Zijlstra 	}
1707814c8c38SPeter Zijlstra 
1708814c8c38SPeter Zijlstra 	/* no arg passed */
1709814c8c38SPeter Zijlstra 	if (!str)
1710814c8c38SPeter Zijlstra 		return 0;
1711814c8c38SPeter Zijlstra 
1712814c8c38SPeter Zijlstra 	/* no setting it twice */
1713814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1714814c8c38SPeter Zijlstra 		return -1;
1715814c8c38SPeter Zijlstra 
1716814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1717814c8c38SPeter Zijlstra 
1718814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1719814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1720cf790516SAlexey Budankov 		return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1721814c8c38SPeter Zijlstra 
1722814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1723814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1724814c8c38SPeter Zijlstra 		str += 6;
1725814c8c38SPeter Zijlstra 
1726814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1727814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1728814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1729cf790516SAlexey Budankov 			return get_clockid_res(opts->clockid,
1730cf790516SAlexey Budankov 					       &opts->clockid_res_ns);
1731814c8c38SPeter Zijlstra 		}
1732814c8c38SPeter Zijlstra 	}
1733814c8c38SPeter Zijlstra 
1734814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1735814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1736814c8c38SPeter Zijlstra 	return -1;
1737814c8c38SPeter Zijlstra }
1738814c8c38SPeter Zijlstra 
1739f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
1740f4fe11b7SAlexey Budankov {
1741f4fe11b7SAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
1742f4fe11b7SAlexey Budankov 
1743f4fe11b7SAlexey Budankov 	if (unset || !str)
1744f4fe11b7SAlexey Budankov 		return 0;
1745f4fe11b7SAlexey Budankov 
1746f4fe11b7SAlexey Budankov 	if (!strcasecmp(str, "node"))
1747f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_NODE;
1748f4fe11b7SAlexey Budankov 	else if (!strcasecmp(str, "cpu"))
1749f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_CPU;
1750f4fe11b7SAlexey Budankov 
1751f4fe11b7SAlexey Budankov 	return 0;
1752f4fe11b7SAlexey Budankov }
1753f4fe11b7SAlexey Budankov 
1754e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1755e9db1310SAdrian Hunter 				    const char *str,
1756e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1757e9db1310SAdrian Hunter {
1758e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1759e9db1310SAdrian Hunter 	char *s, *p;
1760e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1761e9db1310SAdrian Hunter 	int ret;
1762e9db1310SAdrian Hunter 
1763e9db1310SAdrian Hunter 	if (!str)
1764e9db1310SAdrian Hunter 		return -EINVAL;
1765e9db1310SAdrian Hunter 
1766e9db1310SAdrian Hunter 	s = strdup(str);
1767e9db1310SAdrian Hunter 	if (!s)
1768e9db1310SAdrian Hunter 		return -ENOMEM;
1769e9db1310SAdrian Hunter 
1770e9db1310SAdrian Hunter 	p = strchr(s, ',');
1771e9db1310SAdrian Hunter 	if (p)
1772e9db1310SAdrian Hunter 		*p = '\0';
1773e9db1310SAdrian Hunter 
1774e9db1310SAdrian Hunter 	if (*s) {
1775e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1776e9db1310SAdrian Hunter 		if (ret)
1777e9db1310SAdrian Hunter 			goto out_free;
1778e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1779e9db1310SAdrian Hunter 	}
1780e9db1310SAdrian Hunter 
1781e9db1310SAdrian Hunter 	if (!p) {
1782e9db1310SAdrian Hunter 		ret = 0;
1783e9db1310SAdrian Hunter 		goto out_free;
1784e9db1310SAdrian Hunter 	}
1785e9db1310SAdrian Hunter 
1786e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1787e9db1310SAdrian Hunter 	if (ret)
1788e9db1310SAdrian Hunter 		goto out_free;
1789e9db1310SAdrian Hunter 
1790e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1791e9db1310SAdrian Hunter 
1792e9db1310SAdrian Hunter out_free:
1793e9db1310SAdrian Hunter 	free(s);
1794e9db1310SAdrian Hunter 	return ret;
1795e9db1310SAdrian Hunter }
1796e9db1310SAdrian Hunter 
17970c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
17980c582449SJiri Olsa {
17990c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
18000c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
18010c582449SJiri Olsa 
18020c582449SJiri Olsa 	wakeup_size /= 2;
18030c582449SJiri Olsa 
18040c582449SJiri Olsa 	if (s->size < wakeup_size) {
18050c582449SJiri Olsa 		char buf[100];
18060c582449SJiri Olsa 
18070c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
18080c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
18090c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
18100c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
18110c582449SJiri Olsa 	}
18120c582449SJiri Olsa }
18130c582449SJiri Olsa 
1814cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1815cb4e1ebbSJiri Olsa {
1816cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
1817dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
1818dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
1819dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
1820dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
1821dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
1822dc0c6127SJiri Olsa 		{ .tag  = 0 },
1823dc0c6127SJiri Olsa 	};
1824bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
1825bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
1826bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
1827bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
1828bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
1829bfacbe3bSJiri Olsa 		{ .tag  = 0 },
1830bfacbe3bSJiri Olsa 	};
1831dc0c6127SJiri Olsa 	unsigned long val;
1832cb4e1ebbSJiri Olsa 
1833cb4e1ebbSJiri Olsa 	if (!s->set)
1834cb4e1ebbSJiri Olsa 		return 0;
1835cb4e1ebbSJiri Olsa 
1836cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
1837cb4e1ebbSJiri Olsa 		s->signal = true;
1838cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
1839dc0c6127SJiri Olsa 		goto enabled;
1840dc0c6127SJiri Olsa 	}
1841dc0c6127SJiri Olsa 
1842dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
1843dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
1844dc0c6127SJiri Olsa 		s->size = val;
1845dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
1846dc0c6127SJiri Olsa 		goto enabled;
1847cb4e1ebbSJiri Olsa 	}
1848cb4e1ebbSJiri Olsa 
1849bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
1850bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
1851bfacbe3bSJiri Olsa 		s->time = val;
1852bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1853bfacbe3bSJiri Olsa 			 s->str, s->time);
1854bfacbe3bSJiri Olsa 		goto enabled;
1855bfacbe3bSJiri Olsa 	}
1856bfacbe3bSJiri Olsa 
1857cb4e1ebbSJiri Olsa 	return -1;
1858dc0c6127SJiri Olsa 
1859dc0c6127SJiri Olsa enabled:
1860dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
1861dc0c6127SJiri Olsa 	s->enabled              = true;
18620c582449SJiri Olsa 
18630c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
18640c582449SJiri Olsa 		switch_output_size_warn(rec);
18650c582449SJiri Olsa 
1866dc0c6127SJiri Olsa 	return 0;
1867cb4e1ebbSJiri Olsa }
1868cb4e1ebbSJiri Olsa 
1869e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
187086470930SIngo Molnar 	"perf record [<options>] [<command>]",
187186470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
187286470930SIngo Molnar 	NULL
187386470930SIngo Molnar };
1874e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
187586470930SIngo Molnar 
1876d20deb64SArnaldo Carvalho de Melo /*
18778c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
18788c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1879d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1880d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1881d20deb64SArnaldo Carvalho de Melo  *
1882d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1883d20deb64SArnaldo Carvalho de Melo  *
1884d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1885d20deb64SArnaldo Carvalho de Melo  */
18868c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1887d20deb64SArnaldo Carvalho de Melo 	.opts = {
18888affc2b8SAndi Kleen 		.sample_time	     = true,
1889d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1890d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1891d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1892447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1893d1cb9fceSNamhyung Kim 		.target		     = {
1894d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
18953aa5939dSAdrian Hunter 			.default_per_cpu = true,
1896d1cb9fceSNamhyung Kim 		},
1897470530bbSAlexey Budankov 		.mmap_flush          = MMAP_FLUSH_DEFAULT,
1898d20deb64SArnaldo Carvalho de Melo 	},
1899e3d59112SNamhyung Kim 	.tool = {
1900e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1901e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1902cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1903e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1904f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
1905e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1906e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1907cca8482cSAdrian Hunter 		.ordered_events	= true,
1908e3d59112SNamhyung Kim 	},
1909d20deb64SArnaldo Carvalho de Melo };
19107865e817SFrederic Weisbecker 
191176a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
191276a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
191361eaa3beSArnaldo Carvalho de Melo 
19140aab2136SWang Nan static bool dry_run;
19150aab2136SWang Nan 
1916d20deb64SArnaldo Carvalho de Melo /*
1917d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1918d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1919b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1920d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1921d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1922d20deb64SArnaldo Carvalho de Melo  */
1923efd21307SJiri Olsa static struct option __record_options[] = {
1924d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
192586470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1926f120f9d5SJiri Olsa 		     parse_events_option),
1927d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1928c171b552SLi Zefan 		     "event filter", parse_filter),
19294ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
19304ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
19314ba1faa1SWang Nan 			   exclude_perf),
1932bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1933d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1934bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1935d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1936d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
193786470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1938509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
1939acac03faSKirill Smelkov 		    "collect data without buffering"),
1940d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1941daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1942bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
194386470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1944bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1945c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1946d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
19472d4f2799SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
194886470930SIngo Molnar 		    "output file name"),
194969e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
195069e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
19512e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
19524ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
19534ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
1954626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
195571184c6aSSong Liu 	OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
1956b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1957b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
195867230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
195967230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
196067230479SArnaldo Carvalho de Melo 		      record__parse_freq),
1961e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1962e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
1963e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
1964470530bbSAlexey Budankov 	OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
1965470530bbSAlexey Budankov 		     "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
1966470530bbSAlexey Budankov 		     record__mmap_flush_parse),
1967d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
196843bece79SLin Ming 		    "put the counters into a counter group"),
19692ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
197009b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
197109b0fd45SJiri Olsa 			   &record_callchain_opt),
197209b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
197376a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
197409b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
1975c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
19763da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1977b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1978d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1979649c48a9SPeter Zijlstra 		    "per thread counts"),
198056100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
19813b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
19823b0a5daaSKan Liang 		    "Record the sample physical addresses"),
1983b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
19843abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
19853abebc55SAdrian Hunter 			&record.opts.sample_time_set,
19863abebc55SAdrian Hunter 			"Record the sample timestamps"),
1987f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
1988f290aa1fSJiri Olsa 			"Record the sample period"),
1989d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1990649c48a9SPeter Zijlstra 		    "don't sample"),
1991d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
1992d2db9a98SWang Nan 			&record.no_buildid_cache_set,
1993a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
1994d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
1995d2db9a98SWang Nan 			&record.no_buildid_set,
1996baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
1997d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1998023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1999023695d9SStephane Eranian 		     parse_cgroups),
2000a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
20016619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
2002bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
2003bea03405SNamhyung Kim 		   "user to profile"),
2004a5aabdacSStephane Eranian 
2005a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
2006a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
2007a5aabdacSStephane Eranian 		     parse_branch_stack),
2008a5aabdacSStephane Eranian 
2009a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
2010a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
2011bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
201205484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
201305484298SAndi Kleen 		    "sample by weight (on special events only)"),
2014475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
2015475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
20163aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
20173aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
2018bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
2019bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
2020*8e5bc76fSArnaldo Carvalho de Melo 		    " use '-I?' to list register names", parse_regs),
202184c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
202284c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
2023*8e5bc76fSArnaldo Carvalho de Melo 		    " use '-I?' to list register names", parse_regs),
202485c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
202585c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
2026814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
2027814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
2028814c8c38SPeter Zijlstra 	parse_clockid),
20292dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
20302dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
20313fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
20329d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
2033f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
2034f3b3614aSHari Bathini 		    "Record namespaces events"),
2035b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
2036b757bb09SAdrian Hunter 		    "Record context switch events"),
203785723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
203885723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
203985723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
204085723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
204185723885SJiri Olsa 			 "Configure all used events to run in user space.",
204285723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
204371dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
204471dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
204571dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
204671dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
20477efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
20487efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
20496156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
20506156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
2051ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
2052ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
205368588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
205468588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
2055cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
2056c38dab7dSAndi Kleen 			  &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
2057c38dab7dSAndi Kleen 			  "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
2058dc0c6127SJiri Olsa 			  "signal"),
205903724b2eSAndi Kleen 	OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
206003724b2eSAndi Kleen 		   "Limit number of switch output generated files"),
20610aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
20620aab2136SWang Nan 		    "Parse options then exit"),
2063d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
206493f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
206593f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
2066d3d1af6fSAlexey Budankov 		     record__aio_parse),
2067d3d1af6fSAlexey Budankov #endif
2068f4fe11b7SAlexey Budankov 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
2069f4fe11b7SAlexey Budankov 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
2070f4fe11b7SAlexey Budankov 		     record__parse_affinity),
207186470930SIngo Molnar 	OPT_END()
207286470930SIngo Molnar };
207386470930SIngo Molnar 
2074e5b2c207SNamhyung Kim struct option *record_options = __record_options;
2075e5b2c207SNamhyung Kim 
2076b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
207786470930SIngo Molnar {
2078ef149c25SAdrian Hunter 	int err;
20798c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
208016ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
208186470930SIngo Molnar 
208267230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
208367230479SArnaldo Carvalho de Melo 
208448e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
208548e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
208648e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
208748e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
208848e1cab1SWang Nan # undef set_nobuild
208948e1cab1SWang Nan #endif
209048e1cab1SWang Nan 
20917efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
20927efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
20937efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
20947efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
20957efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
20967efe0e03SHe Kuang # else
20977efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
20987efe0e03SHe Kuang # endif
20997efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
21007efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
21017efe0e03SHe Kuang # undef set_nobuild
21027efe0e03SHe Kuang # undef REASON
21037efe0e03SHe Kuang #endif
21047efe0e03SHe Kuang 
21059d2ed645SAlexey Budankov 	CPU_ZERO(&rec->affinity_mask);
21069d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
21079d2ed645SAlexey Budankov 
21083e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
21093e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
2110361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
2111361c99a6SArnaldo Carvalho de Melo 
2112ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
2113ecc4c561SArnaldo Carvalho de Melo 	if (err)
2114ecc4c561SArnaldo Carvalho de Melo 		return err;
2115eb853e80SJiri Olsa 
2116bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
2117a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
211868ba3235SNamhyung Kim 	if (quiet)
211968ba3235SNamhyung Kim 		perf_quiet_option();
2120483635a9SJiri Olsa 
2121483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2122602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2123483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
212486470930SIngo Molnar 
2125bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2126c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2127c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2128c7118369SNamhyung Kim 
2129023695d9SStephane Eranian 	}
2130b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2131b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2132c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2133c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2134c7118369SNamhyung Kim 		return -EINVAL;
2135b757bb09SAdrian Hunter 	}
2136023695d9SStephane Eranian 
2137cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2138cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2139cb4e1ebbSJiri Olsa 		return -EINVAL;
2140cb4e1ebbSJiri Olsa 	}
2141cb4e1ebbSJiri Olsa 
2142bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2143bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2144bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2145bfacbe3bSJiri Olsa 	}
2146bfacbe3bSJiri Olsa 
214703724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
214803724b2eSAndi Kleen 		rec->switch_output.filenames = calloc(sizeof(char *),
214903724b2eSAndi Kleen 						      rec->switch_output.num_files);
215003724b2eSAndi Kleen 		if (!rec->switch_output.filenames)
215103724b2eSAndi Kleen 			return -EINVAL;
215203724b2eSAndi Kleen 	}
215303724b2eSAndi Kleen 
21541b36c03eSAdrian Hunter 	/*
21551b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
21561b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
21571b36c03eSAdrian Hunter 	 */
21581b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
21591b36c03eSAdrian Hunter 
21601b36c03eSAdrian Hunter 	symbol__init(NULL);
21611b36c03eSAdrian Hunter 
21624b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
21631b36c03eSAdrian Hunter 	if (err)
21641b36c03eSAdrian Hunter 		goto out;
21651b36c03eSAdrian Hunter 
21660aab2136SWang Nan 	if (dry_run)
21675c01ad60SAdrian Hunter 		goto out;
21680aab2136SWang Nan 
2169d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2170d7888573SWang Nan 	if (err) {
2171d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2172d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2173d7888573SWang Nan 			 errbuf);
21745c01ad60SAdrian Hunter 		goto out;
2175d7888573SWang Nan 	}
2176d7888573SWang Nan 
2177ef149c25SAdrian Hunter 	err = -ENOMEM;
2178ef149c25SAdrian Hunter 
21796c443954SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist))
2180646aaea6SArnaldo Carvalho de Melo 		pr_warning(
2181646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
2182ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
2183646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
2184646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
2185646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
2186646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
2187646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
2188ec80fde7SArnaldo Carvalho de Melo 
21890c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2190a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2191dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
21920c1d46a8SWang Nan 		/*
21930c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
21940c1d46a8SWang Nan 		 * generation by default to reduce data file switching
21950c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
21960c1d46a8SWang Nan 		 * explicitly using
21970c1d46a8SWang Nan 		 *
219860437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
21990c1d46a8SWang Nan 		 *              --no-no-buildid-cache
22000c1d46a8SWang Nan 		 *
22010c1d46a8SWang Nan 		 * Following code equals to:
22020c1d46a8SWang Nan 		 *
22030c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
22040c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
22050c1d46a8SWang Nan 		 *         disable_buildid_cache();
22060c1d46a8SWang Nan 		 */
22070c1d46a8SWang Nan 		bool disable = true;
22080c1d46a8SWang Nan 
22090c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
22100c1d46a8SWang Nan 			disable = false;
22110c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
22120c1d46a8SWang Nan 			disable = false;
22130c1d46a8SWang Nan 		if (disable) {
22140c1d46a8SWang Nan 			rec->no_buildid = true;
22150c1d46a8SWang Nan 			rec->no_buildid_cache = true;
22160c1d46a8SWang Nan 			disable_buildid_cache();
22170c1d46a8SWang Nan 		}
22180c1d46a8SWang Nan 	}
2219655000e7SArnaldo Carvalho de Melo 
22204ea648aeSWang Nan 	if (record.opts.overwrite)
22214ea648aeSWang Nan 		record.opts.tail_synthesize = true;
22224ea648aeSWang Nan 
22233e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
22244b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
222569aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
2226394c01edSAdrian Hunter 		goto out;
2227bbd36e5eSPeter Zijlstra 	}
222886470930SIngo Molnar 
222969e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
223069e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
223169e7e5b0SAdrian Hunter 
2232602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
223316ad2ffbSNamhyung Kim 	if (err) {
2234602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
2235c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
223616ad2ffbSNamhyung Kim 	}
22374bd0f2d2SNamhyung Kim 
2238602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
223916ad2ffbSNamhyung Kim 	if (err) {
224016ad2ffbSNamhyung Kim 		int saved_errno = errno;
224116ad2ffbSNamhyung Kim 
2242602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
22433780f488SNamhyung Kim 		ui__error("%s", errbuf);
224416ad2ffbSNamhyung Kim 
224516ad2ffbSNamhyung Kim 		err = -saved_errno;
2246394c01edSAdrian Hunter 		goto out;
224716ad2ffbSNamhyung Kim 	}
22480d37aa34SArnaldo Carvalho de Melo 
2249ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
2250ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
225123dc4f15SJiri Olsa 
225216ad2ffbSNamhyung Kim 	err = -ENOMEM;
22533e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
2254dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
225569aad6f1SArnaldo Carvalho de Melo 
2256ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
2257ef149c25SAdrian Hunter 	if (err)
2258394c01edSAdrian Hunter 		goto out;
2259ef149c25SAdrian Hunter 
22606156681bSNamhyung Kim 	/*
22616156681bSNamhyung Kim 	 * We take all buildids when the file contains
22626156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
22636156681bSNamhyung Kim 	 * trace because it would take too long.
22646156681bSNamhyung Kim 	 */
22656156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
22666156681bSNamhyung Kim 		rec->buildid_all = true;
22676156681bSNamhyung Kim 
2268b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
226939d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
2270394c01edSAdrian Hunter 		goto out;
22717e4ff9e3SMike Galbraith 	}
22727e4ff9e3SMike Galbraith 
227393f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
227493f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
2275d3d1af6fSAlexey Budankov 	if (verbose > 0)
2276d3d1af6fSAlexey Budankov 		pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks);
2277d3d1af6fSAlexey Budankov 
22789d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
2279470530bbSAlexey Budankov 	pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
22809d2ed645SAlexey Budankov 
2281d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
2282394c01edSAdrian Hunter out:
228345604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
2284d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
2285ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
228639d17dacSArnaldo Carvalho de Melo 	return err;
228786470930SIngo Molnar }
22882dd6d8a1SAdrian Hunter 
22892dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
22902dd6d8a1SAdrian Hunter {
2291dc0c6127SJiri Olsa 	struct record *rec = &record;
2292dc0c6127SJiri Olsa 
22935f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
22945f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
22952dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
22965f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
22975f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
22985f9cf599SWang Nan 	}
22993c1cb7e3SWang Nan 
2300dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
23013c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
23022dd6d8a1SAdrian Hunter }
2303bfacbe3bSJiri Olsa 
2304bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
2305bfacbe3bSJiri Olsa {
2306bfacbe3bSJiri Olsa 	struct record *rec = &record;
2307bfacbe3bSJiri Olsa 
2308bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
2309bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
2310bfacbe3bSJiri Olsa }
2311