1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
286470930SIngo Molnar /*
386470930SIngo Molnar * builtin-record.c
486470930SIngo Molnar *
586470930SIngo Molnar * Builtin record command: Record the profile of a workload
686470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for
786470930SIngo Molnar * later analysis via perf report.
886470930SIngo Molnar */
986470930SIngo Molnar #include "builtin.h"
1086470930SIngo Molnar
116122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
13e3a23261SNamhyung Kim #include <internal/xyarray.h>
1486470930SIngo Molnar #include "util/parse-events.h"
1541840d21STaeung Song #include "util/config.h"
1686470930SIngo Molnar
178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
24e0fcfb08SArnaldo Carvalho de Melo #include "util/mmap.h"
2549c670b1SIan Rogers #include "util/mutex.h"
26aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h"
2794c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2845694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
298d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
30aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h"
31a12b51c4SPaul Mackerras #include "util/cpumap.h"
32fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
33f5fc1412SJiri Olsa #include "util/data.h"
34bcc84ec6SStephane Eranian #include "util/perf_regs.h"
35ef149c25SAdrian Hunter #include "util/auxtrace.h"
3646bc29b9SAdrian Hunter #include "util/tsc.h"
37f00898f4SAndi Kleen #include "util/parse-branch-options.h"
38bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3940c7d246SArnaldo Carvalho de Melo #include "util/perf_api_probe.h"
405f9cf599SWang Nan #include "util/trigger.h"
41a074865eSWang Nan #include "util/perf-hooks.h"
42f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
43ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h"
44c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4558db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
467b612e29SSong Liu #include "util/bpf-event.h"
47d99c22eaSStephane Eranian #include "util/util.h"
4870943490SStephane Eranian #include "util/pfm.h"
491eaf496eSIan Rogers #include "util/pmu.h"
501eaf496eSIan Rogers #include "util/pmus.h"
516953beb4SJiri Olsa #include "util/clockid.h"
52edc41a10SNamhyung Kim #include "util/off_cpu.h"
5327c6f245SNamhyung Kim #include "util/bpf-filter.h"
54d8871ea7SWang Nan #include "asm/bug.h"
55c1a604dfSArnaldo Carvalho de Melo #include "perf.h"
56f466e5edSAlexey Bayduraev #include "cputopo.h"
577c6a1c65SPeter Zijlstra
58a43783aeSArnaldo Carvalho de Melo #include <errno.h>
59fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
6067230479SArnaldo Carvalho de Melo #include <locale.h>
614208735dSArnaldo Carvalho de Melo #include <poll.h>
62d99c22eaSStephane Eranian #include <pthread.h>
6386470930SIngo Molnar #include <unistd.h>
64415ccb58SAlexey Bayduraev #ifndef HAVE_GETTID
65415ccb58SAlexey Bayduraev #include <syscall.h>
66415ccb58SAlexey Bayduraev #endif
6786470930SIngo Molnar #include <sched.h>
689607ad3aSArnaldo Carvalho de Melo #include <signal.h>
69da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
70da231338SAnand K Mistry #include <sys/eventfd.h>
71da231338SAnand K Mistry #endif
72a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
734208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
74eeb399b5SAdrian Hunter #include <sys/types.h>
75eeb399b5SAdrian Hunter #include <sys/stat.h>
76eeb399b5SAdrian Hunter #include <fcntl.h>
776ef81c55SMamatha Inamdar #include <linux/err.h>
788520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
790693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
80d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h>
818384a260SAlexey Budankov #include <linux/bitmap.h>
82d1e325cfSJiri Olsa #include <sys/time.h>
8378da39faSBernhard Rosenkraenzer
841b43b704SJiri Olsa struct switch_output {
85dc0c6127SJiri Olsa bool enabled;
861b43b704SJiri Olsa bool signal;
87dc0c6127SJiri Olsa unsigned long size;
88bfacbe3bSJiri Olsa unsigned long time;
89cb4e1ebbSJiri Olsa const char *str;
90cb4e1ebbSJiri Olsa bool set;
9103724b2eSAndi Kleen char **filenames;
9203724b2eSAndi Kleen int num_files;
9303724b2eSAndi Kleen int cur_file;
941b43b704SJiri Olsa };
951b43b704SJiri Olsa
967954f716SAlexey Bayduraev struct thread_mask {
977954f716SAlexey Bayduraev struct mmap_cpu_mask maps;
987954f716SAlexey Bayduraev struct mmap_cpu_mask affinity;
997954f716SAlexey Bayduraev };
1007954f716SAlexey Bayduraev
101415ccb58SAlexey Bayduraev struct record_thread {
102415ccb58SAlexey Bayduraev pid_t tid;
103415ccb58SAlexey Bayduraev struct thread_mask *mask;
104415ccb58SAlexey Bayduraev struct {
105415ccb58SAlexey Bayduraev int msg[2];
106415ccb58SAlexey Bayduraev int ack[2];
107415ccb58SAlexey Bayduraev } pipes;
108415ccb58SAlexey Bayduraev struct fdarray pollfd;
109415ccb58SAlexey Bayduraev int ctlfd_pos;
110415ccb58SAlexey Bayduraev int nr_mmaps;
111415ccb58SAlexey Bayduraev struct mmap **maps;
112415ccb58SAlexey Bayduraev struct mmap **overwrite_maps;
113415ccb58SAlexey Bayduraev struct record *rec;
114396b626bSAlexey Bayduraev unsigned long long samples;
115396b626bSAlexey Bayduraev unsigned long waking;
116ae9c7242SAlexey Bayduraev u64 bytes_written;
117610fbc01SAlexey Bayduraev u64 bytes_transferred;
118610fbc01SAlexey Bayduraev u64 bytes_compressed;
119415ccb58SAlexey Bayduraev };
120415ccb58SAlexey Bayduraev
121396b626bSAlexey Bayduraev static __thread struct record_thread *thread;
122396b626bSAlexey Bayduraev
1231e5de7d9SAlexey Bayduraev enum thread_msg {
1241e5de7d9SAlexey Bayduraev THREAD_MSG__UNDEFINED = 0,
1251e5de7d9SAlexey Bayduraev THREAD_MSG__READY,
1261e5de7d9SAlexey Bayduraev THREAD_MSG__MAX,
1271e5de7d9SAlexey Bayduraev };
1281e5de7d9SAlexey Bayduraev
1291e5de7d9SAlexey Bayduraev static const char *thread_msg_tags[THREAD_MSG__MAX] = {
1301e5de7d9SAlexey Bayduraev "UNDEFINED", "READY"
1311e5de7d9SAlexey Bayduraev };
1321e5de7d9SAlexey Bayduraev
13306380a84SAlexey Bayduraev enum thread_spec {
13406380a84SAlexey Bayduraev THREAD_SPEC__UNDEFINED = 0,
13506380a84SAlexey Bayduraev THREAD_SPEC__CPU,
136f466e5edSAlexey Bayduraev THREAD_SPEC__CORE,
137f466e5edSAlexey Bayduraev THREAD_SPEC__PACKAGE,
138f466e5edSAlexey Bayduraev THREAD_SPEC__NUMA,
139f466e5edSAlexey Bayduraev THREAD_SPEC__USER,
140f466e5edSAlexey Bayduraev THREAD_SPEC__MAX,
141f466e5edSAlexey Bayduraev };
142f466e5edSAlexey Bayduraev
143f466e5edSAlexey Bayduraev static const char *thread_spec_tags[THREAD_SPEC__MAX] = {
144f466e5edSAlexey Bayduraev "undefined", "cpu", "core", "package", "numa", "user"
14506380a84SAlexey Bayduraev };
14606380a84SAlexey Bayduraev
1476562c9acSAdrian Hunter struct pollfd_index_map {
1486562c9acSAdrian Hunter int evlist_pollfd_index;
1496562c9acSAdrian Hunter int thread_pollfd_index;
1506562c9acSAdrian Hunter };
1516562c9acSAdrian Hunter
1528c6f45a7SArnaldo Carvalho de Melo struct record {
15345694aa7SArnaldo Carvalho de Melo struct perf_tool tool;
154b4006796SArnaldo Carvalho de Melo struct record_opts opts;
155d20deb64SArnaldo Carvalho de Melo u64 bytes_written;
15691621be6SYang Jihong u64 thread_bytes_written;
1578ceb41d7SJiri Olsa struct perf_data data;
158ef149c25SAdrian Hunter struct auxtrace_record *itr;
15963503dbaSJiri Olsa struct evlist *evlist;
160d20deb64SArnaldo Carvalho de Melo struct perf_session *session;
161bc477d79SArnaldo Carvalho de Melo struct evlist *sb_evlist;
162899e5ffbSArnaldo Carvalho de Melo pthread_t thread_id;
163d20deb64SArnaldo Carvalho de Melo int realtime_prio;
164899e5ffbSArnaldo Carvalho de Melo bool switch_output_event_set;
165d20deb64SArnaldo Carvalho de Melo bool no_buildid;
166d2db9a98SWang Nan bool no_buildid_set;
167d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache;
168d2db9a98SWang Nan bool no_buildid_cache_set;
1696156681bSNamhyung Kim bool buildid_all;
170e29386c8SJiri Olsa bool buildid_mmap;
171ecfd7a9cSWang Nan bool timestamp_filename;
17268588bafSJin Yao bool timestamp_boundary;
173edc41a10SNamhyung Kim bool off_cpu;
1741b43b704SJiri Olsa struct switch_output switch_output;
1759f065194SYang Shi unsigned long long samples;
1766d575816SJiwei Sun unsigned long output_max_size; /* = 0: unlimited */
1779bce13eaSJiri Olsa struct perf_debuginfod debuginfod;
1787954f716SAlexey Bayduraev int nr_threads;
1797954f716SAlexey Bayduraev struct thread_mask *thread_masks;
180415ccb58SAlexey Bayduraev struct record_thread *thread_data;
1816562c9acSAdrian Hunter struct pollfd_index_map *index_map;
1826562c9acSAdrian Hunter size_t index_map_sz;
1836562c9acSAdrian Hunter size_t index_map_cnt;
1840f82ebc4SArnaldo Carvalho de Melo };
18586470930SIngo Molnar
1866d575816SJiwei Sun static volatile int done;
1876d575816SJiwei Sun
188dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
189dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
190dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
191dc0c6127SJiri Olsa
1929d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
1939d2ed645SAlexey Budankov "SYS", "NODE", "CPU"
1949d2ed645SAlexey Budankov };
1959d2ed645SAlexey Budankov
196415ccb58SAlexey Bayduraev #ifndef HAVE_GETTID
gettid(void)197415ccb58SAlexey Bayduraev static inline pid_t gettid(void)
198415ccb58SAlexey Bayduraev {
199415ccb58SAlexey Bayduraev return (pid_t)syscall(__NR_gettid);
200415ccb58SAlexey Bayduraev }
201415ccb58SAlexey Bayduraev #endif
202415ccb58SAlexey Bayduraev
record__threads_enabled(struct record * rec)2033217e9feSAlexey Bayduraev static int record__threads_enabled(struct record *rec)
2043217e9feSAlexey Bayduraev {
2053217e9feSAlexey Bayduraev return rec->opts.threads_spec;
2063217e9feSAlexey Bayduraev }
2073217e9feSAlexey Bayduraev
switch_output_signal(struct record * rec)208dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
209dc0c6127SJiri Olsa {
210dc0c6127SJiri Olsa return rec->switch_output.signal &&
211dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger);
212dc0c6127SJiri Olsa }
213dc0c6127SJiri Olsa
switch_output_size(struct record * rec)214dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
215dc0c6127SJiri Olsa {
216dc0c6127SJiri Olsa return rec->switch_output.size &&
217dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) &&
218dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size);
219dc0c6127SJiri Olsa }
220dc0c6127SJiri Olsa
switch_output_time(struct record * rec)221bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
222bfacbe3bSJiri Olsa {
223bfacbe3bSJiri Olsa return rec->switch_output.time &&
224bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger);
225bfacbe3bSJiri Olsa }
226bfacbe3bSJiri Olsa
record__bytes_written(struct record * rec)227ae9c7242SAlexey Bayduraev static u64 record__bytes_written(struct record *rec)
228ae9c7242SAlexey Bayduraev {
22991621be6SYang Jihong return rec->bytes_written + rec->thread_bytes_written;
230ae9c7242SAlexey Bayduraev }
231ae9c7242SAlexey Bayduraev
record__output_max_size_exceeded(struct record * rec)2326d575816SJiwei Sun static bool record__output_max_size_exceeded(struct record *rec)
2336d575816SJiwei Sun {
2346d575816SJiwei Sun return rec->output_max_size &&
235ae9c7242SAlexey Bayduraev (record__bytes_written(rec) >= rec->output_max_size);
2366d575816SJiwei Sun }
2376d575816SJiwei Sun
record__write(struct record * rec,struct mmap * map __maybe_unused,void * bf,size_t size)238a5830532SJiri Olsa static int record__write(struct record *rec, struct mmap *map __maybe_unused,
239ded2b8feSJiri Olsa void *bf, size_t size)
240f5970550SPeter Zijlstra {
241ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file;
242ded2b8feSJiri Olsa
24356f735ffSAlexey Bayduraev if (map && map->file)
24456f735ffSAlexey Bayduraev file = map->file;
24556f735ffSAlexey Bayduraev
246ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) {
2474f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n");
2488d3eca20SDavid Ahern return -1;
2498d3eca20SDavid Ahern }
250f5970550SPeter Zijlstra
25191621be6SYang Jihong if (map && map->file) {
252ae9c7242SAlexey Bayduraev thread->bytes_written += size;
25391621be6SYang Jihong rec->thread_bytes_written += size;
25491621be6SYang Jihong } else {
255cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size;
25691621be6SYang Jihong }
257dc0c6127SJiri Olsa
2586d575816SJiwei Sun if (record__output_max_size_exceeded(rec) && !done) {
2596d575816SJiwei Sun fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB),"
2606d575816SJiwei Sun " stopping session ]\n",
261ae9c7242SAlexey Bayduraev record__bytes_written(rec) >> 10);
2626d575816SJiwei Sun done = 1;
2636d575816SJiwei Sun }
2646d575816SJiwei Sun
265dc0c6127SJiri Olsa if (switch_output_size(rec))
266dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger);
267dc0c6127SJiri Olsa
2688d3eca20SDavid Ahern return 0;
269f5970550SPeter Zijlstra }
270f5970550SPeter Zijlstra
271ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec);
272ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec);
27375f5f1fcSAlexey Bayduraev static size_t zstd_compress(struct perf_session *session, struct mmap *map,
27475f5f1fcSAlexey Bayduraev void *dst, size_t dst_size, void *src, size_t src_size);
2755d7f4116SAlexey Budankov
276d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
record__aio_write(struct aiocb * cblock,int trace_fd,void * buf,size_t size,off_t off)277d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
278d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off)
279d3d1af6fSAlexey Budankov {
280d3d1af6fSAlexey Budankov int rc;
281d3d1af6fSAlexey Budankov
282d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd;
283d3d1af6fSAlexey Budankov cblock->aio_buf = buf;
284d3d1af6fSAlexey Budankov cblock->aio_nbytes = size;
285d3d1af6fSAlexey Budankov cblock->aio_offset = off;
286d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
287d3d1af6fSAlexey Budankov
288d3d1af6fSAlexey Budankov do {
289d3d1af6fSAlexey Budankov rc = aio_write(cblock);
290d3d1af6fSAlexey Budankov if (rc == 0) {
291d3d1af6fSAlexey Budankov break;
292d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) {
293d3d1af6fSAlexey Budankov cblock->aio_fildes = -1;
294d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n");
295d3d1af6fSAlexey Budankov break;
296d3d1af6fSAlexey Budankov }
297d3d1af6fSAlexey Budankov } while (1);
298d3d1af6fSAlexey Budankov
299d3d1af6fSAlexey Budankov return rc;
300d3d1af6fSAlexey Budankov }
301d3d1af6fSAlexey Budankov
record__aio_complete(struct mmap * md,struct aiocb * cblock)302a5830532SJiri Olsa static int record__aio_complete(struct mmap *md, struct aiocb *cblock)
303d3d1af6fSAlexey Budankov {
304d3d1af6fSAlexey Budankov void *rem_buf;
305d3d1af6fSAlexey Budankov off_t rem_off;
306d3d1af6fSAlexey Budankov size_t rem_size;
307d3d1af6fSAlexey Budankov int rc, aio_errno;
308d3d1af6fSAlexey Budankov ssize_t aio_ret, written;
309d3d1af6fSAlexey Budankov
310d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock);
311d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS)
312d3d1af6fSAlexey Budankov return 0;
313d3d1af6fSAlexey Budankov
314d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock);
315d3d1af6fSAlexey Budankov if (aio_ret < 0) {
316d3d1af6fSAlexey Budankov if (aio_errno != EINTR)
317d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n");
318d3d1af6fSAlexey Budankov written = 0;
319d3d1af6fSAlexey Budankov }
320d3d1af6fSAlexey Budankov
321d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written;
322d3d1af6fSAlexey Budankov
323d3d1af6fSAlexey Budankov if (rem_size == 0) {
324d3d1af6fSAlexey Budankov cblock->aio_fildes = -1;
325d3d1af6fSAlexey Budankov /*
326ef781128SAlexey Budankov * md->refcount is incremented in record__aio_pushfn() for
327ef781128SAlexey Budankov * every aio write request started in record__aio_push() so
328ef781128SAlexey Budankov * decrement it because the request is now complete.
329d3d1af6fSAlexey Budankov */
33080e53d11SJiri Olsa perf_mmap__put(&md->core);
331d3d1af6fSAlexey Budankov rc = 1;
332d3d1af6fSAlexey Budankov } else {
333d3d1af6fSAlexey Budankov /*
334d3d1af6fSAlexey Budankov * aio write request may require restart with the
335d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole
336d3d1af6fSAlexey Budankov * chunk at once.
337d3d1af6fSAlexey Budankov */
338d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written;
339d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written);
340d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes,
341d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off);
342d3d1af6fSAlexey Budankov rc = 0;
343d3d1af6fSAlexey Budankov }
344d3d1af6fSAlexey Budankov
345d3d1af6fSAlexey Budankov return rc;
346d3d1af6fSAlexey Budankov }
347d3d1af6fSAlexey Budankov
record__aio_sync(struct mmap * md,bool sync_all)348a5830532SJiri Olsa static int record__aio_sync(struct mmap *md, bool sync_all)
349d3d1af6fSAlexey Budankov {
35093f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb;
35193f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks;
352d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */
35393f20c0fSAlexey Budankov int i, do_suspend;
354d3d1af6fSAlexey Budankov
355d3d1af6fSAlexey Budankov do {
35693f20c0fSAlexey Budankov do_suspend = 0;
35793f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) {
35893f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
35993f20c0fSAlexey Budankov if (sync_all)
36093f20c0fSAlexey Budankov aiocb[i] = NULL;
36193f20c0fSAlexey Budankov else
36293f20c0fSAlexey Budankov return i;
36393f20c0fSAlexey Budankov } else {
36493f20c0fSAlexey Budankov /*
36593f20c0fSAlexey Budankov * Started aio write is not complete yet
36693f20c0fSAlexey Budankov * so it has to be waited before the
36793f20c0fSAlexey Budankov * next allocation.
36893f20c0fSAlexey Budankov */
36993f20c0fSAlexey Budankov aiocb[i] = &cblocks[i];
37093f20c0fSAlexey Budankov do_suspend = 1;
37193f20c0fSAlexey Budankov }
37293f20c0fSAlexey Budankov }
37393f20c0fSAlexey Budankov if (!do_suspend)
37493f20c0fSAlexey Budankov return -1;
375d3d1af6fSAlexey Budankov
37693f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
377d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR))
378d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n");
379d3d1af6fSAlexey Budankov }
380d3d1af6fSAlexey Budankov } while (1);
381d3d1af6fSAlexey Budankov }
382d3d1af6fSAlexey Budankov
383ef781128SAlexey Budankov struct record_aio {
384ef781128SAlexey Budankov struct record *rec;
385ef781128SAlexey Budankov void *data;
386ef781128SAlexey Budankov size_t size;
387ef781128SAlexey Budankov };
388ef781128SAlexey Budankov
record__aio_pushfn(struct mmap * map,void * to,void * buf,size_t size)389a5830532SJiri Olsa static int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size)
390d3d1af6fSAlexey Budankov {
391ef781128SAlexey Budankov struct record_aio *aio = to;
392ef781128SAlexey Budankov
393ef781128SAlexey Budankov /*
394547740f7SJiri Olsa * map->core.base data pointed by buf is copied into free map->aio.data[] buffer
395ef781128SAlexey Budankov * to release space in the kernel buffer as fast as possible, calling
396ef781128SAlexey Budankov * perf_mmap__consume() from perf_mmap__push() function.
397ef781128SAlexey Budankov *
398ef781128SAlexey Budankov * That lets the kernel to proceed with storing more profiling data into
399ef781128SAlexey Budankov * the kernel buffer earlier than other per-cpu kernel buffers are handled.
400ef781128SAlexey Budankov *
401ef781128SAlexey Budankov * Coping can be done in two steps in case the chunk of profiling data
402ef781128SAlexey Budankov * crosses the upper bound of the kernel buffer. In this case we first move
403ef781128SAlexey Budankov * part of data from map->start till the upper bound and then the reminder
404ef781128SAlexey Budankov * from the beginning of the kernel buffer till the end of the data chunk.
405ef781128SAlexey Budankov */
406ef781128SAlexey Budankov
407ef781128SAlexey Budankov if (record__comp_enabled(aio->rec)) {
40875f5f1fcSAlexey Bayduraev size = zstd_compress(aio->rec->session, NULL, aio->data + aio->size,
409bf59b305SJiri Olsa mmap__mmap_len(map) - aio->size,
410ef781128SAlexey Budankov buf, size);
411ef781128SAlexey Budankov } else {
412ef781128SAlexey Budankov memcpy(aio->data + aio->size, buf, size);
413ef781128SAlexey Budankov }
414ef781128SAlexey Budankov
415ef781128SAlexey Budankov if (!aio->size) {
416ef781128SAlexey Budankov /*
417ef781128SAlexey Budankov * Increment map->refcount to guard map->aio.data[] buffer
418ef781128SAlexey Budankov * from premature deallocation because map object can be
419ef781128SAlexey Budankov * released earlier than aio write request started on
420ef781128SAlexey Budankov * map->aio.data[] buffer is complete.
421ef781128SAlexey Budankov *
422ef781128SAlexey Budankov * perf_mmap__put() is done at record__aio_complete()
423ef781128SAlexey Budankov * after started aio request completion or at record__aio_push()
424ef781128SAlexey Budankov * if the request failed to start.
425ef781128SAlexey Budankov */
426e75710f0SJiri Olsa perf_mmap__get(&map->core);
427ef781128SAlexey Budankov }
428ef781128SAlexey Budankov
429ef781128SAlexey Budankov aio->size += size;
430ef781128SAlexey Budankov
431ef781128SAlexey Budankov return size;
432ef781128SAlexey Budankov }
433ef781128SAlexey Budankov
record__aio_push(struct record * rec,struct mmap * map,off_t * off)434a5830532SJiri Olsa static int record__aio_push(struct record *rec, struct mmap *map, off_t *off)
435ef781128SAlexey Budankov {
436ef781128SAlexey Budankov int ret, idx;
437ef781128SAlexey Budankov int trace_fd = rec->session->data->file.fd;
438ef781128SAlexey Budankov struct record_aio aio = { .rec = rec, .size = 0 };
439ef781128SAlexey Budankov
440ef781128SAlexey Budankov /*
441ef781128SAlexey Budankov * Call record__aio_sync() to wait till map->aio.data[] buffer
442ef781128SAlexey Budankov * becomes available after previous aio write operation.
443ef781128SAlexey Budankov */
444ef781128SAlexey Budankov
445ef781128SAlexey Budankov idx = record__aio_sync(map, false);
446ef781128SAlexey Budankov aio.data = map->aio.data[idx];
447ef781128SAlexey Budankov ret = perf_mmap__push(map, &aio, record__aio_pushfn);
448ef781128SAlexey Budankov if (ret != 0) /* ret > 0 - no data, ret < 0 - error */
449ef781128SAlexey Budankov return ret;
450d3d1af6fSAlexey Budankov
451d3d1af6fSAlexey Budankov rec->samples++;
452ef781128SAlexey Budankov ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off);
453d3d1af6fSAlexey Budankov if (!ret) {
454ef781128SAlexey Budankov *off += aio.size;
455ef781128SAlexey Budankov rec->bytes_written += aio.size;
456d3d1af6fSAlexey Budankov if (switch_output_size(rec))
457d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger);
458ef781128SAlexey Budankov } else {
459ef781128SAlexey Budankov /*
460ef781128SAlexey Budankov * Decrement map->refcount incremented in record__aio_pushfn()
461ef781128SAlexey Budankov * back if record__aio_write() operation failed to start, otherwise
462ef781128SAlexey Budankov * map->refcount is decremented in record__aio_complete() after
463ef781128SAlexey Budankov * aio write operation finishes successfully.
464ef781128SAlexey Budankov */
46580e53d11SJiri Olsa perf_mmap__put(&map->core);
466d3d1af6fSAlexey Budankov }
467d3d1af6fSAlexey Budankov
468d3d1af6fSAlexey Budankov return ret;
469d3d1af6fSAlexey Budankov }
470d3d1af6fSAlexey Budankov
record__aio_get_pos(int trace_fd)471d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
472d3d1af6fSAlexey Budankov {
473d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR);
474d3d1af6fSAlexey Budankov }
475d3d1af6fSAlexey Budankov
record__aio_set_pos(int trace_fd,off_t pos)476d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
477d3d1af6fSAlexey Budankov {
478d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET);
479d3d1af6fSAlexey Budankov }
480d3d1af6fSAlexey Budankov
record__aio_mmap_read_sync(struct record * rec)481d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
482d3d1af6fSAlexey Budankov {
483d3d1af6fSAlexey Budankov int i;
48463503dbaSJiri Olsa struct evlist *evlist = rec->evlist;
485a5830532SJiri Olsa struct mmap *maps = evlist->mmap;
486d3d1af6fSAlexey Budankov
487ef781128SAlexey Budankov if (!record__aio_enabled(rec))
488d3d1af6fSAlexey Budankov return;
489d3d1af6fSAlexey Budankov
490c976ee11SJiri Olsa for (i = 0; i < evlist->core.nr_mmaps; i++) {
491a5830532SJiri Olsa struct mmap *map = &maps[i];
492d3d1af6fSAlexey Budankov
493547740f7SJiri Olsa if (map->core.base)
49493f20c0fSAlexey Budankov record__aio_sync(map, true);
495d3d1af6fSAlexey Budankov }
496d3d1af6fSAlexey Budankov }
497d3d1af6fSAlexey Budankov
498d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
49993f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
500d3d1af6fSAlexey Budankov
record__aio_parse(const struct option * opt,const char * str,int unset)501d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
50293f20c0fSAlexey Budankov const char *str,
503d3d1af6fSAlexey Budankov int unset)
504d3d1af6fSAlexey Budankov {
505d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value;
506d3d1af6fSAlexey Budankov
50793f20c0fSAlexey Budankov if (unset) {
508d3d1af6fSAlexey Budankov opts->nr_cblocks = 0;
50993f20c0fSAlexey Budankov } else {
51093f20c0fSAlexey Budankov if (str)
51193f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0);
51293f20c0fSAlexey Budankov if (!opts->nr_cblocks)
513d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default;
51493f20c0fSAlexey Budankov }
515d3d1af6fSAlexey Budankov
516d3d1af6fSAlexey Budankov return 0;
517d3d1af6fSAlexey Budankov }
518d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
51993f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
52093f20c0fSAlexey Budankov
record__aio_push(struct record * rec __maybe_unused,struct mmap * map __maybe_unused,off_t * off __maybe_unused)521a5830532SJiri Olsa static int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused,
522ef781128SAlexey Budankov off_t *off __maybe_unused)
523d3d1af6fSAlexey Budankov {
524d3d1af6fSAlexey Budankov return -1;
525d3d1af6fSAlexey Budankov }
526d3d1af6fSAlexey Budankov
record__aio_get_pos(int trace_fd __maybe_unused)527d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
528d3d1af6fSAlexey Budankov {
529d3d1af6fSAlexey Budankov return -1;
530d3d1af6fSAlexey Budankov }
531d3d1af6fSAlexey Budankov
record__aio_set_pos(int trace_fd __maybe_unused,off_t pos __maybe_unused)532d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
533d3d1af6fSAlexey Budankov {
534d3d1af6fSAlexey Budankov }
535d3d1af6fSAlexey Budankov
record__aio_mmap_read_sync(struct record * rec __maybe_unused)536d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
537d3d1af6fSAlexey Budankov {
538d3d1af6fSAlexey Budankov }
539d3d1af6fSAlexey Budankov #endif
540d3d1af6fSAlexey Budankov
record__aio_enabled(struct record * rec)541d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
542d3d1af6fSAlexey Budankov {
543d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0;
544d3d1af6fSAlexey Budankov }
545d3d1af6fSAlexey Budankov
546470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
record__mmap_flush_parse(const struct option * opt,const char * str,int unset)547470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
548470530bbSAlexey Budankov const char *str,
549470530bbSAlexey Budankov int unset)
550470530bbSAlexey Budankov {
551470530bbSAlexey Budankov int flush_max;
552470530bbSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value;
553470530bbSAlexey Budankov static struct parse_tag tags[] = {
554470530bbSAlexey Budankov { .tag = 'B', .mult = 1 },
555470530bbSAlexey Budankov { .tag = 'K', .mult = 1 << 10 },
556470530bbSAlexey Budankov { .tag = 'M', .mult = 1 << 20 },
557470530bbSAlexey Budankov { .tag = 'G', .mult = 1 << 30 },
558470530bbSAlexey Budankov { .tag = 0 },
559470530bbSAlexey Budankov };
560470530bbSAlexey Budankov
561470530bbSAlexey Budankov if (unset)
562470530bbSAlexey Budankov return 0;
563470530bbSAlexey Budankov
564470530bbSAlexey Budankov if (str) {
565470530bbSAlexey Budankov opts->mmap_flush = parse_tag_value(str, tags);
566470530bbSAlexey Budankov if (opts->mmap_flush == (int)-1)
567470530bbSAlexey Budankov opts->mmap_flush = strtol(str, NULL, 0);
568470530bbSAlexey Budankov }
569470530bbSAlexey Budankov
570470530bbSAlexey Budankov if (!opts->mmap_flush)
571470530bbSAlexey Budankov opts->mmap_flush = MMAP_FLUSH_DEFAULT;
572470530bbSAlexey Budankov
5739521b5f2SJiri Olsa flush_max = evlist__mmap_size(opts->mmap_pages);
574470530bbSAlexey Budankov flush_max /= 4;
575470530bbSAlexey Budankov if (opts->mmap_flush > flush_max)
576470530bbSAlexey Budankov opts->mmap_flush = flush_max;
577470530bbSAlexey Budankov
578470530bbSAlexey Budankov return 0;
579470530bbSAlexey Budankov }
580470530bbSAlexey Budankov
581504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
582504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1;
583504c1ad1SAlexey Budankov
record__parse_comp_level(const struct option * opt,const char * str,int unset)584504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset)
585504c1ad1SAlexey Budankov {
586504c1ad1SAlexey Budankov struct record_opts *opts = opt->value;
587504c1ad1SAlexey Budankov
588504c1ad1SAlexey Budankov if (unset) {
589504c1ad1SAlexey Budankov opts->comp_level = 0;
590504c1ad1SAlexey Budankov } else {
591504c1ad1SAlexey Budankov if (str)
592504c1ad1SAlexey Budankov opts->comp_level = strtol(str, NULL, 0);
593504c1ad1SAlexey Budankov if (!opts->comp_level)
594504c1ad1SAlexey Budankov opts->comp_level = comp_level_default;
595504c1ad1SAlexey Budankov }
596504c1ad1SAlexey Budankov
597504c1ad1SAlexey Budankov return 0;
598504c1ad1SAlexey Budankov }
599504c1ad1SAlexey Budankov #endif
60051255a8aSAlexey Budankov static unsigned int comp_level_max = 22;
60151255a8aSAlexey Budankov
record__comp_enabled(struct record * rec)60242e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec)
60342e1fd80SAlexey Budankov {
60442e1fd80SAlexey Budankov return rec->opts.comp_level > 0;
60542e1fd80SAlexey Budankov }
60642e1fd80SAlexey Budankov
process_synthesized_event(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample __maybe_unused,struct machine * machine __maybe_unused)60745694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
608d20deb64SArnaldo Carvalho de Melo union perf_event *event,
6091d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused,
6101d037ca1SIrina Tirdea struct machine *machine __maybe_unused)
611234fbbf5SArnaldo Carvalho de Melo {
6128c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool);
613ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size);
614234fbbf5SArnaldo Carvalho de Melo }
615234fbbf5SArnaldo Carvalho de Melo
61649c670b1SIan Rogers static struct mutex synth_lock;
61749c670b1SIan Rogers
process_locked_synthesized_event(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample __maybe_unused,struct machine * machine __maybe_unused)618d99c22eaSStephane Eranian static int process_locked_synthesized_event(struct perf_tool *tool,
619d99c22eaSStephane Eranian union perf_event *event,
620d99c22eaSStephane Eranian struct perf_sample *sample __maybe_unused,
621d99c22eaSStephane Eranian struct machine *machine __maybe_unused)
622d99c22eaSStephane Eranian {
623d99c22eaSStephane Eranian int ret;
624d99c22eaSStephane Eranian
62549c670b1SIan Rogers mutex_lock(&synth_lock);
626d99c22eaSStephane Eranian ret = process_synthesized_event(tool, event, sample, machine);
62749c670b1SIan Rogers mutex_unlock(&synth_lock);
628d99c22eaSStephane Eranian return ret;
629d99c22eaSStephane Eranian }
630d99c22eaSStephane Eranian
record__pushfn(struct mmap * map,void * to,void * bf,size_t size)631a5830532SJiri Olsa static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size)
632d37f1586SArnaldo Carvalho de Melo {
633d37f1586SArnaldo Carvalho de Melo struct record *rec = to;
634d37f1586SArnaldo Carvalho de Melo
6355d7f4116SAlexey Budankov if (record__comp_enabled(rec)) {
63675f5f1fcSAlexey Bayduraev size = zstd_compress(rec->session, map, map->data, mmap__mmap_len(map), bf, size);
6375d7f4116SAlexey Budankov bf = map->data;
6385d7f4116SAlexey Budankov }
6395d7f4116SAlexey Budankov
640396b626bSAlexey Bayduraev thread->samples++;
641ded2b8feSJiri Olsa return record__write(rec, map, bf, size);
642d37f1586SArnaldo Carvalho de Melo }
643d37f1586SArnaldo Carvalho de Melo
6448ed28c2bSIan Rogers static volatile sig_atomic_t signr = -1;
6458ed28c2bSIan Rogers static volatile sig_atomic_t child_finished;
646da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
6478ed28c2bSIan Rogers static volatile sig_atomic_t done_fd = -1;
648da231338SAnand K Mistry #endif
649c0bdc1c4SWang Nan
sig_handler(int sig)6502dd6d8a1SAdrian Hunter static void sig_handler(int sig)
6512dd6d8a1SAdrian Hunter {
6522dd6d8a1SAdrian Hunter if (sig == SIGCHLD)
6532dd6d8a1SAdrian Hunter child_finished = 1;
6542dd6d8a1SAdrian Hunter else
6552dd6d8a1SAdrian Hunter signr = sig;
6562dd6d8a1SAdrian Hunter
6572dd6d8a1SAdrian Hunter done = 1;
658da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
659304f0a2fSIan Rogers if (done_fd >= 0) {
660da231338SAnand K Mistry u64 tmp = 1;
661304f0a2fSIan Rogers int orig_errno = errno;
662304f0a2fSIan Rogers
663da231338SAnand K Mistry /*
664304f0a2fSIan Rogers * It is possible for this signal handler to run after done is
665304f0a2fSIan Rogers * checked in the main loop, but before the perf counter fds are
666304f0a2fSIan Rogers * polled. If this happens, the poll() will continue to wait
667304f0a2fSIan Rogers * even though done is set, and will only break out if either
668304f0a2fSIan Rogers * another signal is received, or the counters are ready for
669304f0a2fSIan Rogers * read. To ensure the poll() doesn't sleep when done is set,
670304f0a2fSIan Rogers * use an eventfd (done_fd) to wake up the poll().
671da231338SAnand K Mistry */
672da231338SAnand K Mistry if (write(done_fd, &tmp, sizeof(tmp)) < 0)
673da231338SAnand K Mistry pr_err("failed to signal wakeup fd, error: %m\n");
674304f0a2fSIan Rogers
675304f0a2fSIan Rogers errno = orig_errno;
676da231338SAnand K Mistry }
677da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT
6782dd6d8a1SAdrian Hunter }
6792dd6d8a1SAdrian Hunter
sigsegv_handler(int sig)680a074865eSWang Nan static void sigsegv_handler(int sig)
681a074865eSWang Nan {
682a074865eSWang Nan perf_hooks__recover();
683a074865eSWang Nan sighandler_dump_stack(sig);
684a074865eSWang Nan }
685a074865eSWang Nan
record__sig_exit(void)6862dd6d8a1SAdrian Hunter static void record__sig_exit(void)
6872dd6d8a1SAdrian Hunter {
6882dd6d8a1SAdrian Hunter if (signr == -1)
6892dd6d8a1SAdrian Hunter return;
6902dd6d8a1SAdrian Hunter
6912dd6d8a1SAdrian Hunter signal(signr, SIG_DFL);
6922dd6d8a1SAdrian Hunter raise(signr);
6932dd6d8a1SAdrian Hunter }
6942dd6d8a1SAdrian Hunter
695e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
696e31f0d01SAdrian Hunter
record__process_auxtrace(struct perf_tool * tool,struct mmap * map,union perf_event * event,void * data1,size_t len1,void * data2,size_t len2)697ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
698a5830532SJiri Olsa struct mmap *map,
699ef149c25SAdrian Hunter union perf_event *event, void *data1,
700ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2)
701ef149c25SAdrian Hunter {
702ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool);
7038ceb41d7SJiri Olsa struct perf_data *data = &rec->data;
704ef149c25SAdrian Hunter size_t padding;
705ef149c25SAdrian Hunter u8 pad[8] = {0};
706ef149c25SAdrian Hunter
70746e201efSAdrian Hunter if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) {
70899fa2984SAdrian Hunter off_t file_offset;
7098ceb41d7SJiri Olsa int fd = perf_data__fd(data);
71099fa2984SAdrian Hunter int err;
71199fa2984SAdrian Hunter
71299fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR);
71399fa2984SAdrian Hunter if (file_offset == -1)
71499fa2984SAdrian Hunter return -1;
71599fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
71699fa2984SAdrian Hunter event, file_offset);
71799fa2984SAdrian Hunter if (err)
71899fa2984SAdrian Hunter return err;
71999fa2984SAdrian Hunter }
72099fa2984SAdrian Hunter
721ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
722ef149c25SAdrian Hunter padding = (len1 + len2) & 7;
723ef149c25SAdrian Hunter if (padding)
724ef149c25SAdrian Hunter padding = 8 - padding;
725ef149c25SAdrian Hunter
726ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size);
727ded2b8feSJiri Olsa record__write(rec, map, data1, len1);
728ef149c25SAdrian Hunter if (len2)
729ded2b8feSJiri Olsa record__write(rec, map, data2, len2);
730ded2b8feSJiri Olsa record__write(rec, map, &pad, padding);
731ef149c25SAdrian Hunter
732ef149c25SAdrian Hunter return 0;
733ef149c25SAdrian Hunter }
734ef149c25SAdrian Hunter
record__auxtrace_mmap_read(struct record * rec,struct mmap * map)735ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
736a5830532SJiri Olsa struct mmap *map)
737ef149c25SAdrian Hunter {
738ef149c25SAdrian Hunter int ret;
739ef149c25SAdrian Hunter
740e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
741ef149c25SAdrian Hunter record__process_auxtrace);
742ef149c25SAdrian Hunter if (ret < 0)
743ef149c25SAdrian Hunter return ret;
744ef149c25SAdrian Hunter
745ef149c25SAdrian Hunter if (ret)
746ef149c25SAdrian Hunter rec->samples++;
747ef149c25SAdrian Hunter
748ef149c25SAdrian Hunter return 0;
749ef149c25SAdrian Hunter }
750ef149c25SAdrian Hunter
record__auxtrace_mmap_read_snapshot(struct record * rec,struct mmap * map)7512dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
752a5830532SJiri Olsa struct mmap *map)
7532dd6d8a1SAdrian Hunter {
7542dd6d8a1SAdrian Hunter int ret;
7552dd6d8a1SAdrian Hunter
756e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
7572dd6d8a1SAdrian Hunter record__process_auxtrace,
7582dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size);
7592dd6d8a1SAdrian Hunter if (ret < 0)
7602dd6d8a1SAdrian Hunter return ret;
7612dd6d8a1SAdrian Hunter
7622dd6d8a1SAdrian Hunter if (ret)
7632dd6d8a1SAdrian Hunter rec->samples++;
7642dd6d8a1SAdrian Hunter
7652dd6d8a1SAdrian Hunter return 0;
7662dd6d8a1SAdrian Hunter }
7672dd6d8a1SAdrian Hunter
record__auxtrace_read_snapshot_all(struct record * rec)7682dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
7692dd6d8a1SAdrian Hunter {
7702dd6d8a1SAdrian Hunter int i;
7712dd6d8a1SAdrian Hunter int rc = 0;
7722dd6d8a1SAdrian Hunter
773c976ee11SJiri Olsa for (i = 0; i < rec->evlist->core.nr_mmaps; i++) {
774a5830532SJiri Olsa struct mmap *map = &rec->evlist->mmap[i];
7752dd6d8a1SAdrian Hunter
776e035f4caSJiri Olsa if (!map->auxtrace_mmap.base)
7772dd6d8a1SAdrian Hunter continue;
7782dd6d8a1SAdrian Hunter
779e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
7802dd6d8a1SAdrian Hunter rc = -1;
7812dd6d8a1SAdrian Hunter goto out;
7822dd6d8a1SAdrian Hunter }
7832dd6d8a1SAdrian Hunter }
7842dd6d8a1SAdrian Hunter out:
7852dd6d8a1SAdrian Hunter return rc;
7862dd6d8a1SAdrian Hunter }
7872dd6d8a1SAdrian Hunter
record__read_auxtrace_snapshot(struct record * rec,bool on_exit)788ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
7892dd6d8a1SAdrian Hunter {
7902dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n");
7912dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) {
7925f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger);
7932dd6d8a1SAdrian Hunter } else {
794ce7b0e42SAlexander Shishkin if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
7955f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger);
7965f9cf599SWang Nan else
7975f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger);
7982dd6d8a1SAdrian Hunter }
7992dd6d8a1SAdrian Hunter }
8002dd6d8a1SAdrian Hunter
record__auxtrace_snapshot_exit(struct record * rec)801ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec)
802ce7b0e42SAlexander Shishkin {
803ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger))
804ce7b0e42SAlexander Shishkin return 0;
805ce7b0e42SAlexander Shishkin
806ce7b0e42SAlexander Shishkin if (!auxtrace_record__snapshot_started &&
807ce7b0e42SAlexander Shishkin auxtrace_record__snapshot_start(rec->itr))
808ce7b0e42SAlexander Shishkin return -1;
809ce7b0e42SAlexander Shishkin
810ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, true);
811ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger))
812ce7b0e42SAlexander Shishkin return -1;
813ce7b0e42SAlexander Shishkin
814ce7b0e42SAlexander Shishkin return 0;
815ce7b0e42SAlexander Shishkin }
816ce7b0e42SAlexander Shishkin
record__auxtrace_init(struct record * rec)8174b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
8184b5ea3bdSAdrian Hunter {
8194b5ea3bdSAdrian Hunter int err;
8204b5ea3bdSAdrian Hunter
821b5f2511dSAlexey Bayduraev if ((rec->opts.auxtrace_snapshot_opts || rec->opts.auxtrace_sample_opts)
822b5f2511dSAlexey Bayduraev && record__threads_enabled(rec)) {
823b5f2511dSAlexey Bayduraev pr_err("AUX area tracing options are not available in parallel streaming mode.\n");
824b5f2511dSAlexey Bayduraev return -EINVAL;
825b5f2511dSAlexey Bayduraev }
826b5f2511dSAlexey Bayduraev
8274b5ea3bdSAdrian Hunter if (!rec->itr) {
8284b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err);
8294b5ea3bdSAdrian Hunter if (err)
8304b5ea3bdSAdrian Hunter return err;
8314b5ea3bdSAdrian Hunter }
8324b5ea3bdSAdrian Hunter
8334b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
8344b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts);
8354b5ea3bdSAdrian Hunter if (err)
8364b5ea3bdSAdrian Hunter return err;
8374b5ea3bdSAdrian Hunter
838c0a6de06SAdrian Hunter err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts,
839c0a6de06SAdrian Hunter rec->opts.auxtrace_sample_opts);
840c0a6de06SAdrian Hunter if (err)
841c0a6de06SAdrian Hunter return err;
842c0a6de06SAdrian Hunter
843d58b3f7eSAdrian Hunter auxtrace_regroup_aux_output(rec->evlist);
844d58b3f7eSAdrian Hunter
8454b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist);
8464b5ea3bdSAdrian Hunter }
8474b5ea3bdSAdrian Hunter
848e31f0d01SAdrian Hunter #else
849e31f0d01SAdrian Hunter
850e31f0d01SAdrian Hunter static inline
record__auxtrace_mmap_read(struct record * rec __maybe_unused,struct mmap * map __maybe_unused)851e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
852a5830532SJiri Olsa struct mmap *map __maybe_unused)
853e31f0d01SAdrian Hunter {
854e31f0d01SAdrian Hunter return 0;
855e31f0d01SAdrian Hunter }
856e31f0d01SAdrian Hunter
8572dd6d8a1SAdrian Hunter static inline
record__read_auxtrace_snapshot(struct record * rec __maybe_unused,bool on_exit __maybe_unused)858ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
859ce7b0e42SAlexander Shishkin bool on_exit __maybe_unused)
8602dd6d8a1SAdrian Hunter {
8612dd6d8a1SAdrian Hunter }
8622dd6d8a1SAdrian Hunter
8632dd6d8a1SAdrian Hunter static inline
auxtrace_record__snapshot_start(struct auxtrace_record * itr __maybe_unused)8642dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
8652dd6d8a1SAdrian Hunter {
8662dd6d8a1SAdrian Hunter return 0;
8672dd6d8a1SAdrian Hunter }
8682dd6d8a1SAdrian Hunter
869ce7b0e42SAlexander Shishkin static inline
record__auxtrace_snapshot_exit(struct record * rec __maybe_unused)870ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
871ce7b0e42SAlexander Shishkin {
872ce7b0e42SAlexander Shishkin return 0;
873ce7b0e42SAlexander Shishkin }
874ce7b0e42SAlexander Shishkin
record__auxtrace_init(struct record * rec __maybe_unused)8754b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
8764b5ea3bdSAdrian Hunter {
8774b5ea3bdSAdrian Hunter return 0;
8784b5ea3bdSAdrian Hunter }
8794b5ea3bdSAdrian Hunter
880e31f0d01SAdrian Hunter #endif
881e31f0d01SAdrian Hunter
record__config_text_poke(struct evlist * evlist)882246eba8eSAdrian Hunter static int record__config_text_poke(struct evlist *evlist)
883246eba8eSAdrian Hunter {
884246eba8eSAdrian Hunter struct evsel *evsel;
885246eba8eSAdrian Hunter
886246eba8eSAdrian Hunter /* Nothing to do if text poke is already configured */
887246eba8eSAdrian Hunter evlist__for_each_entry(evlist, evsel) {
888246eba8eSAdrian Hunter if (evsel->core.attr.text_poke)
889246eba8eSAdrian Hunter return 0;
890246eba8eSAdrian Hunter }
891246eba8eSAdrian Hunter
892921e3be5SAdrian Hunter evsel = evlist__add_dummy_on_all_cpus(evlist);
893921e3be5SAdrian Hunter if (!evsel)
894921e3be5SAdrian Hunter return -ENOMEM;
895246eba8eSAdrian Hunter
896246eba8eSAdrian Hunter evsel->core.attr.text_poke = 1;
897246eba8eSAdrian Hunter evsel->core.attr.ksymbol = 1;
898246eba8eSAdrian Hunter evsel->immediate = true;
899246eba8eSAdrian Hunter evsel__set_sample_bit(evsel, TIME);
900246eba8eSAdrian Hunter
901246eba8eSAdrian Hunter return 0;
902246eba8eSAdrian Hunter }
903246eba8eSAdrian Hunter
record__config_off_cpu(struct record * rec)904edc41a10SNamhyung Kim static int record__config_off_cpu(struct record *rec)
905edc41a10SNamhyung Kim {
906685439a7SNamhyung Kim return off_cpu_prepare(rec->evlist, &rec->opts.target, &rec->opts);
907edc41a10SNamhyung Kim }
908edc41a10SNamhyung Kim
record__config_tracking_events(struct record * rec)909aa4158e3SYang Jihong static int record__config_tracking_events(struct record *rec)
910aa4158e3SYang Jihong {
911aa4158e3SYang Jihong struct record_opts *opts = &rec->opts;
912aa4158e3SYang Jihong struct evlist *evlist = rec->evlist;
913aa4158e3SYang Jihong struct evsel *evsel;
914aa4158e3SYang Jihong
915aa4158e3SYang Jihong /*
916aa4158e3SYang Jihong * For initial_delay, system wide or a hybrid system, we need to add
917aa4158e3SYang Jihong * tracking event so that we can track PERF_RECORD_MMAP to cover the
918aa4158e3SYang Jihong * delay of waiting or event synthesis.
919aa4158e3SYang Jihong */
920aa4158e3SYang Jihong if (opts->target.initial_delay || target__has_cpu(&opts->target) ||
921aa4158e3SYang Jihong perf_pmus__num_core_pmus() > 1) {
922aa4158e3SYang Jihong evsel = evlist__findnew_tracking_event(evlist, false);
923aa4158e3SYang Jihong if (!evsel)
924aa4158e3SYang Jihong return -ENOMEM;
925aa4158e3SYang Jihong
926aa4158e3SYang Jihong /*
927aa4158e3SYang Jihong * Enable the tracking event when the process is forked for
928aa4158e3SYang Jihong * initial_delay, immediately for system wide.
929aa4158e3SYang Jihong */
930aa4158e3SYang Jihong if (opts->target.initial_delay && !evsel->immediate &&
931aa4158e3SYang Jihong !target__has_cpu(&opts->target))
932aa4158e3SYang Jihong evsel->core.attr.enable_on_exec = 1;
933aa4158e3SYang Jihong else
934aa4158e3SYang Jihong evsel->immediate = 1;
935aa4158e3SYang Jihong }
936aa4158e3SYang Jihong
937aa4158e3SYang Jihong return 0;
938aa4158e3SYang Jihong }
939aa4158e3SYang Jihong
record__kcore_readable(struct machine * machine)940eeb399b5SAdrian Hunter static bool record__kcore_readable(struct machine *machine)
941eeb399b5SAdrian Hunter {
942eeb399b5SAdrian Hunter char kcore[PATH_MAX];
943eeb399b5SAdrian Hunter int fd;
944eeb399b5SAdrian Hunter
945eeb399b5SAdrian Hunter scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir);
946eeb399b5SAdrian Hunter
947eeb399b5SAdrian Hunter fd = open(kcore, O_RDONLY);
948eeb399b5SAdrian Hunter if (fd < 0)
949eeb399b5SAdrian Hunter return false;
950eeb399b5SAdrian Hunter
951eeb399b5SAdrian Hunter close(fd);
952eeb399b5SAdrian Hunter
953eeb399b5SAdrian Hunter return true;
954eeb399b5SAdrian Hunter }
955eeb399b5SAdrian Hunter
record__kcore_copy(struct machine * machine,struct perf_data * data)956eeb399b5SAdrian Hunter static int record__kcore_copy(struct machine *machine, struct perf_data *data)
957eeb399b5SAdrian Hunter {
958eeb399b5SAdrian Hunter char from_dir[PATH_MAX];
959eeb399b5SAdrian Hunter char kcore_dir[PATH_MAX];
960eeb399b5SAdrian Hunter int ret;
961eeb399b5SAdrian Hunter
962eeb399b5SAdrian Hunter snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir);
963eeb399b5SAdrian Hunter
964eeb399b5SAdrian Hunter ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir));
965eeb399b5SAdrian Hunter if (ret)
966eeb399b5SAdrian Hunter return ret;
967eeb399b5SAdrian Hunter
968eeb399b5SAdrian Hunter return kcore_copy(from_dir, kcore_dir);
969eeb399b5SAdrian Hunter }
970eeb399b5SAdrian Hunter
record__thread_data_init_pipes(struct record_thread * thread_data)971415ccb58SAlexey Bayduraev static void record__thread_data_init_pipes(struct record_thread *thread_data)
972415ccb58SAlexey Bayduraev {
973415ccb58SAlexey Bayduraev thread_data->pipes.msg[0] = -1;
974415ccb58SAlexey Bayduraev thread_data->pipes.msg[1] = -1;
975415ccb58SAlexey Bayduraev thread_data->pipes.ack[0] = -1;
976415ccb58SAlexey Bayduraev thread_data->pipes.ack[1] = -1;
977415ccb58SAlexey Bayduraev }
978415ccb58SAlexey Bayduraev
record__thread_data_open_pipes(struct record_thread * thread_data)979415ccb58SAlexey Bayduraev static int record__thread_data_open_pipes(struct record_thread *thread_data)
980415ccb58SAlexey Bayduraev {
981415ccb58SAlexey Bayduraev if (pipe(thread_data->pipes.msg))
982415ccb58SAlexey Bayduraev return -EINVAL;
983415ccb58SAlexey Bayduraev
984415ccb58SAlexey Bayduraev if (pipe(thread_data->pipes.ack)) {
985415ccb58SAlexey Bayduraev close(thread_data->pipes.msg[0]);
986415ccb58SAlexey Bayduraev thread_data->pipes.msg[0] = -1;
987415ccb58SAlexey Bayduraev close(thread_data->pipes.msg[1]);
988415ccb58SAlexey Bayduraev thread_data->pipes.msg[1] = -1;
989415ccb58SAlexey Bayduraev return -EINVAL;
990415ccb58SAlexey Bayduraev }
991415ccb58SAlexey Bayduraev
992415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: msg=[%d,%d], ack=[%d,%d]\n", thread_data,
993415ccb58SAlexey Bayduraev thread_data->pipes.msg[0], thread_data->pipes.msg[1],
994415ccb58SAlexey Bayduraev thread_data->pipes.ack[0], thread_data->pipes.ack[1]);
995415ccb58SAlexey Bayduraev
996415ccb58SAlexey Bayduraev return 0;
997415ccb58SAlexey Bayduraev }
998415ccb58SAlexey Bayduraev
record__thread_data_close_pipes(struct record_thread * thread_data)999415ccb58SAlexey Bayduraev static void record__thread_data_close_pipes(struct record_thread *thread_data)
1000415ccb58SAlexey Bayduraev {
1001415ccb58SAlexey Bayduraev if (thread_data->pipes.msg[0] != -1) {
1002415ccb58SAlexey Bayduraev close(thread_data->pipes.msg[0]);
1003415ccb58SAlexey Bayduraev thread_data->pipes.msg[0] = -1;
1004415ccb58SAlexey Bayduraev }
1005415ccb58SAlexey Bayduraev if (thread_data->pipes.msg[1] != -1) {
1006415ccb58SAlexey Bayduraev close(thread_data->pipes.msg[1]);
1007415ccb58SAlexey Bayduraev thread_data->pipes.msg[1] = -1;
1008415ccb58SAlexey Bayduraev }
1009415ccb58SAlexey Bayduraev if (thread_data->pipes.ack[0] != -1) {
1010415ccb58SAlexey Bayduraev close(thread_data->pipes.ack[0]);
1011415ccb58SAlexey Bayduraev thread_data->pipes.ack[0] = -1;
1012415ccb58SAlexey Bayduraev }
1013415ccb58SAlexey Bayduraev if (thread_data->pipes.ack[1] != -1) {
1014415ccb58SAlexey Bayduraev close(thread_data->pipes.ack[1]);
1015415ccb58SAlexey Bayduraev thread_data->pipes.ack[1] = -1;
1016415ccb58SAlexey Bayduraev }
1017415ccb58SAlexey Bayduraev }
1018415ccb58SAlexey Bayduraev
evlist__per_thread(struct evlist * evlist)10197be1feddSAdrian Hunter static bool evlist__per_thread(struct evlist *evlist)
10207be1feddSAdrian Hunter {
10217be1feddSAdrian Hunter return cpu_map__is_dummy(evlist->core.user_requested_cpus);
10227be1feddSAdrian Hunter }
10237be1feddSAdrian Hunter
record__thread_data_init_maps(struct record_thread * thread_data,struct evlist * evlist)1024415ccb58SAlexey Bayduraev static int record__thread_data_init_maps(struct record_thread *thread_data, struct evlist *evlist)
1025415ccb58SAlexey Bayduraev {
1026415ccb58SAlexey Bayduraev int m, tm, nr_mmaps = evlist->core.nr_mmaps;
1027415ccb58SAlexey Bayduraev struct mmap *mmap = evlist->mmap;
1028415ccb58SAlexey Bayduraev struct mmap *overwrite_mmap = evlist->overwrite_mmap;
10297be1feddSAdrian Hunter struct perf_cpu_map *cpus = evlist->core.all_cpus;
10307be1feddSAdrian Hunter bool per_thread = evlist__per_thread(evlist);
1031415ccb58SAlexey Bayduraev
10327be1feddSAdrian Hunter if (per_thread)
103323380e4dSAlexey Bayduraev thread_data->nr_mmaps = nr_mmaps;
103423380e4dSAlexey Bayduraev else
1035415ccb58SAlexey Bayduraev thread_data->nr_mmaps = bitmap_weight(thread_data->mask->maps.bits,
1036415ccb58SAlexey Bayduraev thread_data->mask->maps.nbits);
1037415ccb58SAlexey Bayduraev if (mmap) {
1038415ccb58SAlexey Bayduraev thread_data->maps = zalloc(thread_data->nr_mmaps * sizeof(struct mmap *));
1039415ccb58SAlexey Bayduraev if (!thread_data->maps)
1040415ccb58SAlexey Bayduraev return -ENOMEM;
1041415ccb58SAlexey Bayduraev }
1042415ccb58SAlexey Bayduraev if (overwrite_mmap) {
1043415ccb58SAlexey Bayduraev thread_data->overwrite_maps = zalloc(thread_data->nr_mmaps * sizeof(struct mmap *));
1044415ccb58SAlexey Bayduraev if (!thread_data->overwrite_maps) {
1045415ccb58SAlexey Bayduraev zfree(&thread_data->maps);
1046415ccb58SAlexey Bayduraev return -ENOMEM;
1047415ccb58SAlexey Bayduraev }
1048415ccb58SAlexey Bayduraev }
1049415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: nr_mmaps=%d, maps=%p, ow_maps=%p\n", thread_data,
1050415ccb58SAlexey Bayduraev thread_data->nr_mmaps, thread_data->maps, thread_data->overwrite_maps);
1051415ccb58SAlexey Bayduraev
1052415ccb58SAlexey Bayduraev for (m = 0, tm = 0; m < nr_mmaps && tm < thread_data->nr_mmaps; m++) {
10537be1feddSAdrian Hunter if (per_thread ||
10540255571aSIan Rogers test_bit(perf_cpu_map__cpu(cpus, m).cpu, thread_data->mask->maps.bits)) {
1055415ccb58SAlexey Bayduraev if (thread_data->maps) {
1056415ccb58SAlexey Bayduraev thread_data->maps[tm] = &mmap[m];
1057415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: cpu%d: maps[%d] -> mmap[%d]\n",
105823380e4dSAlexey Bayduraev thread_data, perf_cpu_map__cpu(cpus, m).cpu, tm, m);
1059415ccb58SAlexey Bayduraev }
1060415ccb58SAlexey Bayduraev if (thread_data->overwrite_maps) {
1061415ccb58SAlexey Bayduraev thread_data->overwrite_maps[tm] = &overwrite_mmap[m];
1062415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: cpu%d: ow_maps[%d] -> ow_mmap[%d]\n",
106323380e4dSAlexey Bayduraev thread_data, perf_cpu_map__cpu(cpus, m).cpu, tm, m);
1064415ccb58SAlexey Bayduraev }
1065415ccb58SAlexey Bayduraev tm++;
1066415ccb58SAlexey Bayduraev }
1067415ccb58SAlexey Bayduraev }
1068415ccb58SAlexey Bayduraev
1069415ccb58SAlexey Bayduraev return 0;
1070415ccb58SAlexey Bayduraev }
1071415ccb58SAlexey Bayduraev
record__thread_data_init_pollfd(struct record_thread * thread_data,struct evlist * evlist)1072415ccb58SAlexey Bayduraev static int record__thread_data_init_pollfd(struct record_thread *thread_data, struct evlist *evlist)
1073415ccb58SAlexey Bayduraev {
1074415ccb58SAlexey Bayduraev int f, tm, pos;
1075415ccb58SAlexey Bayduraev struct mmap *map, *overwrite_map;
1076415ccb58SAlexey Bayduraev
1077415ccb58SAlexey Bayduraev fdarray__init(&thread_data->pollfd, 64);
1078415ccb58SAlexey Bayduraev
1079415ccb58SAlexey Bayduraev for (tm = 0; tm < thread_data->nr_mmaps; tm++) {
1080415ccb58SAlexey Bayduraev map = thread_data->maps ? thread_data->maps[tm] : NULL;
1081415ccb58SAlexey Bayduraev overwrite_map = thread_data->overwrite_maps ?
1082415ccb58SAlexey Bayduraev thread_data->overwrite_maps[tm] : NULL;
1083415ccb58SAlexey Bayduraev
1084415ccb58SAlexey Bayduraev for (f = 0; f < evlist->core.pollfd.nr; f++) {
1085415ccb58SAlexey Bayduraev void *ptr = evlist->core.pollfd.priv[f].ptr;
1086415ccb58SAlexey Bayduraev
1087415ccb58SAlexey Bayduraev if ((map && ptr == map) || (overwrite_map && ptr == overwrite_map)) {
1088415ccb58SAlexey Bayduraev pos = fdarray__dup_entry_from(&thread_data->pollfd, f,
1089415ccb58SAlexey Bayduraev &evlist->core.pollfd);
1090415ccb58SAlexey Bayduraev if (pos < 0)
1091415ccb58SAlexey Bayduraev return pos;
1092415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: pollfd[%d] <- event_fd=%d\n",
1093415ccb58SAlexey Bayduraev thread_data, pos, evlist->core.pollfd.entries[f].fd);
1094415ccb58SAlexey Bayduraev }
1095415ccb58SAlexey Bayduraev }
1096415ccb58SAlexey Bayduraev }
1097415ccb58SAlexey Bayduraev
1098415ccb58SAlexey Bayduraev return 0;
1099415ccb58SAlexey Bayduraev }
1100415ccb58SAlexey Bayduraev
record__free_thread_data(struct record * rec)1101415ccb58SAlexey Bayduraev static void record__free_thread_data(struct record *rec)
1102415ccb58SAlexey Bayduraev {
1103415ccb58SAlexey Bayduraev int t;
1104415ccb58SAlexey Bayduraev struct record_thread *thread_data = rec->thread_data;
1105415ccb58SAlexey Bayduraev
1106415ccb58SAlexey Bayduraev if (thread_data == NULL)
1107415ccb58SAlexey Bayduraev return;
1108415ccb58SAlexey Bayduraev
1109415ccb58SAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++) {
1110415ccb58SAlexey Bayduraev record__thread_data_close_pipes(&thread_data[t]);
1111415ccb58SAlexey Bayduraev zfree(&thread_data[t].maps);
1112415ccb58SAlexey Bayduraev zfree(&thread_data[t].overwrite_maps);
1113415ccb58SAlexey Bayduraev fdarray__exit(&thread_data[t].pollfd);
1114415ccb58SAlexey Bayduraev }
1115415ccb58SAlexey Bayduraev
1116415ccb58SAlexey Bayduraev zfree(&rec->thread_data);
1117415ccb58SAlexey Bayduraev }
1118415ccb58SAlexey Bayduraev
record__map_thread_evlist_pollfd_indexes(struct record * rec,int evlist_pollfd_index,int thread_pollfd_index)11196562c9acSAdrian Hunter static int record__map_thread_evlist_pollfd_indexes(struct record *rec,
11206562c9acSAdrian Hunter int evlist_pollfd_index,
11216562c9acSAdrian Hunter int thread_pollfd_index)
11226562c9acSAdrian Hunter {
11236562c9acSAdrian Hunter size_t x = rec->index_map_cnt;
11246562c9acSAdrian Hunter
11256562c9acSAdrian Hunter if (realloc_array_as_needed(rec->index_map, rec->index_map_sz, x, NULL))
11266562c9acSAdrian Hunter return -ENOMEM;
11276562c9acSAdrian Hunter rec->index_map[x].evlist_pollfd_index = evlist_pollfd_index;
11286562c9acSAdrian Hunter rec->index_map[x].thread_pollfd_index = thread_pollfd_index;
11296562c9acSAdrian Hunter rec->index_map_cnt += 1;
11306562c9acSAdrian Hunter return 0;
11316562c9acSAdrian Hunter }
11326562c9acSAdrian Hunter
record__update_evlist_pollfd_from_thread(struct record * rec,struct evlist * evlist,struct record_thread * thread_data)11336562c9acSAdrian Hunter static int record__update_evlist_pollfd_from_thread(struct record *rec,
11346562c9acSAdrian Hunter struct evlist *evlist,
11356562c9acSAdrian Hunter struct record_thread *thread_data)
11366562c9acSAdrian Hunter {
11376562c9acSAdrian Hunter struct pollfd *e_entries = evlist->core.pollfd.entries;
11386562c9acSAdrian Hunter struct pollfd *t_entries = thread_data->pollfd.entries;
11396562c9acSAdrian Hunter int err = 0;
11406562c9acSAdrian Hunter size_t i;
11416562c9acSAdrian Hunter
11426562c9acSAdrian Hunter for (i = 0; i < rec->index_map_cnt; i++) {
11436562c9acSAdrian Hunter int e_pos = rec->index_map[i].evlist_pollfd_index;
11446562c9acSAdrian Hunter int t_pos = rec->index_map[i].thread_pollfd_index;
11456562c9acSAdrian Hunter
11466562c9acSAdrian Hunter if (e_entries[e_pos].fd != t_entries[t_pos].fd ||
11476562c9acSAdrian Hunter e_entries[e_pos].events != t_entries[t_pos].events) {
11486562c9acSAdrian Hunter pr_err("Thread and evlist pollfd index mismatch\n");
11496562c9acSAdrian Hunter err = -EINVAL;
11506562c9acSAdrian Hunter continue;
11516562c9acSAdrian Hunter }
11526562c9acSAdrian Hunter e_entries[e_pos].revents = t_entries[t_pos].revents;
11536562c9acSAdrian Hunter }
11546562c9acSAdrian Hunter return err;
11556562c9acSAdrian Hunter }
11566562c9acSAdrian Hunter
record__dup_non_perf_events(struct record * rec,struct evlist * evlist,struct record_thread * thread_data)11576562c9acSAdrian Hunter static int record__dup_non_perf_events(struct record *rec,
11586562c9acSAdrian Hunter struct evlist *evlist,
11596562c9acSAdrian Hunter struct record_thread *thread_data)
11606562c9acSAdrian Hunter {
11616562c9acSAdrian Hunter struct fdarray *fda = &evlist->core.pollfd;
11626562c9acSAdrian Hunter int i, ret;
11636562c9acSAdrian Hunter
11646562c9acSAdrian Hunter for (i = 0; i < fda->nr; i++) {
11656562c9acSAdrian Hunter if (!(fda->priv[i].flags & fdarray_flag__non_perf_event))
11666562c9acSAdrian Hunter continue;
11676562c9acSAdrian Hunter ret = fdarray__dup_entry_from(&thread_data->pollfd, i, fda);
11686562c9acSAdrian Hunter if (ret < 0) {
11696562c9acSAdrian Hunter pr_err("Failed to duplicate descriptor in main thread pollfd\n");
11706562c9acSAdrian Hunter return ret;
11716562c9acSAdrian Hunter }
11726562c9acSAdrian Hunter pr_debug2("thread_data[%p]: pollfd[%d] <- non_perf_event fd=%d\n",
11736562c9acSAdrian Hunter thread_data, ret, fda->entries[i].fd);
11746562c9acSAdrian Hunter ret = record__map_thread_evlist_pollfd_indexes(rec, i, ret);
11756562c9acSAdrian Hunter if (ret < 0) {
11766562c9acSAdrian Hunter pr_err("Failed to map thread and evlist pollfd indexes\n");
11776562c9acSAdrian Hunter return ret;
11786562c9acSAdrian Hunter }
11796562c9acSAdrian Hunter }
11806562c9acSAdrian Hunter return 0;
11816562c9acSAdrian Hunter }
11826562c9acSAdrian Hunter
record__alloc_thread_data(struct record * rec,struct evlist * evlist)1183415ccb58SAlexey Bayduraev static int record__alloc_thread_data(struct record *rec, struct evlist *evlist)
1184415ccb58SAlexey Bayduraev {
1185415ccb58SAlexey Bayduraev int t, ret;
1186415ccb58SAlexey Bayduraev struct record_thread *thread_data;
1187415ccb58SAlexey Bayduraev
1188415ccb58SAlexey Bayduraev rec->thread_data = zalloc(rec->nr_threads * sizeof(*(rec->thread_data)));
1189415ccb58SAlexey Bayduraev if (!rec->thread_data) {
1190415ccb58SAlexey Bayduraev pr_err("Failed to allocate thread data\n");
1191415ccb58SAlexey Bayduraev return -ENOMEM;
1192415ccb58SAlexey Bayduraev }
1193415ccb58SAlexey Bayduraev thread_data = rec->thread_data;
1194415ccb58SAlexey Bayduraev
1195415ccb58SAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++)
1196415ccb58SAlexey Bayduraev record__thread_data_init_pipes(&thread_data[t]);
1197415ccb58SAlexey Bayduraev
1198415ccb58SAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++) {
1199415ccb58SAlexey Bayduraev thread_data[t].rec = rec;
1200415ccb58SAlexey Bayduraev thread_data[t].mask = &rec->thread_masks[t];
1201415ccb58SAlexey Bayduraev ret = record__thread_data_init_maps(&thread_data[t], evlist);
1202415ccb58SAlexey Bayduraev if (ret) {
1203415ccb58SAlexey Bayduraev pr_err("Failed to initialize thread[%d] maps\n", t);
1204415ccb58SAlexey Bayduraev goto out_free;
1205415ccb58SAlexey Bayduraev }
1206415ccb58SAlexey Bayduraev ret = record__thread_data_init_pollfd(&thread_data[t], evlist);
1207415ccb58SAlexey Bayduraev if (ret) {
1208415ccb58SAlexey Bayduraev pr_err("Failed to initialize thread[%d] pollfd\n", t);
1209415ccb58SAlexey Bayduraev goto out_free;
1210415ccb58SAlexey Bayduraev }
1211415ccb58SAlexey Bayduraev if (t) {
1212415ccb58SAlexey Bayduraev thread_data[t].tid = -1;
1213415ccb58SAlexey Bayduraev ret = record__thread_data_open_pipes(&thread_data[t]);
1214415ccb58SAlexey Bayduraev if (ret) {
1215415ccb58SAlexey Bayduraev pr_err("Failed to open thread[%d] communication pipes\n", t);
1216415ccb58SAlexey Bayduraev goto out_free;
1217415ccb58SAlexey Bayduraev }
1218415ccb58SAlexey Bayduraev ret = fdarray__add(&thread_data[t].pollfd, thread_data[t].pipes.msg[0],
1219415ccb58SAlexey Bayduraev POLLIN | POLLERR | POLLHUP, fdarray_flag__nonfilterable);
1220415ccb58SAlexey Bayduraev if (ret < 0) {
1221415ccb58SAlexey Bayduraev pr_err("Failed to add descriptor to thread[%d] pollfd\n", t);
1222415ccb58SAlexey Bayduraev goto out_free;
1223415ccb58SAlexey Bayduraev }
1224415ccb58SAlexey Bayduraev thread_data[t].ctlfd_pos = ret;
1225415ccb58SAlexey Bayduraev pr_debug2("thread_data[%p]: pollfd[%d] <- ctl_fd=%d\n",
1226415ccb58SAlexey Bayduraev thread_data, thread_data[t].ctlfd_pos,
1227415ccb58SAlexey Bayduraev thread_data[t].pipes.msg[0]);
1228415ccb58SAlexey Bayduraev } else {
1229415ccb58SAlexey Bayduraev thread_data[t].tid = gettid();
12306562c9acSAdrian Hunter
12316562c9acSAdrian Hunter ret = record__dup_non_perf_events(rec, evlist, &thread_data[t]);
12326562c9acSAdrian Hunter if (ret < 0)
12336562c9acSAdrian Hunter goto out_free;
12346562c9acSAdrian Hunter
1235feff0b61SAdrian Hunter thread_data[t].ctlfd_pos = -1; /* Not used */
1236415ccb58SAlexey Bayduraev }
1237415ccb58SAlexey Bayduraev }
1238415ccb58SAlexey Bayduraev
1239415ccb58SAlexey Bayduraev return 0;
1240415ccb58SAlexey Bayduraev
1241415ccb58SAlexey Bayduraev out_free:
1242415ccb58SAlexey Bayduraev record__free_thread_data(rec);
1243415ccb58SAlexey Bayduraev
1244415ccb58SAlexey Bayduraev return ret;
1245415ccb58SAlexey Bayduraev }
1246415ccb58SAlexey Bayduraev
record__mmap_evlist(struct record * rec,struct evlist * evlist)1247cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
124863503dbaSJiri Olsa struct evlist *evlist)
1249cda57a8cSWang Nan {
125056f735ffSAlexey Bayduraev int i, ret;
1251cda57a8cSWang Nan struct record_opts *opts = &rec->opts;
1252c0a6de06SAdrian Hunter bool auxtrace_overwrite = opts->auxtrace_snapshot_mode ||
1253c0a6de06SAdrian Hunter opts->auxtrace_sample_mode;
1254cda57a8cSWang Nan char msg[512];
1255cda57a8cSWang Nan
1256f13de660SAlexey Budankov if (opts->affinity != PERF_AFFINITY_SYS)
1257f13de660SAlexey Budankov cpu__setup_cpunode_map();
1258f13de660SAlexey Budankov
12599521b5f2SJiri Olsa if (evlist__mmap_ex(evlist, opts->mmap_pages,
1260cda57a8cSWang Nan opts->auxtrace_mmap_pages,
1261c0a6de06SAdrian Hunter auxtrace_overwrite,
1262470530bbSAlexey Budankov opts->nr_cblocks, opts->affinity,
126351255a8aSAlexey Budankov opts->mmap_flush, opts->comp_level) < 0) {
1264cda57a8cSWang Nan if (errno == EPERM) {
1265cda57a8cSWang Nan pr_err("Permission error mapping pages.\n"
1266cda57a8cSWang Nan "Consider increasing "
1267cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n"
1268cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n"
1269cda57a8cSWang Nan "(current value: %u,%u)\n",
1270cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages);
1271cda57a8cSWang Nan return -errno;
1272cda57a8cSWang Nan } else {
1273cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno,
1274c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg)));
1275cda57a8cSWang Nan if (errno)
1276cda57a8cSWang Nan return -errno;
1277cda57a8cSWang Nan else
1278cda57a8cSWang Nan return -EINVAL;
1279cda57a8cSWang Nan }
1280cda57a8cSWang Nan }
1281415ccb58SAlexey Bayduraev
1282415ccb58SAlexey Bayduraev if (evlist__initialize_ctlfd(evlist, opts->ctl_fd, opts->ctl_fd_ack))
1283415ccb58SAlexey Bayduraev return -1;
1284415ccb58SAlexey Bayduraev
1285415ccb58SAlexey Bayduraev ret = record__alloc_thread_data(rec, evlist);
1286415ccb58SAlexey Bayduraev if (ret)
1287415ccb58SAlexey Bayduraev return ret;
1288415ccb58SAlexey Bayduraev
128956f735ffSAlexey Bayduraev if (record__threads_enabled(rec)) {
129056f735ffSAlexey Bayduraev ret = perf_data__create_dir(&rec->data, evlist->core.nr_mmaps);
129165e7c963SAlexey Bayduraev if (ret) {
129265e7c963SAlexey Bayduraev pr_err("Failed to create data directory: %s\n", strerror(-ret));
129356f735ffSAlexey Bayduraev return ret;
129465e7c963SAlexey Bayduraev }
129556f735ffSAlexey Bayduraev for (i = 0; i < evlist->core.nr_mmaps; i++) {
129656f735ffSAlexey Bayduraev if (evlist->mmap)
129756f735ffSAlexey Bayduraev evlist->mmap[i].file = &rec->data.dir.files[i];
129856f735ffSAlexey Bayduraev if (evlist->overwrite_mmap)
129956f735ffSAlexey Bayduraev evlist->overwrite_mmap[i].file = &rec->data.dir.files[i];
130056f735ffSAlexey Bayduraev }
130156f735ffSAlexey Bayduraev }
130256f735ffSAlexey Bayduraev
1303cda57a8cSWang Nan return 0;
1304cda57a8cSWang Nan }
1305cda57a8cSWang Nan
record__mmap(struct record * rec)1306cda57a8cSWang Nan static int record__mmap(struct record *rec)
1307cda57a8cSWang Nan {
1308cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist);
1309cda57a8cSWang Nan }
1310cda57a8cSWang Nan
record__open(struct record * rec)13118c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
1312dd7927f4SArnaldo Carvalho de Melo {
1313d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ];
131432dcd021SJiri Olsa struct evsel *pos;
131563503dbaSJiri Olsa struct evlist *evlist = rec->evlist;
1316d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session;
1317b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts;
13188d3eca20SDavid Ahern int rc = 0;
1319dd7927f4SArnaldo Carvalho de Melo
1320e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) {
13213da297a6SIngo Molnar try_again:
1322af663bd0SJiri Olsa if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
1323ae430892SArnaldo Carvalho de Melo if (evsel__fallback(pos, errno, msg, sizeof(msg))) {
1324bb963e16SNamhyung Kim if (verbose > 0)
1325c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg);
13263da297a6SIngo Molnar goto try_again;
13273da297a6SIngo Molnar }
1328cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) &&
1329fba7c866SJiri Olsa pos->core.leader != &pos->core &&
1330cf99ad14SAndi Kleen pos->weak_group) {
133164b4778bSArnaldo Carvalho de Melo pos = evlist__reset_weak_group(evlist, pos, true);
1332cf99ad14SAndi Kleen goto try_again;
1333cf99ad14SAndi Kleen }
133456e52e85SArnaldo Carvalho de Melo rc = -errno;
13352bb72dbbSArnaldo Carvalho de Melo evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg));
133656e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg);
13378d3eca20SDavid Ahern goto out;
13387c6a1c65SPeter Zijlstra }
1339bfd8f72cSAndi Kleen
1340bfd8f72cSAndi Kleen pos->supported = true;
13417c6a1c65SPeter Zijlstra }
13427c6a1c65SPeter Zijlstra
134378e1bc25SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) {
1344c8b567c8SArnaldo Carvalho de Melo pr_warning(
1345c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1346c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
1347c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1348c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1349c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1350c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1351c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1352c8b567c8SArnaldo Carvalho de Melo }
1353c8b567c8SArnaldo Carvalho de Melo
135424bf91a7SArnaldo Carvalho de Melo if (evlist__apply_filters(evlist, &pos)) {
135562d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
13564310551bSNamhyung Kim pos->filter ?: "BPF", evsel__name(pos), errno,
1357c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg)));
13588d3eca20SDavid Ahern rc = -1;
13598d3eca20SDavid Ahern goto out;
13600a102479SFrederic Weisbecker }
13610a102479SFrederic Weisbecker
1362cda57a8cSWang Nan rc = record__mmap(rec);
1363cda57a8cSWang Nan if (rc)
13648d3eca20SDavid Ahern goto out;
13650a27d7f9SArnaldo Carvalho de Melo
1366a91e5431SArnaldo Carvalho de Melo session->evlist = evlist;
13677b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session);
13688d3eca20SDavid Ahern out:
13698d3eca20SDavid Ahern return rc;
1370a91e5431SArnaldo Carvalho de Melo }
1371a91e5431SArnaldo Carvalho de Melo
set_timestamp_boundary(struct record * rec,u64 sample_time)137266286ed3SAdrian Hunter static void set_timestamp_boundary(struct record *rec, u64 sample_time)
137366286ed3SAdrian Hunter {
137466286ed3SAdrian Hunter if (rec->evlist->first_sample_time == 0)
137566286ed3SAdrian Hunter rec->evlist->first_sample_time = sample_time;
137666286ed3SAdrian Hunter
137766286ed3SAdrian Hunter if (sample_time)
137866286ed3SAdrian Hunter rec->evlist->last_sample_time = sample_time;
137966286ed3SAdrian Hunter }
138066286ed3SAdrian Hunter
process_sample_event(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample,struct evsel * evsel,struct machine * machine)1381e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
1382e3d59112SNamhyung Kim union perf_event *event,
1383e3d59112SNamhyung Kim struct perf_sample *sample,
138432dcd021SJiri Olsa struct evsel *evsel,
1385e3d59112SNamhyung Kim struct machine *machine)
1386e3d59112SNamhyung Kim {
1387e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool);
1388e3d59112SNamhyung Kim
138966286ed3SAdrian Hunter set_timestamp_boundary(rec, sample->time);
139068588bafSJin Yao
139168588bafSJin Yao if (rec->buildid_all)
139268588bafSJin Yao return 0;
139368588bafSJin Yao
139468588bafSJin Yao rec->samples++;
1395e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
1396e3d59112SNamhyung Kim }
1397e3d59112SNamhyung Kim
process_buildids(struct record * rec)13988c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
13996122e4e4SArnaldo Carvalho de Melo {
1400f5fc1412SJiri Olsa struct perf_session *session = rec->session;
14016122e4e4SArnaldo Carvalho de Melo
140245112e89SJiri Olsa if (perf_data__size(&rec->data) == 0)
14039f591fd7SArnaldo Carvalho de Melo return 0;
14049f591fd7SArnaldo Carvalho de Melo
140500dc8657SNamhyung Kim /*
140600dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the
140700dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case
140800dc8657SNamhyung Kim * we prefer the vmlinux path like
140900dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux
141000dc8657SNamhyung Kim *
141100dc8657SNamhyung Kim * rather than build-id path (in debug directory).
141200dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
141300dc8657SNamhyung Kim */
141400dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true;
141500dc8657SNamhyung Kim
14166156681bSNamhyung Kim /*
14176156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits,
141868588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled,
141968588bafSJin Yao * it still needs to walk on all samples to get the timestamps of
142068588bafSJin Yao * first/last samples.
14216156681bSNamhyung Kim */
142268588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary)
14236156681bSNamhyung Kim rec->tool.sample = NULL;
14246156681bSNamhyung Kim
1425b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session);
14266122e4e4SArnaldo Carvalho de Melo }
14276122e4e4SArnaldo Carvalho de Melo
perf_event__synthesize_guest_os(struct machine * machine,void * data)14288115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
1429a1645ce1SZhang, Yanmin {
1430a1645ce1SZhang, Yanmin int err;
143145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data;
1432a1645ce1SZhang, Yanmin /*
1433a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report,
1434a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger
1435a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded
1436a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This
1437a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is
1438a1645ce1SZhang, Yanmin *in module instead of in guest kernel.
1439a1645ce1SZhang, Yanmin */
144045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event,
1441743eb868SArnaldo Carvalho de Melo machine);
1442a1645ce1SZhang, Yanmin if (err < 0)
1443a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference"
144423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid);
1445a1645ce1SZhang, Yanmin
1446a1645ce1SZhang, Yanmin /*
1447a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms
1448a1645ce1SZhang, Yanmin * have no _text sometimes.
1449a1645ce1SZhang, Yanmin */
145045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
14510ae617beSAdrian Hunter machine);
1452a1645ce1SZhang, Yanmin if (err < 0)
1453a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference"
145423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid);
1455a1645ce1SZhang, Yanmin }
1456a1645ce1SZhang, Yanmin
145798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
145898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header),
145998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND,
146098402807SFrederic Weisbecker };
146198402807SFrederic Weisbecker
14623812d298SAdrian Hunter static struct perf_event_header finished_init_event = {
14633812d298SAdrian Hunter .size = sizeof(struct perf_event_header),
14643812d298SAdrian Hunter .type = PERF_RECORD_FINISHED_INIT,
14653812d298SAdrian Hunter };
14663812d298SAdrian Hunter
record__adjust_affinity(struct record * rec,struct mmap * map)1467a5830532SJiri Olsa static void record__adjust_affinity(struct record *rec, struct mmap *map)
1468f13de660SAlexey Budankov {
1469f13de660SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS &&
1470396b626bSAlexey Bayduraev !bitmap_equal(thread->mask->affinity.bits, map->affinity_mask.bits,
1471396b626bSAlexey Bayduraev thread->mask->affinity.nbits)) {
1472396b626bSAlexey Bayduraev bitmap_zero(thread->mask->affinity.bits, thread->mask->affinity.nbits);
1473396b626bSAlexey Bayduraev bitmap_or(thread->mask->affinity.bits, thread->mask->affinity.bits,
1474396b626bSAlexey Bayduraev map->affinity_mask.bits, thread->mask->affinity.nbits);
1475396b626bSAlexey Bayduraev sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&thread->mask->affinity),
1476396b626bSAlexey Bayduraev (cpu_set_t *)thread->mask->affinity.bits);
1477396b626bSAlexey Bayduraev if (verbose == 2) {
1478396b626bSAlexey Bayduraev pr_debug("threads[%d]: running on cpu%d: ", thread->tid, sched_getcpu());
1479396b626bSAlexey Bayduraev mmap_cpu_mask__scnprintf(&thread->mask->affinity, "affinity");
1480396b626bSAlexey Bayduraev }
1481f13de660SAlexey Budankov }
1482f13de660SAlexey Budankov }
1483f13de660SAlexey Budankov
process_comp_header(void * record,size_t increment)14845d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment)
14855d7f4116SAlexey Budankov {
148672932371SJiri Olsa struct perf_record_compressed *event = record;
14875d7f4116SAlexey Budankov size_t size = sizeof(*event);
14885d7f4116SAlexey Budankov
14895d7f4116SAlexey Budankov if (increment) {
14905d7f4116SAlexey Budankov event->header.size += increment;
14915d7f4116SAlexey Budankov return increment;
14925d7f4116SAlexey Budankov }
14935d7f4116SAlexey Budankov
14945d7f4116SAlexey Budankov event->header.type = PERF_RECORD_COMPRESSED;
14955d7f4116SAlexey Budankov event->header.size = size;
14965d7f4116SAlexey Budankov
14975d7f4116SAlexey Budankov return size;
14985d7f4116SAlexey Budankov }
14995d7f4116SAlexey Budankov
zstd_compress(struct perf_session * session,struct mmap * map,void * dst,size_t dst_size,void * src,size_t src_size)150075f5f1fcSAlexey Bayduraev static size_t zstd_compress(struct perf_session *session, struct mmap *map,
150175f5f1fcSAlexey Bayduraev void *dst, size_t dst_size, void *src, size_t src_size)
15025d7f4116SAlexey Budankov {
15035d7f4116SAlexey Budankov size_t compressed;
150472932371SJiri Olsa size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1;
150575f5f1fcSAlexey Bayduraev struct zstd_data *zstd_data = &session->zstd_data;
15065d7f4116SAlexey Budankov
150775f5f1fcSAlexey Bayduraev if (map && map->file)
150875f5f1fcSAlexey Bayduraev zstd_data = &map->zstd_data;
150975f5f1fcSAlexey Bayduraev
151075f5f1fcSAlexey Bayduraev compressed = zstd_compress_stream_to_records(zstd_data, dst, dst_size, src, src_size,
15115d7f4116SAlexey Budankov max_record_size, process_comp_header);
15125d7f4116SAlexey Budankov
1513610fbc01SAlexey Bayduraev if (map && map->file) {
1514610fbc01SAlexey Bayduraev thread->bytes_transferred += src_size;
1515610fbc01SAlexey Bayduraev thread->bytes_compressed += compressed;
1516610fbc01SAlexey Bayduraev } else {
15175d7f4116SAlexey Budankov session->bytes_transferred += src_size;
15185d7f4116SAlexey Budankov session->bytes_compressed += compressed;
1519610fbc01SAlexey Bayduraev }
15205d7f4116SAlexey Budankov
15215d7f4116SAlexey Budankov return compressed;
15225d7f4116SAlexey Budankov }
15235d7f4116SAlexey Budankov
record__mmap_read_evlist(struct record * rec,struct evlist * evlist,bool overwrite,bool synch)152463503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
1525470530bbSAlexey Budankov bool overwrite, bool synch)
152698402807SFrederic Weisbecker {
1527dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written;
15280e2e63ddSPeter Zijlstra int i;
15298d3eca20SDavid Ahern int rc = 0;
1530396b626bSAlexey Bayduraev int nr_mmaps;
1531396b626bSAlexey Bayduraev struct mmap **maps;
1532d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd;
1533ef781128SAlexey Budankov off_t off = 0;
153498402807SFrederic Weisbecker
1535cb21686bSWang Nan if (!evlist)
1536cb21686bSWang Nan return 0;
1537ef149c25SAdrian Hunter
1538396b626bSAlexey Bayduraev nr_mmaps = thread->nr_mmaps;
1539396b626bSAlexey Bayduraev maps = overwrite ? thread->overwrite_maps : thread->maps;
1540396b626bSAlexey Bayduraev
1541a4ea0ec4SWang Nan if (!maps)
1542a4ea0ec4SWang Nan return 0;
1543cb21686bSWang Nan
15440b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
154554cc54deSWang Nan return 0;
154654cc54deSWang Nan
1547d3d1af6fSAlexey Budankov if (record__aio_enabled(rec))
1548d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd);
1549d3d1af6fSAlexey Budankov
1550396b626bSAlexey Bayduraev for (i = 0; i < nr_mmaps; i++) {
1551470530bbSAlexey Budankov u64 flush = 0;
1552396b626bSAlexey Bayduraev struct mmap *map = maps[i];
1553a4ea0ec4SWang Nan
1554547740f7SJiri Olsa if (map->core.base) {
1555f13de660SAlexey Budankov record__adjust_affinity(rec, map);
1556470530bbSAlexey Budankov if (synch) {
155765aa2e6bSJiri Olsa flush = map->core.flush;
155865aa2e6bSJiri Olsa map->core.flush = 1;
1559470530bbSAlexey Budankov }
1560d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) {
1561ef781128SAlexey Budankov if (perf_mmap__push(map, rec, record__pushfn) < 0) {
1562470530bbSAlexey Budankov if (synch)
156365aa2e6bSJiri Olsa map->core.flush = flush;
15648d3eca20SDavid Ahern rc = -1;
15658d3eca20SDavid Ahern goto out;
15668d3eca20SDavid Ahern }
1567d3d1af6fSAlexey Budankov } else {
1568ef781128SAlexey Budankov if (record__aio_push(rec, map, &off) < 0) {
1569d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off);
1570470530bbSAlexey Budankov if (synch)
157165aa2e6bSJiri Olsa map->core.flush = flush;
1572d3d1af6fSAlexey Budankov rc = -1;
1573d3d1af6fSAlexey Budankov goto out;
1574d3d1af6fSAlexey Budankov }
1575d3d1af6fSAlexey Budankov }
1576470530bbSAlexey Budankov if (synch)
157765aa2e6bSJiri Olsa map->core.flush = flush;
15788d3eca20SDavid Ahern }
1579ef149c25SAdrian Hunter
1580e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
1581c0a6de06SAdrian Hunter !rec->opts.auxtrace_sample_mode &&
1582e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) {
1583ef149c25SAdrian Hunter rc = -1;
1584ef149c25SAdrian Hunter goto out;
1585ef149c25SAdrian Hunter }
158698402807SFrederic Weisbecker }
158798402807SFrederic Weisbecker
1588d3d1af6fSAlexey Budankov if (record__aio_enabled(rec))
1589d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off);
1590d3d1af6fSAlexey Budankov
1591dcabb507SJiri Olsa /*
1592dcabb507SJiri Olsa * Mark the round finished in case we wrote
1593dcabb507SJiri Olsa * at least one event.
159456f735ffSAlexey Bayduraev *
159556f735ffSAlexey Bayduraev * No need for round events in directory mode,
159656f735ffSAlexey Bayduraev * because per-cpu maps and files have data
159756f735ffSAlexey Bayduraev * sorted by kernel.
1598dcabb507SJiri Olsa */
159956f735ffSAlexey Bayduraev if (!record__threads_enabled(rec) && bytes_written != rec->bytes_written)
1600ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
16018d3eca20SDavid Ahern
16020b72d69aSWang Nan if (overwrite)
1603ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
16048d3eca20SDavid Ahern out:
16058d3eca20SDavid Ahern return rc;
160698402807SFrederic Weisbecker }
160798402807SFrederic Weisbecker
record__mmap_read_all(struct record * rec,bool synch)1608470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
1609cb21686bSWang Nan {
1610cb21686bSWang Nan int err;
1611cb21686bSWang Nan
1612470530bbSAlexey Budankov err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
1613cb21686bSWang Nan if (err)
1614cb21686bSWang Nan return err;
1615cb21686bSWang Nan
1616470530bbSAlexey Budankov return record__mmap_read_evlist(rec, rec->evlist, true, synch);
1617cb21686bSWang Nan }
1618cb21686bSWang Nan
record__thread_munmap_filtered(struct fdarray * fda,int fd,void * arg __maybe_unused)1619396b626bSAlexey Bayduraev static void record__thread_munmap_filtered(struct fdarray *fda, int fd,
1620396b626bSAlexey Bayduraev void *arg __maybe_unused)
1621396b626bSAlexey Bayduraev {
1622396b626bSAlexey Bayduraev struct perf_mmap *map = fda->priv[fd].ptr;
1623396b626bSAlexey Bayduraev
1624396b626bSAlexey Bayduraev if (map)
1625396b626bSAlexey Bayduraev perf_mmap__put(map);
1626396b626bSAlexey Bayduraev }
1627396b626bSAlexey Bayduraev
record__thread(void * arg)16283217e9feSAlexey Bayduraev static void *record__thread(void *arg)
16293217e9feSAlexey Bayduraev {
16303217e9feSAlexey Bayduraev enum thread_msg msg = THREAD_MSG__READY;
16313217e9feSAlexey Bayduraev bool terminate = false;
16323217e9feSAlexey Bayduraev struct fdarray *pollfd;
16333217e9feSAlexey Bayduraev int err, ctlfd_pos;
16343217e9feSAlexey Bayduraev
16353217e9feSAlexey Bayduraev thread = arg;
16363217e9feSAlexey Bayduraev thread->tid = gettid();
16373217e9feSAlexey Bayduraev
16383217e9feSAlexey Bayduraev err = write(thread->pipes.ack[1], &msg, sizeof(msg));
16393217e9feSAlexey Bayduraev if (err == -1)
16403217e9feSAlexey Bayduraev pr_warning("threads[%d]: failed to notify on start: %s\n",
16413217e9feSAlexey Bayduraev thread->tid, strerror(errno));
16423217e9feSAlexey Bayduraev
16433217e9feSAlexey Bayduraev pr_debug("threads[%d]: started on cpu%d\n", thread->tid, sched_getcpu());
16443217e9feSAlexey Bayduraev
16453217e9feSAlexey Bayduraev pollfd = &thread->pollfd;
16463217e9feSAlexey Bayduraev ctlfd_pos = thread->ctlfd_pos;
16473217e9feSAlexey Bayduraev
16483217e9feSAlexey Bayduraev for (;;) {
16493217e9feSAlexey Bayduraev unsigned long long hits = thread->samples;
16503217e9feSAlexey Bayduraev
16513217e9feSAlexey Bayduraev if (record__mmap_read_all(thread->rec, false) < 0 || terminate)
16523217e9feSAlexey Bayduraev break;
16533217e9feSAlexey Bayduraev
16543217e9feSAlexey Bayduraev if (hits == thread->samples) {
16553217e9feSAlexey Bayduraev
16563217e9feSAlexey Bayduraev err = fdarray__poll(pollfd, -1);
16573217e9feSAlexey Bayduraev /*
16583217e9feSAlexey Bayduraev * Propagate error, only if there's any. Ignore positive
16593217e9feSAlexey Bayduraev * number of returned events and interrupt error.
16603217e9feSAlexey Bayduraev */
16613217e9feSAlexey Bayduraev if (err > 0 || (err < 0 && errno == EINTR))
16623217e9feSAlexey Bayduraev err = 0;
16633217e9feSAlexey Bayduraev thread->waking++;
16643217e9feSAlexey Bayduraev
16653217e9feSAlexey Bayduraev if (fdarray__filter(pollfd, POLLERR | POLLHUP,
16663217e9feSAlexey Bayduraev record__thread_munmap_filtered, NULL) == 0)
16673217e9feSAlexey Bayduraev break;
16683217e9feSAlexey Bayduraev }
16693217e9feSAlexey Bayduraev
16703217e9feSAlexey Bayduraev if (pollfd->entries[ctlfd_pos].revents & POLLHUP) {
16713217e9feSAlexey Bayduraev terminate = true;
16723217e9feSAlexey Bayduraev close(thread->pipes.msg[0]);
16733217e9feSAlexey Bayduraev thread->pipes.msg[0] = -1;
16743217e9feSAlexey Bayduraev pollfd->entries[ctlfd_pos].fd = -1;
16753217e9feSAlexey Bayduraev pollfd->entries[ctlfd_pos].events = 0;
16763217e9feSAlexey Bayduraev }
16773217e9feSAlexey Bayduraev
16783217e9feSAlexey Bayduraev pollfd->entries[ctlfd_pos].revents = 0;
16793217e9feSAlexey Bayduraev }
16803217e9feSAlexey Bayduraev record__mmap_read_all(thread->rec, true);
16813217e9feSAlexey Bayduraev
16823217e9feSAlexey Bayduraev err = write(thread->pipes.ack[1], &msg, sizeof(msg));
16833217e9feSAlexey Bayduraev if (err == -1)
16843217e9feSAlexey Bayduraev pr_warning("threads[%d]: failed to notify on termination: %s\n",
16853217e9feSAlexey Bayduraev thread->tid, strerror(errno));
16863217e9feSAlexey Bayduraev
16873217e9feSAlexey Bayduraev return NULL;
16883217e9feSAlexey Bayduraev }
16893217e9feSAlexey Bayduraev
record__init_features(struct record * rec)16908c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
169157706abcSDavid Ahern {
169257706abcSDavid Ahern struct perf_session *session = rec->session;
169357706abcSDavid Ahern int feat;
169457706abcSDavid Ahern
169557706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
169657706abcSDavid Ahern perf_header__set_feat(&session->header, feat);
169757706abcSDavid Ahern
169857706abcSDavid Ahern if (rec->no_buildid)
169957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
170057706abcSDavid Ahern
1701378ef0f5SIan Rogers #ifdef HAVE_LIBTRACEEVENT
1702ce9036a6SJiri Olsa if (!have_tracepoints(&rec->evlist->core.entries))
170357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
1704378ef0f5SIan Rogers #endif
170557706abcSDavid Ahern
170657706abcSDavid Ahern if (!rec->opts.branch_stack)
170757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1708ef149c25SAdrian Hunter
1709ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace)
1710ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1711ffa517adSJiri Olsa
1712cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
1713cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID);
1714cf790516SAlexey Budankov
1715d1e325cfSJiri Olsa if (!rec->opts.use_clockid)
1716d1e325cfSJiri Olsa perf_header__clear_feat(&session->header, HEADER_CLOCK_DATA);
1717d1e325cfSJiri Olsa
171856f735ffSAlexey Bayduraev if (!record__threads_enabled(rec))
1719258031c0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
172056f735ffSAlexey Bayduraev
172142e1fd80SAlexey Budankov if (!record__comp_enabled(rec))
172242e1fd80SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
1723258031c0SJiri Olsa
1724ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT);
172557706abcSDavid Ahern }
172657706abcSDavid Ahern
1727e1ab48baSWang Nan static void
record__finish_output(struct record * rec)1728e1ab48baSWang Nan record__finish_output(struct record *rec)
1729e1ab48baSWang Nan {
173056f735ffSAlexey Bayduraev int i;
17318ceb41d7SJiri Olsa struct perf_data *data = &rec->data;
17328ceb41d7SJiri Olsa int fd = perf_data__fd(data);
1733e1ab48baSWang Nan
17348ceb41d7SJiri Olsa if (data->is_pipe)
1735e1ab48baSWang Nan return;
1736e1ab48baSWang Nan
1737e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written;
173845112e89SJiri Olsa data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
173956f735ffSAlexey Bayduraev if (record__threads_enabled(rec)) {
174056f735ffSAlexey Bayduraev for (i = 0; i < data->dir.nr; i++)
174156f735ffSAlexey Bayduraev data->dir.files[i].size = lseek(data->dir.files[i].fd, 0, SEEK_CUR);
174256f735ffSAlexey Bayduraev }
1743e1ab48baSWang Nan
1744e1ab48baSWang Nan if (!rec->no_buildid) {
1745e1ab48baSWang Nan process_buildids(rec);
1746e1ab48baSWang Nan
1747e1ab48baSWang Nan if (rec->buildid_all)
1748e1ab48baSWang Nan dsos__hit_all(rec->session);
1749e1ab48baSWang Nan }
1750e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true);
1751e1ab48baSWang Nan
1752e1ab48baSWang Nan return;
1753e1ab48baSWang Nan }
1754e1ab48baSWang Nan
record__synthesize_workload(struct record * rec,bool tail)17554ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
1756be7b0c9eSWang Nan {
17579d6aae72SArnaldo Carvalho de Melo int err;
17589749b90eSJiri Olsa struct perf_thread_map *thread_map;
175941b740b6SNamhyung Kim bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP;
1760be7b0c9eSWang Nan
17614ea648aeSWang Nan if (rec->opts.tail_synthesize != tail)
17624ea648aeSWang Nan return 0;
17634ea648aeSWang Nan
17649d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
17659d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL)
17669d6aae72SArnaldo Carvalho de Melo return -1;
17679d6aae72SArnaldo Carvalho de Melo
17689d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
1769be7b0c9eSWang Nan process_synthesized_event,
1770be7b0c9eSWang Nan &rec->session->machines.host,
177141b740b6SNamhyung Kim needs_mmap,
17723fcb10e4SMark Drayton rec->opts.sample_address);
17737836e52eSJiri Olsa perf_thread_map__put(thread_map);
17749d6aae72SArnaldo Carvalho de Melo return err;
1775be7b0c9eSWang Nan }
1776be7b0c9eSWang Nan
write_finished_init(struct record * rec,bool tail)17773812d298SAdrian Hunter static int write_finished_init(struct record *rec, bool tail)
17783812d298SAdrian Hunter {
17793812d298SAdrian Hunter if (rec->opts.tail_synthesize != tail)
17803812d298SAdrian Hunter return 0;
17813812d298SAdrian Hunter
17823812d298SAdrian Hunter return record__write(rec, NULL, &finished_init_event, sizeof(finished_init_event));
17833812d298SAdrian Hunter }
17843812d298SAdrian Hunter
17854ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
17863c1cb7e3SWang Nan
1787ecfd7a9cSWang Nan static int
record__switch_output(struct record * rec,bool at_exit)1788ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
1789ecfd7a9cSWang Nan {
17908ceb41d7SJiri Olsa struct perf_data *data = &rec->data;
1791d361a8ecSYang Jihong char *new_filename = NULL;
1792ecfd7a9cSWang Nan int fd, err;
1793ecfd7a9cSWang Nan
1794ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/
1795ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp";
1796ecfd7a9cSWang Nan
1797d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec);
1798d3d1af6fSAlexey Budankov
17993812d298SAdrian Hunter write_finished_init(rec, true);
18003812d298SAdrian Hunter
18014ea648aeSWang Nan record__synthesize(rec, true);
18024ea648aeSWang Nan if (target__none(&rec->opts.target))
18034ea648aeSWang Nan record__synthesize_workload(rec, true);
18044ea648aeSWang Nan
1805ecfd7a9cSWang Nan rec->samples = 0;
1806ecfd7a9cSWang Nan record__finish_output(rec);
1807ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp));
1808ecfd7a9cSWang Nan if (err) {
1809ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n");
1810ecfd7a9cSWang Nan return -EINVAL;
1811ecfd7a9cSWang Nan }
1812ecfd7a9cSWang Nan
18138ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp,
1814ecfd7a9cSWang Nan rec->session->header.data_offset,
181503724b2eSAndi Kleen at_exit, &new_filename);
1816ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) {
1817ecfd7a9cSWang Nan rec->bytes_written = 0;
1818ecfd7a9cSWang Nan rec->session->header.data_size = 0;
1819ecfd7a9cSWang Nan }
1820ecfd7a9cSWang Nan
1821ecfd7a9cSWang Nan if (!quiet)
1822ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
18232d4f2799SJiri Olsa data->path, timestamp);
18243c1cb7e3SWang Nan
182503724b2eSAndi Kleen if (rec->switch_output.num_files) {
182603724b2eSAndi Kleen int n = rec->switch_output.cur_file + 1;
182703724b2eSAndi Kleen
182803724b2eSAndi Kleen if (n >= rec->switch_output.num_files)
182903724b2eSAndi Kleen n = 0;
183003724b2eSAndi Kleen rec->switch_output.cur_file = n;
183103724b2eSAndi Kleen if (rec->switch_output.filenames[n]) {
183203724b2eSAndi Kleen remove(rec->switch_output.filenames[n]);
1833d8f9da24SArnaldo Carvalho de Melo zfree(&rec->switch_output.filenames[n]);
183403724b2eSAndi Kleen }
183503724b2eSAndi Kleen rec->switch_output.filenames[n] = new_filename;
183603724b2eSAndi Kleen } else {
183703724b2eSAndi Kleen free(new_filename);
183803724b2eSAndi Kleen }
183903724b2eSAndi Kleen
18403c1cb7e3SWang Nan /* Output tracking events */
1841be7b0c9eSWang Nan if (!at_exit) {
18424ea648aeSWang Nan record__synthesize(rec, false);
18433c1cb7e3SWang Nan
1844be7b0c9eSWang Nan /*
1845be7b0c9eSWang Nan * In 'perf record --switch-output' without -a,
1846be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't
1847be7b0c9eSWang Nan * generate tracking events because there's no thread_map
1848be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't
1849be7b0c9eSWang Nan * contain map and comm information.
1850be7b0c9eSWang Nan * Create a fake thread_map and directly call
1851be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events.
1852be7b0c9eSWang Nan */
1853be7b0c9eSWang Nan if (target__none(&rec->opts.target))
18544ea648aeSWang Nan record__synthesize_workload(rec, false);
18553812d298SAdrian Hunter write_finished_init(rec, false);
1856be7b0c9eSWang Nan }
1857ecfd7a9cSWang Nan return fd;
1858ecfd7a9cSWang Nan }
1859ecfd7a9cSWang Nan
__record__save_lost_samples(struct record * rec,struct evsel * evsel,struct perf_record_lost_samples * lost,int cpu_idx,int thread_idx,u64 lost_count,u16 misc_flag)186027c6f245SNamhyung Kim static void __record__save_lost_samples(struct record *rec, struct evsel *evsel,
1861e3a23261SNamhyung Kim struct perf_record_lost_samples *lost,
186227c6f245SNamhyung Kim int cpu_idx, int thread_idx, u64 lost_count,
186327c6f245SNamhyung Kim u16 misc_flag)
1864e3a23261SNamhyung Kim {
1865e3a23261SNamhyung Kim struct perf_sample_id *sid;
1866e3a23261SNamhyung Kim struct perf_sample sample = {};
1867e3a23261SNamhyung Kim int id_hdr_size;
1868e3a23261SNamhyung Kim
186927c6f245SNamhyung Kim lost->lost = lost_count;
1870e3a23261SNamhyung Kim if (evsel->core.ids) {
1871e3a23261SNamhyung Kim sid = xyarray__entry(evsel->core.sample_id, cpu_idx, thread_idx);
1872e3a23261SNamhyung Kim sample.id = sid->id;
1873e3a23261SNamhyung Kim }
1874e3a23261SNamhyung Kim
1875e3a23261SNamhyung Kim id_hdr_size = perf_event__synthesize_id_sample((void *)(lost + 1),
1876e3a23261SNamhyung Kim evsel->core.attr.sample_type, &sample);
1877e3a23261SNamhyung Kim lost->header.size = sizeof(*lost) + id_hdr_size;
187827c6f245SNamhyung Kim lost->header.misc = misc_flag;
1879e3a23261SNamhyung Kim record__write(rec, NULL, lost, lost->header.size);
1880e3a23261SNamhyung Kim }
1881e3a23261SNamhyung Kim
record__read_lost_samples(struct record * rec)1882e3a23261SNamhyung Kim static void record__read_lost_samples(struct record *rec)
1883e3a23261SNamhyung Kim {
1884e3a23261SNamhyung Kim struct perf_session *session = rec->session;
1885e3a23261SNamhyung Kim struct perf_record_lost_samples *lost;
1886e3a23261SNamhyung Kim struct evsel *evsel;
1887e3a23261SNamhyung Kim
1888d031a00aSNamhyung Kim /* there was an error during record__open */
1889d031a00aSNamhyung Kim if (session->evlist == NULL)
1890d031a00aSNamhyung Kim return;
1891d031a00aSNamhyung Kim
1892e3a23261SNamhyung Kim lost = zalloc(PERF_SAMPLE_MAX_SIZE);
1893e3a23261SNamhyung Kim if (lost == NULL) {
1894e3a23261SNamhyung Kim pr_debug("Memory allocation failed\n");
1895e3a23261SNamhyung Kim return;
1896e3a23261SNamhyung Kim }
1897e3a23261SNamhyung Kim
1898e3a23261SNamhyung Kim lost->header.type = PERF_RECORD_LOST_SAMPLES;
1899e3a23261SNamhyung Kim
1900e3a23261SNamhyung Kim evlist__for_each_entry(session->evlist, evsel) {
1901e3a23261SNamhyung Kim struct xyarray *xy = evsel->core.sample_id;
190227c6f245SNamhyung Kim u64 lost_count;
1903e3a23261SNamhyung Kim
1904d031a00aSNamhyung Kim if (xy == NULL || evsel->core.fd == NULL)
1905d031a00aSNamhyung Kim continue;
1906e3a23261SNamhyung Kim if (xyarray__max_x(evsel->core.fd) != xyarray__max_x(xy) ||
1907e3a23261SNamhyung Kim xyarray__max_y(evsel->core.fd) != xyarray__max_y(xy)) {
1908e3a23261SNamhyung Kim pr_debug("Unmatched FD vs. sample ID: skip reading LOST count\n");
1909e3a23261SNamhyung Kim continue;
1910e3a23261SNamhyung Kim }
1911e3a23261SNamhyung Kim
1912e3a23261SNamhyung Kim for (int x = 0; x < xyarray__max_x(xy); x++) {
1913e3a23261SNamhyung Kim for (int y = 0; y < xyarray__max_y(xy); y++) {
191427c6f245SNamhyung Kim struct perf_counts_values count;
1915e3a23261SNamhyung Kim
191627c6f245SNamhyung Kim if (perf_evsel__read(&evsel->core, x, y, &count) < 0) {
191727c6f245SNamhyung Kim pr_debug("read LOST count failed\n");
191827c6f245SNamhyung Kim goto out;
191927c6f245SNamhyung Kim }
192027c6f245SNamhyung Kim
192127c6f245SNamhyung Kim if (count.lost) {
192227c6f245SNamhyung Kim __record__save_lost_samples(rec, evsel, lost,
192327c6f245SNamhyung Kim x, y, count.lost, 0);
192427c6f245SNamhyung Kim }
192527c6f245SNamhyung Kim }
192627c6f245SNamhyung Kim }
192727c6f245SNamhyung Kim
192827c6f245SNamhyung Kim lost_count = perf_bpf_filter__lost_count(evsel);
192927c6f245SNamhyung Kim if (lost_count)
193027c6f245SNamhyung Kim __record__save_lost_samples(rec, evsel, lost, 0, 0, lost_count,
193127c6f245SNamhyung Kim PERF_RECORD_MISC_LOST_SAMPLES_BPF);
193227c6f245SNamhyung Kim }
193327c6f245SNamhyung Kim out:
193427c6f245SNamhyung Kim free(lost);
1935e3a23261SNamhyung Kim }
1936e3a23261SNamhyung Kim
19378ed28c2bSIan Rogers static volatile sig_atomic_t workload_exec_errno;
1938f33cbe72SArnaldo Carvalho de Melo
1939f33cbe72SArnaldo Carvalho de Melo /*
19407b392ef0SArnaldo Carvalho de Melo * evlist__prepare_workload will send a SIGUSR1
1941f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its
1942f33cbe72SArnaldo Carvalho de Melo * want_signal to true.
1943f33cbe72SArnaldo Carvalho de Melo */
workload_exec_failed_signal(int signo __maybe_unused,siginfo_t * info,void * ucontext __maybe_unused)194445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
194545604710SNamhyung Kim siginfo_t *info,
1946f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused)
1947f33cbe72SArnaldo Carvalho de Melo {
1948f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int;
1949f33cbe72SArnaldo Carvalho de Melo done = 1;
1950f33cbe72SArnaldo Carvalho de Melo child_finished = 1;
1951f33cbe72SArnaldo Carvalho de Melo }
1952f33cbe72SArnaldo Carvalho de Melo
19532dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1954bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
19552dd6d8a1SAdrian Hunter
evlist__pick_pc(struct evlist * evlist)1956db0ea13cSArnaldo Carvalho de Melo static const struct perf_event_mmap_page *evlist__pick_pc(struct evlist *evlist)
1957ee667f94SWang Nan {
1958b2cb615dSWang Nan if (evlist) {
1959547740f7SJiri Olsa if (evlist->mmap && evlist->mmap[0].core.base)
1960547740f7SJiri Olsa return evlist->mmap[0].core.base;
1961547740f7SJiri Olsa if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base)
1962547740f7SJiri Olsa return evlist->overwrite_mmap[0].core.base;
1963b2cb615dSWang Nan }
1964ee667f94SWang Nan return NULL;
1965ee667f94SWang Nan }
1966ee667f94SWang Nan
record__pick_pc(struct record * rec)1967c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1968c45628b0SWang Nan {
1969db0ea13cSArnaldo Carvalho de Melo const struct perf_event_mmap_page *pc = evlist__pick_pc(rec->evlist);
1970ee667f94SWang Nan if (pc)
1971ee667f94SWang Nan return pc;
1972c45628b0SWang Nan return NULL;
1973c45628b0SWang Nan }
1974c45628b0SWang Nan
record__synthesize(struct record * rec,bool tail)19754ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1976c45c86ebSWang Nan {
1977c45c86ebSWang Nan struct perf_session *session = rec->session;
1978c45c86ebSWang Nan struct machine *machine = &session->machines.host;
19798ceb41d7SJiri Olsa struct perf_data *data = &rec->data;
1980c45c86ebSWang Nan struct record_opts *opts = &rec->opts;
1981c45c86ebSWang Nan struct perf_tool *tool = &rec->tool;
1982c45c86ebSWang Nan int err = 0;
1983d99c22eaSStephane Eranian event_op f = process_synthesized_event;
1984c45c86ebSWang Nan
19854ea648aeSWang Nan if (rec->opts.tail_synthesize != tail)
19864ea648aeSWang Nan return 0;
19874ea648aeSWang Nan
19888ceb41d7SJiri Olsa if (data->is_pipe) {
1989c3a057dcSNamhyung Kim err = perf_event__synthesize_for_pipe(tool, session, data,
1990c45c86ebSWang Nan process_synthesized_event);
1991c3a057dcSNamhyung Kim if (err < 0)
1992c45c86ebSWang Nan goto out;
1993c45c86ebSWang Nan
1994c45c86ebSWang Nan rec->bytes_written += err;
1995c45c86ebSWang Nan }
1996c45c86ebSWang Nan
1997c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
199846bc29b9SAdrian Hunter process_synthesized_event, machine);
199946bc29b9SAdrian Hunter if (err)
200046bc29b9SAdrian Hunter goto out;
200146bc29b9SAdrian Hunter
2002c0a6de06SAdrian Hunter /* Synthesize id_index before auxtrace_info */
2003c0a6de06SAdrian Hunter err = perf_event__synthesize_id_index(tool,
2004c0a6de06SAdrian Hunter process_synthesized_event,
2005c0a6de06SAdrian Hunter session->evlist, machine);
2006c0a6de06SAdrian Hunter if (err)
2007c0a6de06SAdrian Hunter goto out;
2008c0a6de06SAdrian Hunter
2009c45c86ebSWang Nan if (rec->opts.full_auxtrace) {
2010c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
2011c45c86ebSWang Nan session, process_synthesized_event);
2012c45c86ebSWang Nan if (err)
2013c45c86ebSWang Nan goto out;
2014c45c86ebSWang Nan }
2015c45c86ebSWang Nan
201678e1bc25SArnaldo Carvalho de Melo if (!evlist__exclude_kernel(rec->evlist)) {
2017c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
2018c45c86ebSWang Nan machine);
2019c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
2020c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
2021c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n");
2022c45c86ebSWang Nan
2023c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event,
2024c45c86ebSWang Nan machine);
2025c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
2026c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
2027c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n");
20286c443954SArnaldo Carvalho de Melo }
2029c45c86ebSWang Nan
2030c45c86ebSWang Nan if (perf_guest) {
2031c45c86ebSWang Nan machines__process_guests(&session->machines,
2032c45c86ebSWang Nan perf_event__synthesize_guest_os, tool);
2033c45c86ebSWang Nan }
2034c45c86ebSWang Nan
2035bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool,
2036bfd8f72cSAndi Kleen rec->evlist,
2037bfd8f72cSAndi Kleen process_synthesized_event,
2038bfd8f72cSAndi Kleen data->is_pipe);
2039bfd8f72cSAndi Kleen if (err)
2040bfd8f72cSAndi Kleen goto out;
2041bfd8f72cSAndi Kleen
204203617c22SJiri Olsa err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads,
2043373565d2SAndi Kleen process_synthesized_event,
2044373565d2SAndi Kleen NULL);
2045373565d2SAndi Kleen if (err < 0) {
2046373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n");
2047373565d2SAndi Kleen return err;
2048373565d2SAndi Kleen }
2049373565d2SAndi Kleen
20507be1feddSAdrian Hunter err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.all_cpus,
2051373565d2SAndi Kleen process_synthesized_event, NULL);
2052373565d2SAndi Kleen if (err < 0) {
2053373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n");
2054373565d2SAndi Kleen return err;
2055373565d2SAndi Kleen }
2056373565d2SAndi Kleen
2057e5416950SSong Liu err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
20587b612e29SSong Liu machine, opts);
2059faf59ec8SAdrian Hunter if (err < 0) {
20607b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n");
2061faf59ec8SAdrian Hunter err = 0;
2062faf59ec8SAdrian Hunter }
20637b612e29SSong Liu
206441b740b6SNamhyung Kim if (rec->opts.synth & PERF_SYNTH_CGROUP) {
2065ab64069fSNamhyung Kim err = perf_event__synthesize_cgroups(tool, process_synthesized_event,
2066ab64069fSNamhyung Kim machine);
2067faf59ec8SAdrian Hunter if (err < 0) {
2068ab64069fSNamhyung Kim pr_warning("Couldn't synthesize cgroup events.\n");
2069faf59ec8SAdrian Hunter err = 0;
2070faf59ec8SAdrian Hunter }
207141b740b6SNamhyung Kim }
2072ab64069fSNamhyung Kim
2073d99c22eaSStephane Eranian if (rec->opts.nr_threads_synthesize > 1) {
207449c670b1SIan Rogers mutex_init(&synth_lock);
2075d99c22eaSStephane Eranian perf_set_multithreaded();
2076d99c22eaSStephane Eranian f = process_locked_synthesized_event;
2077d99c22eaSStephane Eranian }
2078d99c22eaSStephane Eranian
207941b740b6SNamhyung Kim if (rec->opts.synth & PERF_SYNTH_TASK) {
208041b740b6SNamhyung Kim bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP;
208141b740b6SNamhyung Kim
208284111b9cSNamhyung Kim err = __machine__synthesize_threads(machine, tool, &opts->target,
208384111b9cSNamhyung Kim rec->evlist->core.threads,
208441b740b6SNamhyung Kim f, needs_mmap, opts->sample_address,
2085d99c22eaSStephane Eranian rec->opts.nr_threads_synthesize);
208641b740b6SNamhyung Kim }
2087d99c22eaSStephane Eranian
208849c670b1SIan Rogers if (rec->opts.nr_threads_synthesize > 1) {
2089d99c22eaSStephane Eranian perf_set_singlethreaded();
209049c670b1SIan Rogers mutex_destroy(&synth_lock);
209149c670b1SIan Rogers }
2092d99c22eaSStephane Eranian
2093c45c86ebSWang Nan out:
2094c45c86ebSWang Nan return err;
2095c45c86ebSWang Nan }
2096c45c86ebSWang Nan
record__process_signal_event(union perf_event * event __maybe_unused,void * data)2097899e5ffbSArnaldo Carvalho de Melo static int record__process_signal_event(union perf_event *event __maybe_unused, void *data)
2098899e5ffbSArnaldo Carvalho de Melo {
2099899e5ffbSArnaldo Carvalho de Melo struct record *rec = data;
2100899e5ffbSArnaldo Carvalho de Melo pthread_kill(rec->thread_id, SIGUSR2);
2101899e5ffbSArnaldo Carvalho de Melo return 0;
2102899e5ffbSArnaldo Carvalho de Melo }
2103899e5ffbSArnaldo Carvalho de Melo
record__setup_sb_evlist(struct record * rec)210423cbb41cSArnaldo Carvalho de Melo static int record__setup_sb_evlist(struct record *rec)
210523cbb41cSArnaldo Carvalho de Melo {
210623cbb41cSArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts;
210723cbb41cSArnaldo Carvalho de Melo
210823cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist != NULL) {
210923cbb41cSArnaldo Carvalho de Melo /*
211023cbb41cSArnaldo Carvalho de Melo * We get here if --switch-output-event populated the
211123cbb41cSArnaldo Carvalho de Melo * sb_evlist, so associate a callback that will send a SIGUSR2
211223cbb41cSArnaldo Carvalho de Melo * to the main thread.
211323cbb41cSArnaldo Carvalho de Melo */
211423cbb41cSArnaldo Carvalho de Melo evlist__set_cb(rec->sb_evlist, record__process_signal_event, rec);
211523cbb41cSArnaldo Carvalho de Melo rec->thread_id = pthread_self();
211623cbb41cSArnaldo Carvalho de Melo }
21171101c872SJin Yao #ifdef HAVE_LIBBPF_SUPPORT
211823cbb41cSArnaldo Carvalho de Melo if (!opts->no_bpf_event) {
211923cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) {
212023cbb41cSArnaldo Carvalho de Melo rec->sb_evlist = evlist__new();
212123cbb41cSArnaldo Carvalho de Melo
212223cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) {
212323cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't create side band evlist.\n.");
212423cbb41cSArnaldo Carvalho de Melo return -1;
212523cbb41cSArnaldo Carvalho de Melo }
212623cbb41cSArnaldo Carvalho de Melo }
212723cbb41cSArnaldo Carvalho de Melo
212823cbb41cSArnaldo Carvalho de Melo if (evlist__add_bpf_sb_event(rec->sb_evlist, &rec->session->header.env)) {
212923cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n.");
213023cbb41cSArnaldo Carvalho de Melo return -1;
213123cbb41cSArnaldo Carvalho de Melo }
213223cbb41cSArnaldo Carvalho de Melo }
21331101c872SJin Yao #endif
213408c83997SArnaldo Carvalho de Melo if (evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) {
213523cbb41cSArnaldo Carvalho de Melo pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
213623cbb41cSArnaldo Carvalho de Melo opts->no_bpf_event = true;
213723cbb41cSArnaldo Carvalho de Melo }
213823cbb41cSArnaldo Carvalho de Melo
213923cbb41cSArnaldo Carvalho de Melo return 0;
214023cbb41cSArnaldo Carvalho de Melo }
214123cbb41cSArnaldo Carvalho de Melo
record__init_clock(struct record * rec)2142d1e325cfSJiri Olsa static int record__init_clock(struct record *rec)
2143d1e325cfSJiri Olsa {
2144d1e325cfSJiri Olsa struct perf_session *session = rec->session;
2145d1e325cfSJiri Olsa struct timespec ref_clockid;
2146d1e325cfSJiri Olsa struct timeval ref_tod;
2147d1e325cfSJiri Olsa u64 ref;
2148d1e325cfSJiri Olsa
2149d1e325cfSJiri Olsa if (!rec->opts.use_clockid)
2150d1e325cfSJiri Olsa return 0;
2151d1e325cfSJiri Olsa
21529d88a1a1SJiri Olsa if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
21539d88a1a1SJiri Olsa session->header.env.clock.clockid_res_ns = rec->opts.clockid_res_ns;
21549d88a1a1SJiri Olsa
2155d1e325cfSJiri Olsa session->header.env.clock.clockid = rec->opts.clockid;
2156d1e325cfSJiri Olsa
2157d1e325cfSJiri Olsa if (gettimeofday(&ref_tod, NULL) != 0) {
2158d1e325cfSJiri Olsa pr_err("gettimeofday failed, cannot set reference time.\n");
2159d1e325cfSJiri Olsa return -1;
2160d1e325cfSJiri Olsa }
2161d1e325cfSJiri Olsa
2162d1e325cfSJiri Olsa if (clock_gettime(rec->opts.clockid, &ref_clockid)) {
2163d1e325cfSJiri Olsa pr_err("clock_gettime failed, cannot set reference time.\n");
2164d1e325cfSJiri Olsa return -1;
2165d1e325cfSJiri Olsa }
2166d1e325cfSJiri Olsa
2167d1e325cfSJiri Olsa ref = (u64) ref_tod.tv_sec * NSEC_PER_SEC +
2168d1e325cfSJiri Olsa (u64) ref_tod.tv_usec * NSEC_PER_USEC;
2169d1e325cfSJiri Olsa
2170d1e325cfSJiri Olsa session->header.env.clock.tod_ns = ref;
2171d1e325cfSJiri Olsa
2172d1e325cfSJiri Olsa ref = (u64) ref_clockid.tv_sec * NSEC_PER_SEC +
2173d1e325cfSJiri Olsa (u64) ref_clockid.tv_nsec;
2174d1e325cfSJiri Olsa
2175d1e325cfSJiri Olsa session->header.env.clock.clockid_ns = ref;
2176d1e325cfSJiri Olsa return 0;
2177d1e325cfSJiri Olsa }
2178d1e325cfSJiri Olsa
hit_auxtrace_snapshot_trigger(struct record * rec)2179d20aff15SAdrian Hunter static void hit_auxtrace_snapshot_trigger(struct record *rec)
2180d20aff15SAdrian Hunter {
2181d20aff15SAdrian Hunter if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
2182d20aff15SAdrian Hunter trigger_hit(&auxtrace_snapshot_trigger);
2183d20aff15SAdrian Hunter auxtrace_record__snapshot_started = 1;
2184d20aff15SAdrian Hunter if (auxtrace_record__snapshot_start(rec->itr))
2185d20aff15SAdrian Hunter trigger_error(&auxtrace_snapshot_trigger);
2186d20aff15SAdrian Hunter }
2187d20aff15SAdrian Hunter }
2188d20aff15SAdrian Hunter
record__terminate_thread(struct record_thread * thread_data)21891e5de7d9SAlexey Bayduraev static int record__terminate_thread(struct record_thread *thread_data)
21901e5de7d9SAlexey Bayduraev {
21911e5de7d9SAlexey Bayduraev int err;
21921e5de7d9SAlexey Bayduraev enum thread_msg ack = THREAD_MSG__UNDEFINED;
21931e5de7d9SAlexey Bayduraev pid_t tid = thread_data->tid;
21941e5de7d9SAlexey Bayduraev
21951e5de7d9SAlexey Bayduraev close(thread_data->pipes.msg[1]);
21961e5de7d9SAlexey Bayduraev thread_data->pipes.msg[1] = -1;
21971e5de7d9SAlexey Bayduraev err = read(thread_data->pipes.ack[0], &ack, sizeof(ack));
21981e5de7d9SAlexey Bayduraev if (err > 0)
21991e5de7d9SAlexey Bayduraev pr_debug2("threads[%d]: sent %s\n", tid, thread_msg_tags[ack]);
22001e5de7d9SAlexey Bayduraev else
22011e5de7d9SAlexey Bayduraev pr_warning("threads[%d]: failed to receive termination notification from %d\n",
22021e5de7d9SAlexey Bayduraev thread->tid, tid);
22031e5de7d9SAlexey Bayduraev
22041e5de7d9SAlexey Bayduraev return 0;
22051e5de7d9SAlexey Bayduraev }
22061e5de7d9SAlexey Bayduraev
record__start_threads(struct record * rec)2207396b626bSAlexey Bayduraev static int record__start_threads(struct record *rec)
2208396b626bSAlexey Bayduraev {
22093217e9feSAlexey Bayduraev int t, tt, err, ret = 0, nr_threads = rec->nr_threads;
2210396b626bSAlexey Bayduraev struct record_thread *thread_data = rec->thread_data;
22113217e9feSAlexey Bayduraev sigset_t full, mask;
22123217e9feSAlexey Bayduraev pthread_t handle;
22133217e9feSAlexey Bayduraev pthread_attr_t attrs;
2214396b626bSAlexey Bayduraev
2215396b626bSAlexey Bayduraev thread = &thread_data[0];
2216396b626bSAlexey Bayduraev
22173217e9feSAlexey Bayduraev if (!record__threads_enabled(rec))
22183217e9feSAlexey Bayduraev return 0;
22193217e9feSAlexey Bayduraev
22203217e9feSAlexey Bayduraev sigfillset(&full);
22213217e9feSAlexey Bayduraev if (sigprocmask(SIG_SETMASK, &full, &mask)) {
22223217e9feSAlexey Bayduraev pr_err("Failed to block signals on threads start: %s\n", strerror(errno));
22233217e9feSAlexey Bayduraev return -1;
22243217e9feSAlexey Bayduraev }
22253217e9feSAlexey Bayduraev
22263217e9feSAlexey Bayduraev pthread_attr_init(&attrs);
22273217e9feSAlexey Bayduraev pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
22283217e9feSAlexey Bayduraev
22293217e9feSAlexey Bayduraev for (t = 1; t < nr_threads; t++) {
22303217e9feSAlexey Bayduraev enum thread_msg msg = THREAD_MSG__UNDEFINED;
22313217e9feSAlexey Bayduraev
22323217e9feSAlexey Bayduraev #ifdef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
22333217e9feSAlexey Bayduraev pthread_attr_setaffinity_np(&attrs,
22343217e9feSAlexey Bayduraev MMAP_CPU_MASK_BYTES(&(thread_data[t].mask->affinity)),
22353217e9feSAlexey Bayduraev (cpu_set_t *)(thread_data[t].mask->affinity.bits));
22363217e9feSAlexey Bayduraev #endif
22373217e9feSAlexey Bayduraev if (pthread_create(&handle, &attrs, record__thread, &thread_data[t])) {
22383217e9feSAlexey Bayduraev for (tt = 1; tt < t; tt++)
22393217e9feSAlexey Bayduraev record__terminate_thread(&thread_data[t]);
22403217e9feSAlexey Bayduraev pr_err("Failed to start threads: %s\n", strerror(errno));
22413217e9feSAlexey Bayduraev ret = -1;
22423217e9feSAlexey Bayduraev goto out_err;
22433217e9feSAlexey Bayduraev }
22443217e9feSAlexey Bayduraev
22453217e9feSAlexey Bayduraev err = read(thread_data[t].pipes.ack[0], &msg, sizeof(msg));
22463217e9feSAlexey Bayduraev if (err > 0)
22473217e9feSAlexey Bayduraev pr_debug2("threads[%d]: sent %s\n", rec->thread_data[t].tid,
22483217e9feSAlexey Bayduraev thread_msg_tags[msg]);
22493217e9feSAlexey Bayduraev else
22503217e9feSAlexey Bayduraev pr_warning("threads[%d]: failed to receive start notification from %d\n",
22513217e9feSAlexey Bayduraev thread->tid, rec->thread_data[t].tid);
22523217e9feSAlexey Bayduraev }
22533217e9feSAlexey Bayduraev
22543217e9feSAlexey Bayduraev sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&thread->mask->affinity),
22553217e9feSAlexey Bayduraev (cpu_set_t *)thread->mask->affinity.bits);
22563217e9feSAlexey Bayduraev
2257396b626bSAlexey Bayduraev pr_debug("threads[%d]: started on cpu%d\n", thread->tid, sched_getcpu());
2258396b626bSAlexey Bayduraev
22593217e9feSAlexey Bayduraev out_err:
22603217e9feSAlexey Bayduraev pthread_attr_destroy(&attrs);
22613217e9feSAlexey Bayduraev
22623217e9feSAlexey Bayduraev if (sigprocmask(SIG_SETMASK, &mask, NULL)) {
22633217e9feSAlexey Bayduraev pr_err("Failed to unblock signals on threads start: %s\n", strerror(errno));
22643217e9feSAlexey Bayduraev ret = -1;
22653217e9feSAlexey Bayduraev }
22663217e9feSAlexey Bayduraev
22673217e9feSAlexey Bayduraev return ret;
2268396b626bSAlexey Bayduraev }
2269396b626bSAlexey Bayduraev
record__stop_threads(struct record * rec)2270396b626bSAlexey Bayduraev static int record__stop_threads(struct record *rec)
2271396b626bSAlexey Bayduraev {
2272396b626bSAlexey Bayduraev int t;
2273396b626bSAlexey Bayduraev struct record_thread *thread_data = rec->thread_data;
2274396b626bSAlexey Bayduraev
22751e5de7d9SAlexey Bayduraev for (t = 1; t < rec->nr_threads; t++)
22761e5de7d9SAlexey Bayduraev record__terminate_thread(&thread_data[t]);
22771e5de7d9SAlexey Bayduraev
2278610fbc01SAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++) {
2279396b626bSAlexey Bayduraev rec->samples += thread_data[t].samples;
2280610fbc01SAlexey Bayduraev if (!record__threads_enabled(rec))
2281610fbc01SAlexey Bayduraev continue;
2282610fbc01SAlexey Bayduraev rec->session->bytes_transferred += thread_data[t].bytes_transferred;
2283610fbc01SAlexey Bayduraev rec->session->bytes_compressed += thread_data[t].bytes_compressed;
2284610fbc01SAlexey Bayduraev pr_debug("threads[%d]: samples=%lld, wakes=%ld, ", thread_data[t].tid,
2285610fbc01SAlexey Bayduraev thread_data[t].samples, thread_data[t].waking);
2286610fbc01SAlexey Bayduraev if (thread_data[t].bytes_transferred && thread_data[t].bytes_compressed)
2287610fbc01SAlexey Bayduraev pr_debug("transferred=%" PRIu64 ", compressed=%" PRIu64 "\n",
2288610fbc01SAlexey Bayduraev thread_data[t].bytes_transferred, thread_data[t].bytes_compressed);
2289610fbc01SAlexey Bayduraev else
2290610fbc01SAlexey Bayduraev pr_debug("written=%" PRIu64 "\n", thread_data[t].bytes_written);
2291610fbc01SAlexey Bayduraev }
2292396b626bSAlexey Bayduraev
2293396b626bSAlexey Bayduraev return 0;
2294396b626bSAlexey Bayduraev }
2295396b626bSAlexey Bayduraev
record__waking(struct record * rec)2296396b626bSAlexey Bayduraev static unsigned long record__waking(struct record *rec)
2297396b626bSAlexey Bayduraev {
2298396b626bSAlexey Bayduraev int t;
2299396b626bSAlexey Bayduraev unsigned long waking = 0;
2300396b626bSAlexey Bayduraev struct record_thread *thread_data = rec->thread_data;
2301396b626bSAlexey Bayduraev
2302396b626bSAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++)
2303396b626bSAlexey Bayduraev waking += thread_data[t].waking;
2304396b626bSAlexey Bayduraev
2305396b626bSAlexey Bayduraev return waking;
2306396b626bSAlexey Bayduraev }
2307396b626bSAlexey Bayduraev
__cmd_record(struct record * rec,int argc,const char ** argv)23088c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
230986470930SIngo Molnar {
231057706abcSDavid Ahern int err;
231145604710SNamhyung Kim int status = 0;
231246be604bSZhang, Yanmin const bool forks = argc > 0;
231345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool;
2314b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts;
23158ceb41d7SJiri Olsa struct perf_data *data = &rec->data;
2316d20deb64SArnaldo Carvalho de Melo struct perf_session *session;
23176dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false;
231842aa276fSNamhyung Kim int fd;
2319d3c8c08eSAlexey Budankov float ratio = 0;
2320acce0223SAlexey Budankov enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED;
232186470930SIngo Molnar
232245604710SNamhyung Kim atexit(record__sig_exit);
2323f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler);
2324f5970550SPeter Zijlstra signal(SIGINT, sig_handler);
2325804f7ac7SDavid Ahern signal(SIGTERM, sig_handler);
2326a074865eSWang Nan signal(SIGSEGV, sigsegv_handler);
2327c0bdc1c4SWang Nan
2328f3b3614aSHari Bathini if (rec->opts.record_namespaces)
2329f3b3614aSHari Bathini tool->namespace_events = true;
2330f3b3614aSHari Bathini
23318fb4b679SNamhyung Kim if (rec->opts.record_cgroup) {
23328fb4b679SNamhyung Kim #ifdef HAVE_FILE_HANDLE
23338fb4b679SNamhyung Kim tool->cgroup_events = true;
23348fb4b679SNamhyung Kim #else
23358fb4b679SNamhyung Kim pr_err("cgroup tracking is not supported\n");
23368fb4b679SNamhyung Kim return -1;
23378fb4b679SNamhyung Kim #endif
23388fb4b679SNamhyung Kim }
23398fb4b679SNamhyung Kim
2340dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
23412dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler);
23423c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode)
23435f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger);
2344dc0c6127SJiri Olsa if (rec->switch_output.enabled)
23453c1cb7e3SWang Nan trigger_on(&switch_output_trigger);
2346c0bdc1c4SWang Nan } else {
23472dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN);
2348c0bdc1c4SWang Nan }
2349f5970550SPeter Zijlstra
23502681bd85SNamhyung Kim session = perf_session__new(data, tool);
23516ef81c55SMamatha Inamdar if (IS_ERR(session)) {
2352ffa91880SAdrien BAK pr_err("Perf session creation failed.\n");
23536ef81c55SMamatha Inamdar return PTR_ERR(session);
2354a9a70bbcSArnaldo Carvalho de Melo }
2355a9a70bbcSArnaldo Carvalho de Melo
2356b5f2511dSAlexey Bayduraev if (record__threads_enabled(rec)) {
2357b5f2511dSAlexey Bayduraev if (perf_data__is_pipe(&rec->data)) {
2358b5f2511dSAlexey Bayduraev pr_err("Parallel trace streaming is not available in pipe mode.\n");
2359b5f2511dSAlexey Bayduraev return -1;
2360b5f2511dSAlexey Bayduraev }
2361b5f2511dSAlexey Bayduraev if (rec->opts.full_auxtrace) {
2362b5f2511dSAlexey Bayduraev pr_err("Parallel trace streaming is not available in AUX area tracing mode.\n");
2363b5f2511dSAlexey Bayduraev return -1;
2364b5f2511dSAlexey Bayduraev }
2365b5f2511dSAlexey Bayduraev }
2366b5f2511dSAlexey Bayduraev
23678ceb41d7SJiri Olsa fd = perf_data__fd(data);
2368d20deb64SArnaldo Carvalho de Melo rec->session = session;
2369d20deb64SArnaldo Carvalho de Melo
23705d7f4116SAlexey Budankov if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
23715d7f4116SAlexey Budankov pr_err("Compression initialization failed.\n");
23725d7f4116SAlexey Budankov return -1;
23735d7f4116SAlexey Budankov }
2374da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
2375da231338SAnand K Mistry done_fd = eventfd(0, EFD_NONBLOCK);
2376da231338SAnand K Mistry if (done_fd < 0) {
2377da231338SAnand K Mistry pr_err("Failed to create wakeup eventfd, error: %m\n");
2378da231338SAnand K Mistry status = -1;
2379da231338SAnand K Mistry goto out_delete_session;
2380da231338SAnand K Mistry }
2381e16c2ce7SYang Jihong err = evlist__add_wakeup_eventfd(rec->evlist, done_fd);
2382da231338SAnand K Mistry if (err < 0) {
2383da231338SAnand K Mistry pr_err("Failed to add wakeup eventfd to poll list\n");
2384da231338SAnand K Mistry status = err;
2385da231338SAnand K Mistry goto out_delete_session;
2386da231338SAnand K Mistry }
2387da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT
23885d7f4116SAlexey Budankov
23895d7f4116SAlexey Budankov session->header.env.comp_type = PERF_COMP_ZSTD;
23905d7f4116SAlexey Budankov session->header.env.comp_level = rec->opts.comp_level;
23915d7f4116SAlexey Budankov
2392eeb399b5SAdrian Hunter if (rec->opts.kcore &&
2393eeb399b5SAdrian Hunter !record__kcore_readable(&session->machines.host)) {
2394eeb399b5SAdrian Hunter pr_err("ERROR: kcore is not readable.\n");
2395eeb399b5SAdrian Hunter return -1;
2396eeb399b5SAdrian Hunter }
2397eeb399b5SAdrian Hunter
2398d1e325cfSJiri Olsa if (record__init_clock(rec))
2399d1e325cfSJiri Olsa return -1;
2400d1e325cfSJiri Olsa
24018c6f45a7SArnaldo Carvalho de Melo record__init_features(rec);
2402330aa675SStephane Eranian
2403d4db3f16SArnaldo Carvalho de Melo if (forks) {
24047b392ef0SArnaldo Carvalho de Melo err = evlist__prepare_workload(rec->evlist, &opts->target, argv, data->is_pipe,
2405735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal);
240635b9d88eSArnaldo Carvalho de Melo if (err < 0) {
240735b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n");
240845604710SNamhyung Kim status = err;
240935b9d88eSArnaldo Carvalho de Melo goto out_delete_session;
2410856e9660SPeter Zijlstra }
2411856e9660SPeter Zijlstra }
2412856e9660SPeter Zijlstra
2413ad46e48cSJiri Olsa /*
2414ad46e48cSJiri Olsa * If we have just single event and are sending data
2415ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation,
2416ad46e48cSJiri Olsa * because we synthesize event name through the pipe
2417ad46e48cSJiri Olsa * and need the id for that.
2418ad46e48cSJiri Olsa */
24196484d2f9SJiri Olsa if (data->is_pipe && rec->evlist->core.nr_entries == 1)
2420ad46e48cSJiri Olsa rec->opts.sample_id = true;
2421ad46e48cSJiri Olsa
2422e55c8abaSYang Jihong if (rec->timestamp_filename && perf_data__is_pipe(data)) {
2423e55c8abaSYang Jihong rec->timestamp_filename = false;
2424e55c8abaSYang Jihong pr_warning("WARNING: --timestamp-filename option is not available in pipe mode.\n");
2425e55c8abaSYang Jihong }
2426e55c8abaSYang Jihong
24271f7b3c80SKan Liang evlist__uniquify_name(rec->evlist);
242891c0f5ecSJin Yao
2429*829afc13SAdrian Hunter evlist__config(rec->evlist, opts, &callchain_param);
2430*829afc13SAdrian Hunter
2431da406202SAdrian Hunter /* Debug message used by test scripts */
2432da406202SAdrian Hunter pr_debug3("perf record opening and mmapping events\n");
24338c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) {
24348d3eca20SDavid Ahern err = -1;
2435396b626bSAlexey Bayduraev goto out_free_threads;
24368d3eca20SDavid Ahern }
2437da406202SAdrian Hunter /* Debug message used by test scripts */
2438da406202SAdrian Hunter pr_debug3("perf record done opening and mmapping events\n");
2439f6fa4375SJiri Olsa session->header.env.comp_mmap_len = session->evlist->core.mmap_len;
244086470930SIngo Molnar
2441eeb399b5SAdrian Hunter if (rec->opts.kcore) {
2442eeb399b5SAdrian Hunter err = record__kcore_copy(&session->machines.host, data);
2443eeb399b5SAdrian Hunter if (err) {
2444eeb399b5SAdrian Hunter pr_err("ERROR: Failed to copy kcore\n");
2445396b626bSAlexey Bayduraev goto out_free_threads;
2446eeb399b5SAdrian Hunter }
2447eeb399b5SAdrian Hunter }
2448eeb399b5SAdrian Hunter
2449cca8482cSAdrian Hunter /*
2450cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the
2451cca8482cSAdrian Hunter * evlist.
2452cca8482cSAdrian Hunter */
24538cedf3a5SArnaldo Carvalho de Melo if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) {
2454cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
2455cca8482cSAdrian Hunter rec->tool.ordered_events = false;
2456cca8482cSAdrian Hunter }
2457cca8482cSAdrian Hunter
24589d2dc632SIan Rogers if (evlist__nr_groups(rec->evlist) == 0)
2459a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
2460a8bb559bSNamhyung Kim
24618ceb41d7SJiri Olsa if (data->is_pipe) {
246242aa276fSNamhyung Kim err = perf_header__write_pipe(fd);
2463529870e3STom Zanussi if (err < 0)
2464396b626bSAlexey Bayduraev goto out_free_threads;
2465563aecb2SJiri Olsa } else {
246642aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false);
2467d5eed904SArnaldo Carvalho de Melo if (err < 0)
2468396b626bSAlexey Bayduraev goto out_free_threads;
2469d5eed904SArnaldo Carvalho de Melo }
24707c6a1c65SPeter Zijlstra
2471b38d85efSArnaldo Carvalho de Melo err = -1;
2472d3665498SDavid Ahern if (!rec->no_buildid
2473e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
2474d3665498SDavid Ahern pr_err("Couldn't generate buildids. "
2475e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n");
2476396b626bSAlexey Bayduraev goto out_free_threads;
2477e20960c0SRobert Richter }
2478e20960c0SRobert Richter
247923cbb41cSArnaldo Carvalho de Melo err = record__setup_sb_evlist(rec);
248023cbb41cSArnaldo Carvalho de Melo if (err)
2481396b626bSAlexey Bayduraev goto out_free_threads;
2482657ee553SSong Liu
24834ea648aeSWang Nan err = record__synthesize(rec, false);
2484c45c86ebSWang Nan if (err < 0)
2485396b626bSAlexey Bayduraev goto out_free_threads;
24868d3eca20SDavid Ahern
2487d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) {
248886470930SIngo Molnar struct sched_param param;
248986470930SIngo Molnar
2490d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio;
249186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
24926beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n");
24938d3eca20SDavid Ahern err = -1;
2494396b626bSAlexey Bayduraev goto out_free_threads;
249586470930SIngo Molnar }
249686470930SIngo Molnar }
249786470930SIngo Molnar
2498396b626bSAlexey Bayduraev if (record__start_threads(rec))
2499396b626bSAlexey Bayduraev goto out_free_threads;
2500396b626bSAlexey Bayduraev
2501774cb499SJiri Olsa /*
2502774cb499SJiri Olsa * When perf is starting the traced process, all the events
2503774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set,
2504774cb499SJiri Olsa * so don't spoil it by prematurely enabling them.
2505774cb499SJiri Olsa */
2506cb4b9e68SChangbin Du if (!target__none(&opts->target) && !opts->target.initial_delay)
25071c87f165SJiri Olsa evlist__enable(rec->evlist);
2508764e16a3SDavid Ahern
2509856e9660SPeter Zijlstra /*
2510856e9660SPeter Zijlstra * Let the child rip
2511856e9660SPeter Zijlstra */
2512e803cf97SNamhyung Kim if (forks) {
251320a8a3cfSJiri Olsa struct machine *machine = &session->machines.host;
2514e5bed564SNamhyung Kim union perf_event *event;
2515e907caf3SHari Bathini pid_t tgid;
2516e5bed564SNamhyung Kim
2517e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size);
2518e5bed564SNamhyung Kim if (event == NULL) {
2519e5bed564SNamhyung Kim err = -ENOMEM;
2520e5bed564SNamhyung Kim goto out_child;
2521e5bed564SNamhyung Kim }
2522e5bed564SNamhyung Kim
2523e803cf97SNamhyung Kim /*
2524e803cf97SNamhyung Kim * Some H/W events are generated before COMM event
2525e803cf97SNamhyung Kim * which is emitted during exec(), so perf script
2526e803cf97SNamhyung Kim * cannot see a correct process name for those events.
2527e803cf97SNamhyung Kim * Synthesize COMM event to prevent it.
2528e803cf97SNamhyung Kim */
2529e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event,
2530e803cf97SNamhyung Kim rec->evlist->workload.pid,
2531e803cf97SNamhyung Kim process_synthesized_event,
2532e803cf97SNamhyung Kim machine);
2533e5bed564SNamhyung Kim free(event);
2534e803cf97SNamhyung Kim
2535e907caf3SHari Bathini if (tgid == -1)
2536e907caf3SHari Bathini goto out_child;
2537e907caf3SHari Bathini
2538e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) +
2539e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
2540e907caf3SHari Bathini machine->id_hdr_size);
2541e907caf3SHari Bathini if (event == NULL) {
2542e907caf3SHari Bathini err = -ENOMEM;
2543e907caf3SHari Bathini goto out_child;
2544e907caf3SHari Bathini }
2545e907caf3SHari Bathini
2546e907caf3SHari Bathini /*
2547e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified.
2548e907caf3SHari Bathini */
2549e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event,
2550e907caf3SHari Bathini rec->evlist->workload.pid,
2551e907caf3SHari Bathini tgid, process_synthesized_event,
2552e907caf3SHari Bathini machine);
2553e907caf3SHari Bathini free(event);
2554e907caf3SHari Bathini
25557b392ef0SArnaldo Carvalho de Melo evlist__start_workload(rec->evlist);
2556e803cf97SNamhyung Kim }
2557856e9660SPeter Zijlstra
2558cb4b9e68SChangbin Du if (opts->target.initial_delay) {
255968cd3b45SAlexey Budankov pr_info(EVLIST_DISABLED_MSG);
2560cb4b9e68SChangbin Du if (opts->target.initial_delay > 0) {
2561cb4b9e68SChangbin Du usleep(opts->target.initial_delay * USEC_PER_MSEC);
25621c87f165SJiri Olsa evlist__enable(rec->evlist);
256368cd3b45SAlexey Budankov pr_info(EVLIST_ENABLED_MSG);
256468cd3b45SAlexey Budankov }
25656619a53eSAndi Kleen }
25666619a53eSAndi Kleen
25676657a099SAdrian Hunter err = event_enable_timer__start(rec->evlist->eet);
25686657a099SAdrian Hunter if (err)
25696657a099SAdrian Hunter goto out_child;
25706657a099SAdrian Hunter
2571da406202SAdrian Hunter /* Debug message used by test scripts */
2572da406202SAdrian Hunter pr_debug3("perf record has started\n");
2573da406202SAdrian Hunter fflush(stderr);
2574da406202SAdrian Hunter
25755f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger);
25763c1cb7e3SWang Nan trigger_ready(&switch_output_trigger);
2577a074865eSWang Nan perf_hooks__invoke_record_start();
25783812d298SAdrian Hunter
25793812d298SAdrian Hunter /*
25803812d298SAdrian Hunter * Must write FINISHED_INIT so it will be seen after all other
25813812d298SAdrian Hunter * synthesized user events, but before any regular events.
25823812d298SAdrian Hunter */
25833812d298SAdrian Hunter err = write_finished_init(rec, false);
25843812d298SAdrian Hunter if (err < 0)
25853812d298SAdrian Hunter goto out_child;
25863812d298SAdrian Hunter
2587649c48a9SPeter Zijlstra for (;;) {
2588396b626bSAlexey Bayduraev unsigned long long hits = thread->samples;
258986470930SIngo Molnar
259005737464SWang Nan /*
259105737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be
259205737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and
259305737464SWang Nan * hits != rec->samples in previous round.
259405737464SWang Nan *
2595ade9d208SArnaldo Carvalho de Melo * evlist__toggle_bkw_mmap ensure we never
259605737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
259705737464SWang Nan */
259805737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining)
2599ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
260005737464SWang Nan
2601470530bbSAlexey Budankov if (record__mmap_read_all(rec, false) < 0) {
26025f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger);
26033c1cb7e3SWang Nan trigger_error(&switch_output_trigger);
26048d3eca20SDavid Ahern err = -1;
260545604710SNamhyung Kim goto out_child;
26068d3eca20SDavid Ahern }
260786470930SIngo Molnar
26082dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) {
26092dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0;
26105f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger))
2611ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, false);
26125f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) {
26132dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n");
26142dd6d8a1SAdrian Hunter err = -1;
26152dd6d8a1SAdrian Hunter goto out_child;
26162dd6d8a1SAdrian Hunter }
26172dd6d8a1SAdrian Hunter }
26182dd6d8a1SAdrian Hunter
26193c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) {
262005737464SWang Nan /*
262105737464SWang Nan * If switch_output_trigger is hit, the data in
262205737464SWang Nan * overwritable ring buffer should have been collected,
262305737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
262405737464SWang Nan *
262505737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(),
262605737464SWang Nan * record__mmap_read_all() didn't collect data from
262705737464SWang Nan * overwritable ring buffer. Read again.
262805737464SWang Nan */
262905737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
263005737464SWang Nan continue;
26313c1cb7e3SWang Nan trigger_ready(&switch_output_trigger);
26323c1cb7e3SWang Nan
263305737464SWang Nan /*
263405737464SWang Nan * Reenable events in overwrite ring buffer after
263505737464SWang Nan * record__mmap_read_all(): we should have collected
263605737464SWang Nan * data from it.
263705737464SWang Nan */
2638ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
263905737464SWang Nan
26403c1cb7e3SWang Nan if (!quiet)
26413c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
2642396b626bSAlexey Bayduraev record__waking(rec));
2643396b626bSAlexey Bayduraev thread->waking = 0;
26443c1cb7e3SWang Nan fd = record__switch_output(rec, false);
26453c1cb7e3SWang Nan if (fd < 0) {
26463c1cb7e3SWang Nan pr_err("Failed to switch to new file\n");
26473c1cb7e3SWang Nan trigger_error(&switch_output_trigger);
26483c1cb7e3SWang Nan err = fd;
26493c1cb7e3SWang Nan goto out_child;
26503c1cb7e3SWang Nan }
2651bfacbe3bSJiri Olsa
2652bfacbe3bSJiri Olsa /* re-arm the alarm */
2653bfacbe3bSJiri Olsa if (rec->switch_output.time)
2654bfacbe3bSJiri Olsa alarm(rec->switch_output.time);
26553c1cb7e3SWang Nan }
26563c1cb7e3SWang Nan
2657396b626bSAlexey Bayduraev if (hits == thread->samples) {
26586dcf45efSArnaldo Carvalho de Melo if (done || draining)
2659649c48a9SPeter Zijlstra break;
2660396b626bSAlexey Bayduraev err = fdarray__poll(&thread->pollfd, -1);
2661a515114fSJiri Olsa /*
2662a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive
2663a515114fSJiri Olsa * number of returned events and interrupt error.
2664a515114fSJiri Olsa */
2665a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR))
266645604710SNamhyung Kim err = 0;
2667396b626bSAlexey Bayduraev thread->waking++;
26686dcf45efSArnaldo Carvalho de Melo
2669396b626bSAlexey Bayduraev if (fdarray__filter(&thread->pollfd, POLLERR | POLLHUP,
2670396b626bSAlexey Bayduraev record__thread_munmap_filtered, NULL) == 0)
26716dcf45efSArnaldo Carvalho de Melo draining = true;
2672396b626bSAlexey Bayduraev
26736562c9acSAdrian Hunter err = record__update_evlist_pollfd_from_thread(rec, rec->evlist, thread);
26746562c9acSAdrian Hunter if (err)
26756562c9acSAdrian Hunter goto out_child;
26768b412664SPeter Zijlstra }
26778b412664SPeter Zijlstra
2678acce0223SAlexey Budankov if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) {
2679acce0223SAlexey Budankov switch (cmd) {
2680d20aff15SAdrian Hunter case EVLIST_CTL_CMD_SNAPSHOT:
2681d20aff15SAdrian Hunter hit_auxtrace_snapshot_trigger(rec);
2682d20aff15SAdrian Hunter evlist__ctlfd_ack(rec->evlist);
2683d20aff15SAdrian Hunter break;
2684f186cd61SJiri Olsa case EVLIST_CTL_CMD_STOP:
2685f186cd61SJiri Olsa done = 1;
2686f186cd61SJiri Olsa break;
2687acce0223SAlexey Budankov case EVLIST_CTL_CMD_ACK:
2688acce0223SAlexey Budankov case EVLIST_CTL_CMD_UNSUPPORTED:
2689991ae4ebSJiri Olsa case EVLIST_CTL_CMD_ENABLE:
2690991ae4ebSJiri Olsa case EVLIST_CTL_CMD_DISABLE:
2691142544a9SJiri Olsa case EVLIST_CTL_CMD_EVLIST:
269247fddcb4SJiri Olsa case EVLIST_CTL_CMD_PING:
2693acce0223SAlexey Budankov default:
2694acce0223SAlexey Budankov break;
2695acce0223SAlexey Budankov }
2696acce0223SAlexey Budankov }
2697acce0223SAlexey Budankov
26986657a099SAdrian Hunter err = event_enable_timer__process(rec->evlist->eet);
26996657a099SAdrian Hunter if (err < 0)
27006657a099SAdrian Hunter goto out_child;
27016657a099SAdrian Hunter if (err) {
27026657a099SAdrian Hunter err = 0;
27036657a099SAdrian Hunter done = 1;
27046657a099SAdrian Hunter }
27056657a099SAdrian Hunter
2706774cb499SJiri Olsa /*
2707774cb499SJiri Olsa * When perf is starting the traced process, at the end events
2708774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to
2709774cb499SJiri Olsa * disable events in this case.
2710774cb499SJiri Olsa */
2711602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) {
27125f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger);
2713e74676deSJiri Olsa evlist__disable(rec->evlist);
27142711926aSJiri Olsa disabled = true;
27152711926aSJiri Olsa }
27168b412664SPeter Zijlstra }
2717ce7b0e42SAlexander Shishkin
27185f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger);
27193c1cb7e3SWang Nan trigger_off(&switch_output_trigger);
27208b412664SPeter Zijlstra
2721ce7b0e42SAlexander Shishkin if (opts->auxtrace_snapshot_on_exit)
2722ce7b0e42SAlexander Shishkin record__auxtrace_snapshot_exit(rec);
2723ce7b0e42SAlexander Shishkin
2724f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) {
27253535a696SArnaldo Carvalho de Melo char msg[STRERR_BUFSIZE], strevsels[2048];
2726c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
27273535a696SArnaldo Carvalho de Melo
27283535a696SArnaldo Carvalho de Melo evlist__scnprintf_evsels(rec->evlist, sizeof(strevsels), strevsels);
27293535a696SArnaldo Carvalho de Melo
27303535a696SArnaldo Carvalho de Melo pr_err("Failed to collect '%s' for the '%s' workload: %s\n",
27313535a696SArnaldo Carvalho de Melo strevsels, argv[0], emsg);
2732f33cbe72SArnaldo Carvalho de Melo err = -1;
273345604710SNamhyung Kim goto out_child;
2734f33cbe72SArnaldo Carvalho de Melo }
2735f33cbe72SArnaldo Carvalho de Melo
2736e3d59112SNamhyung Kim if (!quiet)
2737396b626bSAlexey Bayduraev fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n",
2738396b626bSAlexey Bayduraev record__waking(rec));
273986470930SIngo Molnar
27403812d298SAdrian Hunter write_finished_init(rec, true);
27413812d298SAdrian Hunter
27424ea648aeSWang Nan if (target__none(&rec->opts.target))
27434ea648aeSWang Nan record__synthesize_workload(rec, true);
27444ea648aeSWang Nan
274545604710SNamhyung Kim out_child:
2746396b626bSAlexey Bayduraev record__stop_threads(rec);
2747470530bbSAlexey Budankov record__mmap_read_all(rec, true);
2748396b626bSAlexey Bayduraev out_free_threads:
2749415ccb58SAlexey Bayduraev record__free_thread_data(rec);
2750396b626bSAlexey Bayduraev evlist__finalize_ctlfd(rec->evlist);
2751d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec);
2752d3d1af6fSAlexey Budankov
2753d3c8c08eSAlexey Budankov if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
2754d3c8c08eSAlexey Budankov ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
2755d3c8c08eSAlexey Budankov session->header.env.comp_ratio = ratio + 0.5;
2756d3c8c08eSAlexey Budankov }
2757d3c8c08eSAlexey Budankov
275845604710SNamhyung Kim if (forks) {
275945604710SNamhyung Kim int exit_status;
276045604710SNamhyung Kim
276145604710SNamhyung Kim if (!child_finished)
276245604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM);
276345604710SNamhyung Kim
276445604710SNamhyung Kim wait(&exit_status);
276545604710SNamhyung Kim
276645604710SNamhyung Kim if (err < 0)
276745604710SNamhyung Kim status = err;
276845604710SNamhyung Kim else if (WIFEXITED(exit_status))
276945604710SNamhyung Kim status = WEXITSTATUS(exit_status);
277045604710SNamhyung Kim else if (WIFSIGNALED(exit_status))
277145604710SNamhyung Kim signr = WTERMSIG(exit_status);
277245604710SNamhyung Kim } else
277345604710SNamhyung Kim status = err;
277445604710SNamhyung Kim
2775edc41a10SNamhyung Kim if (rec->off_cpu)
2776edc41a10SNamhyung Kim rec->bytes_written += off_cpu_write(rec->session);
2777edc41a10SNamhyung Kim
2778e3a23261SNamhyung Kim record__read_lost_samples(rec);
27794ea648aeSWang Nan record__synthesize(rec, true);
2780e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */
2781e3d59112SNamhyung Kim rec->samples = 0;
2782e3d59112SNamhyung Kim
2783ecfd7a9cSWang Nan if (!err) {
2784ecfd7a9cSWang Nan if (!rec->timestamp_filename) {
2785e1ab48baSWang Nan record__finish_output(rec);
2786ecfd7a9cSWang Nan } else {
2787ecfd7a9cSWang Nan fd = record__switch_output(rec, true);
2788ecfd7a9cSWang Nan if (fd < 0) {
2789ecfd7a9cSWang Nan status = fd;
2790ecfd7a9cSWang Nan goto out_delete_session;
2791ecfd7a9cSWang Nan }
2792ecfd7a9cSWang Nan }
2793ecfd7a9cSWang Nan }
279439d17dacSArnaldo Carvalho de Melo
2795a074865eSWang Nan perf_hooks__invoke_record_end();
2796a074865eSWang Nan
2797e3d59112SNamhyung Kim if (!err && !quiet) {
2798e3d59112SNamhyung Kim char samples[128];
2799ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ?
2800ecfd7a9cSWang Nan ".<timestamp>" : "";
2801e3d59112SNamhyung Kim
2802ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace)
2803e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples),
2804e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples);
2805e3d59112SNamhyung Kim else
2806e3d59112SNamhyung Kim samples[0] = '\0';
2807e3d59112SNamhyung Kim
2808d3c8c08eSAlexey Budankov fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s",
28098ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0,
28102d4f2799SJiri Olsa data->path, postfix, samples);
2811d3c8c08eSAlexey Budankov if (ratio) {
2812d3c8c08eSAlexey Budankov fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)",
2813d3c8c08eSAlexey Budankov rec->session->bytes_transferred / 1024.0 / 1024.0,
2814d3c8c08eSAlexey Budankov ratio);
2815d3c8c08eSAlexey Budankov }
2816d3c8c08eSAlexey Budankov fprintf(stderr, " ]\n");
2817e3d59112SNamhyung Kim }
2818e3d59112SNamhyung Kim
281939d17dacSArnaldo Carvalho de Melo out_delete_session:
2820da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT
2821304f0a2fSIan Rogers if (done_fd >= 0) {
2822304f0a2fSIan Rogers fd = done_fd;
2823304f0a2fSIan Rogers done_fd = -1;
2824304f0a2fSIan Rogers
2825304f0a2fSIan Rogers close(fd);
2826304f0a2fSIan Rogers }
2827da231338SAnand K Mistry #endif
28285d7f4116SAlexey Budankov zstd_fini(&session->zstd_data);
2829657ee553SSong Liu if (!opts->no_bpf_event)
283008c83997SArnaldo Carvalho de Melo evlist__stop_sb_thread(rec->sb_evlist);
2831834e603dSIan Rogers
2832834e603dSIan Rogers perf_session__delete(session);
283345604710SNamhyung Kim return status;
283486470930SIngo Molnar }
283586470930SIngo Molnar
callchain_debug(struct callchain_param * callchain)28360883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
283709b0fd45SJiri Olsa {
2838aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
2839a601fdffSJiri Olsa
28400883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]);
284126d33022SJiri Olsa
28420883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF)
284309b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n",
28440883e820SArnaldo Carvalho de Melo callchain->dump_size);
28450883e820SArnaldo Carvalho de Melo }
28460883e820SArnaldo Carvalho de Melo
record_opts__parse_callchain(struct record_opts * record,struct callchain_param * callchain,const char * arg,bool unset)28470883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
28480883e820SArnaldo Carvalho de Melo struct callchain_param *callchain,
28490883e820SArnaldo Carvalho de Melo const char *arg, bool unset)
28500883e820SArnaldo Carvalho de Melo {
28510883e820SArnaldo Carvalho de Melo int ret;
28520883e820SArnaldo Carvalho de Melo callchain->enabled = !unset;
28530883e820SArnaldo Carvalho de Melo
28540883e820SArnaldo Carvalho de Melo /* --no-call-graph */
28550883e820SArnaldo Carvalho de Melo if (unset) {
28560883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE;
28570883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n");
28580883e820SArnaldo Carvalho de Melo return 0;
28590883e820SArnaldo Carvalho de Melo }
28600883e820SArnaldo Carvalho de Melo
28610883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain);
28620883e820SArnaldo Carvalho de Melo if (!ret) {
28630883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */
28640883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF)
28650883e820SArnaldo Carvalho de Melo record->sample_address = true;
28660883e820SArnaldo Carvalho de Melo callchain_debug(callchain);
28670883e820SArnaldo Carvalho de Melo }
28680883e820SArnaldo Carvalho de Melo
28690883e820SArnaldo Carvalho de Melo return ret;
287009b0fd45SJiri Olsa }
287109b0fd45SJiri Olsa
record_parse_callchain_opt(const struct option * opt,const char * arg,int unset)2872c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
287309b0fd45SJiri Olsa const char *arg,
287409b0fd45SJiri Olsa int unset)
287509b0fd45SJiri Olsa {
28760883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
287726d33022SJiri Olsa }
287826d33022SJiri Olsa
record_callchain_opt(const struct option * opt,const char * arg __maybe_unused,int unset __maybe_unused)2879c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
288009b0fd45SJiri Olsa const char *arg __maybe_unused,
288109b0fd45SJiri Olsa int unset __maybe_unused)
288209b0fd45SJiri Olsa {
28832ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value;
2884c421e80bSKan Liang
28852ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true;
288609b0fd45SJiri Olsa
28872ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE)
28882ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP;
2889eb853e80SJiri Olsa
28902ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain);
289109b0fd45SJiri Olsa return 0;
289209b0fd45SJiri Olsa }
289309b0fd45SJiri Olsa
perf_record_config(const char * var,const char * value,void * cb)2894eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
2895eb853e80SJiri Olsa {
28967a29c087SNamhyung Kim struct record *rec = cb;
28977a29c087SNamhyung Kim
28987a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) {
28997a29c087SNamhyung Kim if (!strcmp(value, "cache"))
29007a29c087SNamhyung Kim rec->no_buildid_cache = false;
29017a29c087SNamhyung Kim else if (!strcmp(value, "no-cache"))
29027a29c087SNamhyung Kim rec->no_buildid_cache = true;
29037a29c087SNamhyung Kim else if (!strcmp(value, "skip"))
29047a29c087SNamhyung Kim rec->no_buildid = true;
2905e29386c8SJiri Olsa else if (!strcmp(value, "mmap"))
2906e29386c8SJiri Olsa rec->buildid_mmap = true;
29077a29c087SNamhyung Kim else
29087a29c087SNamhyung Kim return -1;
29097a29c087SNamhyung Kim return 0;
29107a29c087SNamhyung Kim }
2911cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) {
2912cff17205SYisheng Xie var = "call-graph.record-mode";
2913eb853e80SJiri Olsa return perf_default_config(var, value, cb);
2914eb853e80SJiri Olsa }
291593f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
291693f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) {
291793f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0);
291893f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks)
291993f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default;
292093f20c0fSAlexey Budankov }
292193f20c0fSAlexey Budankov #endif
29229bce13eaSJiri Olsa if (!strcmp(var, "record.debuginfod")) {
29239bce13eaSJiri Olsa rec->debuginfod.urls = strdup(value);
29249bce13eaSJiri Olsa if (!rec->debuginfod.urls)
29259bce13eaSJiri Olsa return -ENOMEM;
29269bce13eaSJiri Olsa rec->debuginfod.set = true;
29279bce13eaSJiri Olsa }
2928eb853e80SJiri Olsa
2929cff17205SYisheng Xie return 0;
2930cff17205SYisheng Xie }
2931cff17205SYisheng Xie
record__parse_event_enable_time(const struct option * opt,const char * str,int unset)29326657a099SAdrian Hunter static int record__parse_event_enable_time(const struct option *opt, const char *str, int unset)
29336657a099SAdrian Hunter {
29346657a099SAdrian Hunter struct record *rec = (struct record *)opt->value;
29356657a099SAdrian Hunter
29366657a099SAdrian Hunter return evlist__parse_event_enable_time(rec->evlist, &rec->opts, str, unset);
29376657a099SAdrian Hunter }
2938814c8c38SPeter Zijlstra
record__parse_affinity(const struct option * opt,const char * str,int unset)2939f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
2940f4fe11b7SAlexey Budankov {
2941f4fe11b7SAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value;
2942f4fe11b7SAlexey Budankov
2943f4fe11b7SAlexey Budankov if (unset || !str)
2944f4fe11b7SAlexey Budankov return 0;
2945f4fe11b7SAlexey Budankov
2946f4fe11b7SAlexey Budankov if (!strcasecmp(str, "node"))
2947f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_NODE;
2948f4fe11b7SAlexey Budankov else if (!strcasecmp(str, "cpu"))
2949f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_CPU;
2950f4fe11b7SAlexey Budankov
2951f4fe11b7SAlexey Budankov return 0;
2952f4fe11b7SAlexey Budankov }
2953f4fe11b7SAlexey Budankov
record__mmap_cpu_mask_alloc(struct mmap_cpu_mask * mask,int nr_bits)29547954f716SAlexey Bayduraev static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits)
29557954f716SAlexey Bayduraev {
29567954f716SAlexey Bayduraev mask->nbits = nr_bits;
29577954f716SAlexey Bayduraev mask->bits = bitmap_zalloc(mask->nbits);
29587954f716SAlexey Bayduraev if (!mask->bits)
29597954f716SAlexey Bayduraev return -ENOMEM;
29607954f716SAlexey Bayduraev
29617954f716SAlexey Bayduraev return 0;
29627954f716SAlexey Bayduraev }
29637954f716SAlexey Bayduraev
record__mmap_cpu_mask_free(struct mmap_cpu_mask * mask)29647954f716SAlexey Bayduraev static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask)
29657954f716SAlexey Bayduraev {
29667954f716SAlexey Bayduraev bitmap_free(mask->bits);
29677954f716SAlexey Bayduraev mask->nbits = 0;
29687954f716SAlexey Bayduraev }
29697954f716SAlexey Bayduraev
record__thread_mask_alloc(struct thread_mask * mask,int nr_bits)29707954f716SAlexey Bayduraev static int record__thread_mask_alloc(struct thread_mask *mask, int nr_bits)
29717954f716SAlexey Bayduraev {
29727954f716SAlexey Bayduraev int ret;
29737954f716SAlexey Bayduraev
29747954f716SAlexey Bayduraev ret = record__mmap_cpu_mask_alloc(&mask->maps, nr_bits);
29757954f716SAlexey Bayduraev if (ret) {
29767954f716SAlexey Bayduraev mask->affinity.bits = NULL;
29777954f716SAlexey Bayduraev return ret;
29787954f716SAlexey Bayduraev }
29797954f716SAlexey Bayduraev
29807954f716SAlexey Bayduraev ret = record__mmap_cpu_mask_alloc(&mask->affinity, nr_bits);
29817954f716SAlexey Bayduraev if (ret) {
29827954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->maps);
29837954f716SAlexey Bayduraev mask->maps.bits = NULL;
29847954f716SAlexey Bayduraev }
29857954f716SAlexey Bayduraev
29867954f716SAlexey Bayduraev return ret;
29877954f716SAlexey Bayduraev }
29887954f716SAlexey Bayduraev
record__thread_mask_free(struct thread_mask * mask)29897954f716SAlexey Bayduraev static void record__thread_mask_free(struct thread_mask *mask)
29907954f716SAlexey Bayduraev {
29917954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->maps);
29927954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->affinity);
29937954f716SAlexey Bayduraev }
29947954f716SAlexey Bayduraev
record__parse_threads(const struct option * opt,const char * str,int unset)299506380a84SAlexey Bayduraev static int record__parse_threads(const struct option *opt, const char *str, int unset)
299606380a84SAlexey Bayduraev {
2997f466e5edSAlexey Bayduraev int s;
299806380a84SAlexey Bayduraev struct record_opts *opts = opt->value;
299906380a84SAlexey Bayduraev
3000f466e5edSAlexey Bayduraev if (unset || !str || !strlen(str)) {
300106380a84SAlexey Bayduraev opts->threads_spec = THREAD_SPEC__CPU;
3002f466e5edSAlexey Bayduraev } else {
3003f466e5edSAlexey Bayduraev for (s = 1; s < THREAD_SPEC__MAX; s++) {
3004f466e5edSAlexey Bayduraev if (s == THREAD_SPEC__USER) {
3005f466e5edSAlexey Bayduraev opts->threads_user_spec = strdup(str);
3006f466e5edSAlexey Bayduraev if (!opts->threads_user_spec)
3007f466e5edSAlexey Bayduraev return -ENOMEM;
3008f466e5edSAlexey Bayduraev opts->threads_spec = THREAD_SPEC__USER;
3009f466e5edSAlexey Bayduraev break;
3010f466e5edSAlexey Bayduraev }
3011f466e5edSAlexey Bayduraev if (!strncasecmp(str, thread_spec_tags[s], strlen(thread_spec_tags[s]))) {
3012f466e5edSAlexey Bayduraev opts->threads_spec = s;
3013f466e5edSAlexey Bayduraev break;
3014f466e5edSAlexey Bayduraev }
3015f466e5edSAlexey Bayduraev }
3016f466e5edSAlexey Bayduraev }
3017f466e5edSAlexey Bayduraev
3018f466e5edSAlexey Bayduraev if (opts->threads_spec == THREAD_SPEC__USER)
3019f466e5edSAlexey Bayduraev pr_debug("threads_spec: %s\n", opts->threads_user_spec);
3020f466e5edSAlexey Bayduraev else
3021f466e5edSAlexey Bayduraev pr_debug("threads_spec: %s\n", thread_spec_tags[opts->threads_spec]);
302206380a84SAlexey Bayduraev
302306380a84SAlexey Bayduraev return 0;
302406380a84SAlexey Bayduraev }
302506380a84SAlexey Bayduraev
parse_output_max_size(const struct option * opt,const char * str,int unset)30266d575816SJiwei Sun static int parse_output_max_size(const struct option *opt,
30276d575816SJiwei Sun const char *str, int unset)
30286d575816SJiwei Sun {
30296d575816SJiwei Sun unsigned long *s = (unsigned long *)opt->value;
30306d575816SJiwei Sun static struct parse_tag tags_size[] = {
30316d575816SJiwei Sun { .tag = 'B', .mult = 1 },
30326d575816SJiwei Sun { .tag = 'K', .mult = 1 << 10 },
30336d575816SJiwei Sun { .tag = 'M', .mult = 1 << 20 },
30346d575816SJiwei Sun { .tag = 'G', .mult = 1 << 30 },
30356d575816SJiwei Sun { .tag = 0 },
30366d575816SJiwei Sun };
30376d575816SJiwei Sun unsigned long val;
30386d575816SJiwei Sun
30396d575816SJiwei Sun if (unset) {
30406d575816SJiwei Sun *s = 0;
30416d575816SJiwei Sun return 0;
30426d575816SJiwei Sun }
30436d575816SJiwei Sun
30446d575816SJiwei Sun val = parse_tag_value(str, tags_size);
30456d575816SJiwei Sun if (val != (unsigned long) -1) {
30466d575816SJiwei Sun *s = val;
30476d575816SJiwei Sun return 0;
30486d575816SJiwei Sun }
30496d575816SJiwei Sun
30506d575816SJiwei Sun return -1;
30516d575816SJiwei Sun }
30526d575816SJiwei Sun
record__parse_mmap_pages(const struct option * opt,const char * str,int unset __maybe_unused)3053e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
3054e9db1310SAdrian Hunter const char *str,
3055e9db1310SAdrian Hunter int unset __maybe_unused)
3056e9db1310SAdrian Hunter {
3057e9db1310SAdrian Hunter struct record_opts *opts = opt->value;
3058e9db1310SAdrian Hunter char *s, *p;
3059e9db1310SAdrian Hunter unsigned int mmap_pages;
3060e9db1310SAdrian Hunter int ret;
3061e9db1310SAdrian Hunter
3062e9db1310SAdrian Hunter if (!str)
3063e9db1310SAdrian Hunter return -EINVAL;
3064e9db1310SAdrian Hunter
3065e9db1310SAdrian Hunter s = strdup(str);
3066e9db1310SAdrian Hunter if (!s)
3067e9db1310SAdrian Hunter return -ENOMEM;
3068e9db1310SAdrian Hunter
3069e9db1310SAdrian Hunter p = strchr(s, ',');
3070e9db1310SAdrian Hunter if (p)
3071e9db1310SAdrian Hunter *p = '\0';
3072e9db1310SAdrian Hunter
3073e9db1310SAdrian Hunter if (*s) {
307425f84702SArnaldo Carvalho de Melo ret = __evlist__parse_mmap_pages(&mmap_pages, s);
3075e9db1310SAdrian Hunter if (ret)
3076e9db1310SAdrian Hunter goto out_free;
3077e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages;
3078e9db1310SAdrian Hunter }
3079e9db1310SAdrian Hunter
3080e9db1310SAdrian Hunter if (!p) {
3081e9db1310SAdrian Hunter ret = 0;
3082e9db1310SAdrian Hunter goto out_free;
3083e9db1310SAdrian Hunter }
3084e9db1310SAdrian Hunter
308525f84702SArnaldo Carvalho de Melo ret = __evlist__parse_mmap_pages(&mmap_pages, p + 1);
3086e9db1310SAdrian Hunter if (ret)
3087e9db1310SAdrian Hunter goto out_free;
3088e9db1310SAdrian Hunter
3089e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages;
3090e9db1310SAdrian Hunter
3091e9db1310SAdrian Hunter out_free:
3092e9db1310SAdrian Hunter free(s);
3093e9db1310SAdrian Hunter return ret;
3094e9db1310SAdrian Hunter }
3095e9db1310SAdrian Hunter
arch__add_leaf_frame_record_opts(struct record_opts * opts __maybe_unused)30967248e308SAlexandre Truong void __weak arch__add_leaf_frame_record_opts(struct record_opts *opts __maybe_unused)
30977248e308SAlexandre Truong {
30987248e308SAlexandre Truong }
30997248e308SAlexandre Truong
parse_control_option(const struct option * opt,const char * str,int unset __maybe_unused)31001d078ccbSAlexey Budankov static int parse_control_option(const struct option *opt,
31011d078ccbSAlexey Budankov const char *str,
31021d078ccbSAlexey Budankov int unset __maybe_unused)
31031d078ccbSAlexey Budankov {
31049864a66dSAdrian Hunter struct record_opts *opts = opt->value;
31051d078ccbSAlexey Budankov
3106a8fcbd26SAdrian Hunter return evlist__parse_control(str, &opts->ctl_fd, &opts->ctl_fd_ack, &opts->ctl_fd_close);
3107a8fcbd26SAdrian Hunter }
3108a8fcbd26SAdrian Hunter
switch_output_size_warn(struct record * rec)31090c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
31100c582449SJiri Olsa {
31119521b5f2SJiri Olsa u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages);
31120c582449SJiri Olsa struct switch_output *s = &rec->switch_output;
31130c582449SJiri Olsa
31140c582449SJiri Olsa wakeup_size /= 2;
31150c582449SJiri Olsa
31160c582449SJiri Olsa if (s->size < wakeup_size) {
31170c582449SJiri Olsa char buf[100];
31180c582449SJiri Olsa
31190c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
31200c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than "
31210c582449SJiri Olsa "wakeup kernel buffer size (%s) "
31220c582449SJiri Olsa "expect bigger perf.data sizes\n", buf);
31230c582449SJiri Olsa }
31240c582449SJiri Olsa }
31250c582449SJiri Olsa
switch_output_setup(struct record * rec)3126cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
3127cb4e1ebbSJiri Olsa {
3128cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output;
3129dc0c6127SJiri Olsa static struct parse_tag tags_size[] = {
3130dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 },
3131dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 },
3132dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 },
3133dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 },
3134dc0c6127SJiri Olsa { .tag = 0 },
3135dc0c6127SJiri Olsa };
3136bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = {
3137bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 },
3138bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 },
3139bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 },
3140bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 },
3141bfacbe3bSJiri Olsa { .tag = 0 },
3142bfacbe3bSJiri Olsa };
3143dc0c6127SJiri Olsa unsigned long val;
3144cb4e1ebbSJiri Olsa
3145899e5ffbSArnaldo Carvalho de Melo /*
3146899e5ffbSArnaldo Carvalho de Melo * If we're using --switch-output-events, then we imply its
3147899e5ffbSArnaldo Carvalho de Melo * --switch-output=signal, as we'll send a SIGUSR2 from the side band
3148899e5ffbSArnaldo Carvalho de Melo * thread to its parent.
3149899e5ffbSArnaldo Carvalho de Melo */
3150b5f2511dSAlexey Bayduraev if (rec->switch_output_event_set) {
3151b5f2511dSAlexey Bayduraev if (record__threads_enabled(rec)) {
3152b5f2511dSAlexey Bayduraev pr_warning("WARNING: --switch-output-event option is not available in parallel streaming mode.\n");
3153b5f2511dSAlexey Bayduraev return 0;
3154b5f2511dSAlexey Bayduraev }
3155899e5ffbSArnaldo Carvalho de Melo goto do_signal;
3156b5f2511dSAlexey Bayduraev }
3157899e5ffbSArnaldo Carvalho de Melo
3158cb4e1ebbSJiri Olsa if (!s->set)
3159cb4e1ebbSJiri Olsa return 0;
3160cb4e1ebbSJiri Olsa
3161b5f2511dSAlexey Bayduraev if (record__threads_enabled(rec)) {
3162b5f2511dSAlexey Bayduraev pr_warning("WARNING: --switch-output option is not available in parallel streaming mode.\n");
3163b5f2511dSAlexey Bayduraev return 0;
3164b5f2511dSAlexey Bayduraev }
3165b5f2511dSAlexey Bayduraev
3166cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) {
3167899e5ffbSArnaldo Carvalho de Melo do_signal:
3168cb4e1ebbSJiri Olsa s->signal = true;
3169cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n");
3170dc0c6127SJiri Olsa goto enabled;
3171dc0c6127SJiri Olsa }
3172dc0c6127SJiri Olsa
3173dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size);
3174dc0c6127SJiri Olsa if (val != (unsigned long) -1) {
3175dc0c6127SJiri Olsa s->size = val;
3176dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str);
3177dc0c6127SJiri Olsa goto enabled;
3178cb4e1ebbSJiri Olsa }
3179cb4e1ebbSJiri Olsa
3180bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time);
3181bfacbe3bSJiri Olsa if (val != (unsigned long) -1) {
3182bfacbe3bSJiri Olsa s->time = val;
3183bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n",
3184bfacbe3bSJiri Olsa s->str, s->time);
3185bfacbe3bSJiri Olsa goto enabled;
3186bfacbe3bSJiri Olsa }
3187bfacbe3bSJiri Olsa
3188cb4e1ebbSJiri Olsa return -1;
3189dc0c6127SJiri Olsa
3190dc0c6127SJiri Olsa enabled:
3191dc0c6127SJiri Olsa rec->timestamp_filename = true;
3192dc0c6127SJiri Olsa s->enabled = true;
31930c582449SJiri Olsa
31940c582449SJiri Olsa if (s->size && !rec->opts.no_buffering)
31950c582449SJiri Olsa switch_output_size_warn(rec);
31960c582449SJiri Olsa
3197dc0c6127SJiri Olsa return 0;
3198cb4e1ebbSJiri Olsa }
3199cb4e1ebbSJiri Olsa
3200e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
320186470930SIngo Molnar "perf record [<options>] [<command>]",
320286470930SIngo Molnar "perf record [<options>] -- <command> [<options>]",
320386470930SIngo Molnar NULL
320486470930SIngo Molnar };
3205e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
320686470930SIngo Molnar
build_id__process_mmap(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample,struct machine * machine)32076e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap(struct perf_tool *tool, union perf_event *event,
32086e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine)
32096e0a9b3dSArnaldo Carvalho de Melo {
32106e0a9b3dSArnaldo Carvalho de Melo /*
32116e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
32126e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice.
32136e0a9b3dSArnaldo Carvalho de Melo */
32146e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER))
32156e0a9b3dSArnaldo Carvalho de Melo return 0;
32166e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap(tool, event, sample, machine);
32176e0a9b3dSArnaldo Carvalho de Melo }
32186e0a9b3dSArnaldo Carvalho de Melo
build_id__process_mmap2(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample,struct machine * machine)32196e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event,
32206e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine)
32216e0a9b3dSArnaldo Carvalho de Melo {
32226e0a9b3dSArnaldo Carvalho de Melo /*
32236e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
32246e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice.
32256e0a9b3dSArnaldo Carvalho de Melo */
32266e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER))
32276e0a9b3dSArnaldo Carvalho de Melo return 0;
32286e0a9b3dSArnaldo Carvalho de Melo
32296e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap2(tool, event, sample, machine);
32306e0a9b3dSArnaldo Carvalho de Melo }
32316e0a9b3dSArnaldo Carvalho de Melo
process_timestamp_boundary(struct perf_tool * tool,union perf_event * event __maybe_unused,struct perf_sample * sample,struct machine * machine __maybe_unused)323266286ed3SAdrian Hunter static int process_timestamp_boundary(struct perf_tool *tool,
323366286ed3SAdrian Hunter union perf_event *event __maybe_unused,
323466286ed3SAdrian Hunter struct perf_sample *sample,
323566286ed3SAdrian Hunter struct machine *machine __maybe_unused)
323666286ed3SAdrian Hunter {
323766286ed3SAdrian Hunter struct record *rec = container_of(tool, struct record, tool);
323866286ed3SAdrian Hunter
323966286ed3SAdrian Hunter set_timestamp_boundary(rec, sample->time);
324066286ed3SAdrian Hunter return 0;
324166286ed3SAdrian Hunter }
324266286ed3SAdrian Hunter
parse_record_synth_option(const struct option * opt,const char * str,int unset __maybe_unused)324341b740b6SNamhyung Kim static int parse_record_synth_option(const struct option *opt,
324441b740b6SNamhyung Kim const char *str,
324541b740b6SNamhyung Kim int unset __maybe_unused)
324641b740b6SNamhyung Kim {
324741b740b6SNamhyung Kim struct record_opts *opts = opt->value;
324841b740b6SNamhyung Kim char *p = strdup(str);
324941b740b6SNamhyung Kim
325041b740b6SNamhyung Kim if (p == NULL)
325141b740b6SNamhyung Kim return -1;
325241b740b6SNamhyung Kim
325341b740b6SNamhyung Kim opts->synth = parse_synth_opt(p);
325441b740b6SNamhyung Kim free(p);
325541b740b6SNamhyung Kim
325641b740b6SNamhyung Kim if (opts->synth < 0) {
325741b740b6SNamhyung Kim pr_err("Invalid synth option: %s\n", str);
325841b740b6SNamhyung Kim return -1;
325941b740b6SNamhyung Kim }
326041b740b6SNamhyung Kim return 0;
326141b740b6SNamhyung Kim }
326241b740b6SNamhyung Kim
3263d20deb64SArnaldo Carvalho de Melo /*
32648c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new
32658c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called
3266d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to
3267d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here.
3268d20deb64SArnaldo Carvalho de Melo *
3269d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly.
3270d20deb64SArnaldo Carvalho de Melo *
3271d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh.
3272d20deb64SArnaldo Carvalho de Melo */
32738c6f45a7SArnaldo Carvalho de Melo static struct record record = {
3274d20deb64SArnaldo Carvalho de Melo .opts = {
32758affc2b8SAndi Kleen .sample_time = true,
3276d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX,
3277d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX,
3278d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX,
3279447a6013SArnaldo Carvalho de Melo .freq = 4000,
3280d1cb9fceSNamhyung Kim .target = {
3281d1cb9fceSNamhyung Kim .uses_mmap = true,
32823aa5939dSAdrian Hunter .default_per_cpu = true,
3283d1cb9fceSNamhyung Kim },
3284470530bbSAlexey Budankov .mmap_flush = MMAP_FLUSH_DEFAULT,
3285d99c22eaSStephane Eranian .nr_threads_synthesize = 1,
32861d078ccbSAlexey Budankov .ctl_fd = -1,
32871d078ccbSAlexey Budankov .ctl_fd_ack = -1,
328841b740b6SNamhyung Kim .synth = PERF_SYNTH_ALL,
3289d20deb64SArnaldo Carvalho de Melo },
3290e3d59112SNamhyung Kim .tool = {
3291e3d59112SNamhyung Kim .sample = process_sample_event,
3292e3d59112SNamhyung Kim .fork = perf_event__process_fork,
3293cca8482cSAdrian Hunter .exit = perf_event__process_exit,
3294e3d59112SNamhyung Kim .comm = perf_event__process_comm,
3295f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces,
32966e0a9b3dSArnaldo Carvalho de Melo .mmap = build_id__process_mmap,
32976e0a9b3dSArnaldo Carvalho de Melo .mmap2 = build_id__process_mmap2,
329866286ed3SAdrian Hunter .itrace_start = process_timestamp_boundary,
329966286ed3SAdrian Hunter .aux = process_timestamp_boundary,
3300cca8482cSAdrian Hunter .ordered_events = true,
3301e3d59112SNamhyung Kim },
3302d20deb64SArnaldo Carvalho de Melo };
33037865e817SFrederic Weisbecker
330476a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
330576a26549SNamhyung Kim "\n\t\t\t\tDefault: fp";
330661eaa3beSArnaldo Carvalho de Melo
33070aab2136SWang Nan static bool dry_run;
33080aab2136SWang Nan
3309411ad22eSIan Rogers static struct parse_events_option_args parse_events_option_args = {
3310411ad22eSIan Rogers .evlistp = &record.evlist,
3311411ad22eSIan Rogers };
3312411ad22eSIan Rogers
3313411ad22eSIan Rogers static struct parse_events_option_args switch_output_parse_events_option_args = {
3314411ad22eSIan Rogers .evlistp = &record.sb_evlist,
3315411ad22eSIan Rogers };
3316411ad22eSIan Rogers
3317d20deb64SArnaldo Carvalho de Melo /*
3318d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing
3319d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came
3320b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts,
33217b392ef0SArnaldo Carvalho de Melo * evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
3322d20deb64SArnaldo Carvalho de Melo * using pipes, etc.
3323d20deb64SArnaldo Carvalho de Melo */
3324efd21307SJiri Olsa static struct option __record_options[] = {
3325411ad22eSIan Rogers OPT_CALLBACK('e', "event", &parse_events_option_args, "event",
332686470930SIngo Molnar "event selector. use 'perf list' to list available events",
3327f120f9d5SJiri Olsa parse_events_option),
3328d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter",
3329c171b552SLi Zefan "event filter", parse_filter),
33304ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
33314ba1faa1SWang Nan NULL, "don't record events from perf itself",
33324ba1faa1SWang Nan exclude_perf),
3333bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
3334d6d901c2SZhang, Yanmin "record events on existing process id"),
3335bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
3336d6d901c2SZhang, Yanmin "record events on existing thread id"),
3337d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio,
333886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"),
3339509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
3340acac03faSKirill Smelkov "collect data without buffering"),
3341d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
3342daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"),
3343bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
334486470930SIngo Molnar "system-wide collection from all CPUs"),
3345bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
3346c45c6ea2SStephane Eranian "list of cpus to monitor"),
3347d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
33482d4f2799SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file",
334986470930SIngo Molnar "output file name"),
335069e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
335169e7e5b0SAdrian Hunter &record.opts.no_inherit_set,
33522e6cdf99SStephane Eranian "child tasks do not inherit counters"),
33534ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
33544ea648aeSWang Nan "synthesize non-sample events at the end of output"),
3355626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
3356a060c1f1SWei Li OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "do not record bpf events"),
3357b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
3358b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"),
335967230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
336067230479SArnaldo Carvalho de Melo "profile at this frequency",
336167230479SArnaldo Carvalho de Melo record__parse_freq),
3362e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
3363e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages",
3364e9db1310SAdrian Hunter record__parse_mmap_pages),
3365470530bbSAlexey Budankov OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
3366470530bbSAlexey Budankov "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
3367470530bbSAlexey Budankov record__mmap_flush_parse),
33682ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
336909b0fd45SJiri Olsa NULL, "enables call-graph recording" ,
337009b0fd45SJiri Olsa &record_callchain_opt),
337109b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts,
337276a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help,
337309b0fd45SJiri Olsa &record_parse_callchain_opt),
3374c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose,
33753da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"),
3376a527c2c1SJames Clark OPT_BOOLEAN('q', "quiet", &quiet, "don't print any warnings or messages"),
3377d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
3378649c48a9SPeter Zijlstra "per thread counts"),
337956100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
33803b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
33813b0a5daaSKan Liang "Record the sample physical addresses"),
3382542b88fdSKan Liang OPT_BOOLEAN(0, "data-page-size", &record.opts.sample_data_page_size,
3383542b88fdSKan Liang "Record the sampled data address data page size"),
3384c1de7f3dSKan Liang OPT_BOOLEAN(0, "code-page-size", &record.opts.sample_code_page_size,
3385c1de7f3dSKan Liang "Record the sampled code address (ip) page size"),
3386b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
338761110883SAdrian Hunter OPT_BOOLEAN(0, "sample-identifier", &record.opts.sample_identifier,
338861110883SAdrian Hunter "Record the sample identifier"),
33893abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
33903abebc55SAdrian Hunter &record.opts.sample_time_set,
33913abebc55SAdrian Hunter "Record the sample timestamps"),
3392f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
3393f290aa1fSJiri Olsa "Record the sample period"),
3394d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
3395649c48a9SPeter Zijlstra "don't sample"),
3396d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
3397d2db9a98SWang Nan &record.no_buildid_cache_set,
3398a1ac1d3cSStephane Eranian "do not update the buildid cache"),
3399d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
3400d2db9a98SWang Nan &record.no_buildid_set,
3401baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"),
3402d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
3403023695d9SStephane Eranian "monitor event in cgroup name only",
3404023695d9SStephane Eranian parse_cgroups),
34056657a099SAdrian Hunter OPT_CALLBACK('D', "delay", &record, "ms",
34066657a099SAdrian Hunter "ms to wait before starting measurement after program start (-1: start with events disabled), "
34076657a099SAdrian Hunter "or ranges of time to enable events e.g. '-D 10-20,30-40'",
34086657a099SAdrian Hunter record__parse_event_enable_time),
3409eeb399b5SAdrian Hunter OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"),
3410bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
3411bea03405SNamhyung Kim "user to profile"),
3412a5aabdacSStephane Eranian
3413a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
3414a5aabdacSStephane Eranian "branch any", "sample any taken branches",
3415a5aabdacSStephane Eranian parse_branch_stack),
3416a5aabdacSStephane Eranian
3417a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
3418a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes",
3419bdfebd84SRoberto Agostino Vitillo parse_branch_stack),
342005484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
342105484298SAndi Kleen "sample by weight (on special events only)"),
3422475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
3423475eeab9SAndi Kleen "sample transaction flags (special events only)"),
34243aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
34253aa5939dSAdrian Hunter "use per-thread mmaps"),
3426bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
3427bcc84ec6SStephane Eranian "sample selected machine registers on interrupt,"
3428aeea9062SKan Liang " use '-I?' to list register names", parse_intr_regs),
342984c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
343084c41742SAndi Kleen "sample selected machine registers on interrupt,"
3431aeea9062SKan Liang " use '--user-regs=?' to list register names", parse_user_regs),
343285c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
343385c273d2SAndi Kleen "Record running/enabled time of read (:S) events"),
3434814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts,
3435814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()",
3436814c8c38SPeter Zijlstra parse_clockid),
34372dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
34382dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""),
3439c0a6de06SAdrian Hunter OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts,
3440c0a6de06SAdrian Hunter "opts", "sample AUX area", ""),
34413fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
34429d9cad76SKan Liang "per thread proc mmap processing timeout in ms"),
3443f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
3444f3b3614aSHari Bathini "Record namespaces events"),
34458fb4b679SNamhyung Kim OPT_BOOLEAN(0, "all-cgroups", &record.opts.record_cgroup,
34468fb4b679SNamhyung Kim "Record cgroup events"),
344716b4b4e1SAdrian Hunter OPT_BOOLEAN_SET(0, "switch-events", &record.opts.record_switch_events,
344816b4b4e1SAdrian Hunter &record.opts.record_switch_events_set,
3449b757bb09SAdrian Hunter "Record context switch events"),
345085723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
345185723885SJiri Olsa "Configure all used events to run in kernel space.",
345285723885SJiri Olsa PARSE_OPT_EXCLUSIVE),
345385723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
345485723885SJiri Olsa "Configure all used events to run in user space.",
345585723885SJiri Olsa PARSE_OPT_EXCLUSIVE),
345653651b28Syuzhoujian OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains,
345753651b28Syuzhoujian "collect kernel callchains"),
345853651b28Syuzhoujian OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains,
345953651b28Syuzhoujian "collect user callchains"),
34607efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
34617efe0e03SHe Kuang "file", "vmlinux pathname"),
34626156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
34636156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"),
3464e29386c8SJiri Olsa OPT_BOOLEAN(0, "buildid-mmap", &record.buildid_mmap,
3465e29386c8SJiri Olsa "Record build-id in map events"),
3466ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
3467ecfd7a9cSWang Nan "append timestamp to output filename"),
346868588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
346968588bafSJin Yao "Record timestamp boundary (time of first/last samples)"),
3470cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
3471c38dab7dSAndi Kleen &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
3472c38dab7dSAndi Kleen "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
3473dc0c6127SJiri Olsa "signal"),
3474411ad22eSIan Rogers OPT_CALLBACK_SET(0, "switch-output-event", &switch_output_parse_events_option_args,
3475411ad22eSIan Rogers &record.switch_output_event_set, "switch output event",
3476899e5ffbSArnaldo Carvalho de Melo "switch output event selector. use 'perf list' to list available events",
3477899e5ffbSArnaldo Carvalho de Melo parse_events_option_new_evlist),
347803724b2eSAndi Kleen OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
347903724b2eSAndi Kleen "Limit number of switch output generated files"),
34800aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run,
34810aab2136SWang Nan "Parse options then exit"),
3482d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
348393f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
348493f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
3485d3d1af6fSAlexey Budankov record__aio_parse),
3486d3d1af6fSAlexey Budankov #endif
3487f4fe11b7SAlexey Budankov OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
3488f4fe11b7SAlexey Budankov "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
3489f4fe11b7SAlexey Budankov record__parse_affinity),
3490504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
3491b5f2511dSAlexey Bayduraev OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, "n",
3492b5f2511dSAlexey Bayduraev "Compress records using specified level (default: 1 - fastest compression, 22 - greatest compression)",
3493504c1ad1SAlexey Budankov record__parse_comp_level),
3494504c1ad1SAlexey Budankov #endif
34956d575816SJiwei Sun OPT_CALLBACK(0, "max-size", &record.output_max_size,
34966d575816SJiwei Sun "size", "Limit the maximum size of the output file", parse_output_max_size),
3497d99c22eaSStephane Eranian OPT_UINTEGER(0, "num-thread-synthesize",
3498d99c22eaSStephane Eranian &record.opts.nr_threads_synthesize,
3499d99c22eaSStephane Eranian "number of threads to run for event synthesis"),
350070943490SStephane Eranian #ifdef HAVE_LIBPFM
350170943490SStephane Eranian OPT_CALLBACK(0, "pfm-events", &record.evlist, "event",
350270943490SStephane Eranian "libpfm4 event selector. use 'perf list' to list available events",
350370943490SStephane Eranian parse_libpfm_events_option),
350470943490SStephane Eranian #endif
3505a8fcbd26SAdrian Hunter OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]",
3506d20aff15SAdrian Hunter "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events,\n"
3507d20aff15SAdrian Hunter "\t\t\t 'snapshot': AUX area tracing snapshot).\n"
3508a8fcbd26SAdrian Hunter "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n"
3509a8fcbd26SAdrian Hunter "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.",
35101d078ccbSAlexey Budankov parse_control_option),
351141b740b6SNamhyung Kim OPT_CALLBACK(0, "synth", &record.opts, "no|all|task|mmap|cgroup",
351241b740b6SNamhyung Kim "Fine-tune event synthesis: default=all", parse_record_synth_option),
35139bce13eaSJiri Olsa OPT_STRING_OPTARG_SET(0, "debuginfod", &record.debuginfod.urls,
35149bce13eaSJiri Olsa &record.debuginfod.set, "debuginfod urls",
35159bce13eaSJiri Olsa "Enable debuginfod data retrieval from DEBUGINFOD_URLS or specified urls",
35169bce13eaSJiri Olsa "system"),
351706380a84SAlexey Bayduraev OPT_CALLBACK_OPTARG(0, "threads", &record.opts, NULL, "spec",
351806380a84SAlexey Bayduraev "write collected trace data into several data files using parallel threads",
351906380a84SAlexey Bayduraev record__parse_threads),
3520edc41a10SNamhyung Kim OPT_BOOLEAN(0, "off-cpu", &record.off_cpu, "Enable off-cpu analysis"),
352186470930SIngo Molnar OPT_END()
352286470930SIngo Molnar };
352386470930SIngo Molnar
3524e5b2c207SNamhyung Kim struct option *record_options = __record_options;
3525e5b2c207SNamhyung Kim
record__mmap_cpu_mask_init(struct mmap_cpu_mask * mask,struct perf_cpu_map * cpus)3526cbd7bfc7SAthira Rajeev static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
35277954f716SAlexey Bayduraev {
35280255571aSIan Rogers struct perf_cpu cpu;
35290255571aSIan Rogers int idx;
35307954f716SAlexey Bayduraev
353123380e4dSAlexey Bayduraev if (cpu_map__is_dummy(cpus))
3532cbd7bfc7SAthira Rajeev return 0;
353323380e4dSAlexey Bayduraev
3534cbd7bfc7SAthira Rajeev perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
3535ca76d7d2SAdrian Hunter if (cpu.cpu == -1)
3536ca76d7d2SAdrian Hunter continue;
3537cbd7bfc7SAthira Rajeev /* Return ENODEV is input cpu is greater than max cpu */
3538cbd7bfc7SAthira Rajeev if ((unsigned long)cpu.cpu > mask->nbits)
3539cbd7bfc7SAthira Rajeev return -ENODEV;
354049bd97c2SSean Christopherson __set_bit(cpu.cpu, mask->bits);
35417954f716SAlexey Bayduraev }
35427954f716SAlexey Bayduraev
3543cbd7bfc7SAthira Rajeev return 0;
3544cbd7bfc7SAthira Rajeev }
3545cbd7bfc7SAthira Rajeev
record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask * mask,const char * mask_spec)3546f466e5edSAlexey Bayduraev static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const char *mask_spec)
3547f466e5edSAlexey Bayduraev {
3548f466e5edSAlexey Bayduraev struct perf_cpu_map *cpus;
3549f466e5edSAlexey Bayduraev
3550f466e5edSAlexey Bayduraev cpus = perf_cpu_map__new(mask_spec);
3551f466e5edSAlexey Bayduraev if (!cpus)
3552f466e5edSAlexey Bayduraev return -ENOMEM;
3553f466e5edSAlexey Bayduraev
3554f466e5edSAlexey Bayduraev bitmap_zero(mask->bits, mask->nbits);
3555cbd7bfc7SAthira Rajeev if (record__mmap_cpu_mask_init(mask, cpus))
3556cbd7bfc7SAthira Rajeev return -ENODEV;
3557cbd7bfc7SAthira Rajeev
3558f466e5edSAlexey Bayduraev perf_cpu_map__put(cpus);
3559f466e5edSAlexey Bayduraev
3560f466e5edSAlexey Bayduraev return 0;
3561f466e5edSAlexey Bayduraev }
3562f466e5edSAlexey Bayduraev
record__free_thread_masks(struct record * rec,int nr_threads)35637954f716SAlexey Bayduraev static void record__free_thread_masks(struct record *rec, int nr_threads)
35647954f716SAlexey Bayduraev {
35657954f716SAlexey Bayduraev int t;
35667954f716SAlexey Bayduraev
35677954f716SAlexey Bayduraev if (rec->thread_masks)
35687954f716SAlexey Bayduraev for (t = 0; t < nr_threads; t++)
35697954f716SAlexey Bayduraev record__thread_mask_free(&rec->thread_masks[t]);
35707954f716SAlexey Bayduraev
35717954f716SAlexey Bayduraev zfree(&rec->thread_masks);
35727954f716SAlexey Bayduraev }
35737954f716SAlexey Bayduraev
record__alloc_thread_masks(struct record * rec,int nr_threads,int nr_bits)35747954f716SAlexey Bayduraev static int record__alloc_thread_masks(struct record *rec, int nr_threads, int nr_bits)
35757954f716SAlexey Bayduraev {
35767954f716SAlexey Bayduraev int t, ret;
35777954f716SAlexey Bayduraev
35787954f716SAlexey Bayduraev rec->thread_masks = zalloc(nr_threads * sizeof(*(rec->thread_masks)));
35797954f716SAlexey Bayduraev if (!rec->thread_masks) {
35807954f716SAlexey Bayduraev pr_err("Failed to allocate thread masks\n");
35817954f716SAlexey Bayduraev return -ENOMEM;
35827954f716SAlexey Bayduraev }
35837954f716SAlexey Bayduraev
35847954f716SAlexey Bayduraev for (t = 0; t < nr_threads; t++) {
35857954f716SAlexey Bayduraev ret = record__thread_mask_alloc(&rec->thread_masks[t], nr_bits);
35867954f716SAlexey Bayduraev if (ret) {
35877954f716SAlexey Bayduraev pr_err("Failed to allocate thread masks[%d]\n", t);
35887954f716SAlexey Bayduraev goto out_free;
35897954f716SAlexey Bayduraev }
35907954f716SAlexey Bayduraev }
35917954f716SAlexey Bayduraev
35927954f716SAlexey Bayduraev return 0;
35937954f716SAlexey Bayduraev
35947954f716SAlexey Bayduraev out_free:
35957954f716SAlexey Bayduraev record__free_thread_masks(rec, nr_threads);
35967954f716SAlexey Bayduraev
35977954f716SAlexey Bayduraev return ret;
35987954f716SAlexey Bayduraev }
35997954f716SAlexey Bayduraev
record__init_thread_cpu_masks(struct record * rec,struct perf_cpu_map * cpus)360006380a84SAlexey Bayduraev static int record__init_thread_cpu_masks(struct record *rec, struct perf_cpu_map *cpus)
360106380a84SAlexey Bayduraev {
360206380a84SAlexey Bayduraev int t, ret, nr_cpus = perf_cpu_map__nr(cpus);
360306380a84SAlexey Bayduraev
360406380a84SAlexey Bayduraev ret = record__alloc_thread_masks(rec, nr_cpus, cpu__max_cpu().cpu);
360506380a84SAlexey Bayduraev if (ret)
360606380a84SAlexey Bayduraev return ret;
360706380a84SAlexey Bayduraev
360806380a84SAlexey Bayduraev rec->nr_threads = nr_cpus;
360906380a84SAlexey Bayduraev pr_debug("nr_threads: %d\n", rec->nr_threads);
361006380a84SAlexey Bayduraev
361106380a84SAlexey Bayduraev for (t = 0; t < rec->nr_threads; t++) {
361249bd97c2SSean Christopherson __set_bit(perf_cpu_map__cpu(cpus, t).cpu, rec->thread_masks[t].maps.bits);
361349bd97c2SSean Christopherson __set_bit(perf_cpu_map__cpu(cpus, t).cpu, rec->thread_masks[t].affinity.bits);
36147c0a6144SYang Jihong if (verbose > 0) {
361506380a84SAlexey Bayduraev pr_debug("thread_masks[%d]: ", t);
361606380a84SAlexey Bayduraev mmap_cpu_mask__scnprintf(&rec->thread_masks[t].maps, "maps");
361706380a84SAlexey Bayduraev pr_debug("thread_masks[%d]: ", t);
361806380a84SAlexey Bayduraev mmap_cpu_mask__scnprintf(&rec->thread_masks[t].affinity, "affinity");
361906380a84SAlexey Bayduraev }
362006380a84SAlexey Bayduraev }
362106380a84SAlexey Bayduraev
362206380a84SAlexey Bayduraev return 0;
362306380a84SAlexey Bayduraev }
362406380a84SAlexey Bayduraev
record__init_thread_masks_spec(struct record * rec,struct perf_cpu_map * cpus,const char ** maps_spec,const char ** affinity_spec,u32 nr_spec)3625f466e5edSAlexey Bayduraev static int record__init_thread_masks_spec(struct record *rec, struct perf_cpu_map *cpus,
3626f466e5edSAlexey Bayduraev const char **maps_spec, const char **affinity_spec,
3627f466e5edSAlexey Bayduraev u32 nr_spec)
3628f466e5edSAlexey Bayduraev {
3629f466e5edSAlexey Bayduraev u32 s;
3630f466e5edSAlexey Bayduraev int ret = 0, t = 0;
3631f466e5edSAlexey Bayduraev struct mmap_cpu_mask cpus_mask;
3632f466e5edSAlexey Bayduraev struct thread_mask thread_mask, full_mask, *thread_masks;
3633f466e5edSAlexey Bayduraev
3634f466e5edSAlexey Bayduraev ret = record__mmap_cpu_mask_alloc(&cpus_mask, cpu__max_cpu().cpu);
3635f466e5edSAlexey Bayduraev if (ret) {
3636f466e5edSAlexey Bayduraev pr_err("Failed to allocate CPUs mask\n");
3637f466e5edSAlexey Bayduraev return ret;
3638f466e5edSAlexey Bayduraev }
3639cbd7bfc7SAthira Rajeev
3640cbd7bfc7SAthira Rajeev ret = record__mmap_cpu_mask_init(&cpus_mask, cpus);
3641cbd7bfc7SAthira Rajeev if (ret) {
3642cbd7bfc7SAthira Rajeev pr_err("Failed to init cpu mask\n");
3643cbd7bfc7SAthira Rajeev goto out_free_cpu_mask;
3644cbd7bfc7SAthira Rajeev }
3645f466e5edSAlexey Bayduraev
3646f466e5edSAlexey Bayduraev ret = record__thread_mask_alloc(&full_mask, cpu__max_cpu().cpu);
3647f466e5edSAlexey Bayduraev if (ret) {
3648f466e5edSAlexey Bayduraev pr_err("Failed to allocate full mask\n");
3649f466e5edSAlexey Bayduraev goto out_free_cpu_mask;
3650f466e5edSAlexey Bayduraev }
3651f466e5edSAlexey Bayduraev
3652f466e5edSAlexey Bayduraev ret = record__thread_mask_alloc(&thread_mask, cpu__max_cpu().cpu);
3653f466e5edSAlexey Bayduraev if (ret) {
3654f466e5edSAlexey Bayduraev pr_err("Failed to allocate thread mask\n");
3655f466e5edSAlexey Bayduraev goto out_free_full_and_cpu_masks;
3656f466e5edSAlexey Bayduraev }
3657f466e5edSAlexey Bayduraev
3658f466e5edSAlexey Bayduraev for (s = 0; s < nr_spec; s++) {
3659f466e5edSAlexey Bayduraev ret = record__mmap_cpu_mask_init_spec(&thread_mask.maps, maps_spec[s]);
3660f466e5edSAlexey Bayduraev if (ret) {
3661f466e5edSAlexey Bayduraev pr_err("Failed to initialize maps thread mask\n");
3662f466e5edSAlexey Bayduraev goto out_free;
3663f466e5edSAlexey Bayduraev }
3664f466e5edSAlexey Bayduraev ret = record__mmap_cpu_mask_init_spec(&thread_mask.affinity, affinity_spec[s]);
3665f466e5edSAlexey Bayduraev if (ret) {
3666f466e5edSAlexey Bayduraev pr_err("Failed to initialize affinity thread mask\n");
3667f466e5edSAlexey Bayduraev goto out_free;
3668f466e5edSAlexey Bayduraev }
3669f466e5edSAlexey Bayduraev
3670f466e5edSAlexey Bayduraev /* ignore invalid CPUs but do not allow empty masks */
3671f466e5edSAlexey Bayduraev if (!bitmap_and(thread_mask.maps.bits, thread_mask.maps.bits,
3672f466e5edSAlexey Bayduraev cpus_mask.bits, thread_mask.maps.nbits)) {
3673f466e5edSAlexey Bayduraev pr_err("Empty maps mask: %s\n", maps_spec[s]);
3674f466e5edSAlexey Bayduraev ret = -EINVAL;
3675f466e5edSAlexey Bayduraev goto out_free;
3676f466e5edSAlexey Bayduraev }
3677f466e5edSAlexey Bayduraev if (!bitmap_and(thread_mask.affinity.bits, thread_mask.affinity.bits,
3678f466e5edSAlexey Bayduraev cpus_mask.bits, thread_mask.affinity.nbits)) {
3679f466e5edSAlexey Bayduraev pr_err("Empty affinity mask: %s\n", affinity_spec[s]);
3680f466e5edSAlexey Bayduraev ret = -EINVAL;
3681f466e5edSAlexey Bayduraev goto out_free;
3682f466e5edSAlexey Bayduraev }
3683f466e5edSAlexey Bayduraev
3684f466e5edSAlexey Bayduraev /* do not allow intersection with other masks (full_mask) */
3685f466e5edSAlexey Bayduraev if (bitmap_intersects(thread_mask.maps.bits, full_mask.maps.bits,
3686f466e5edSAlexey Bayduraev thread_mask.maps.nbits)) {
3687f466e5edSAlexey Bayduraev pr_err("Intersecting maps mask: %s\n", maps_spec[s]);
3688f466e5edSAlexey Bayduraev ret = -EINVAL;
3689f466e5edSAlexey Bayduraev goto out_free;
3690f466e5edSAlexey Bayduraev }
3691f466e5edSAlexey Bayduraev if (bitmap_intersects(thread_mask.affinity.bits, full_mask.affinity.bits,
3692f466e5edSAlexey Bayduraev thread_mask.affinity.nbits)) {
3693f466e5edSAlexey Bayduraev pr_err("Intersecting affinity mask: %s\n", affinity_spec[s]);
3694f466e5edSAlexey Bayduraev ret = -EINVAL;
3695f466e5edSAlexey Bayduraev goto out_free;
3696f466e5edSAlexey Bayduraev }
3697f466e5edSAlexey Bayduraev
3698f466e5edSAlexey Bayduraev bitmap_or(full_mask.maps.bits, full_mask.maps.bits,
3699f466e5edSAlexey Bayduraev thread_mask.maps.bits, full_mask.maps.nbits);
3700f466e5edSAlexey Bayduraev bitmap_or(full_mask.affinity.bits, full_mask.affinity.bits,
3701f466e5edSAlexey Bayduraev thread_mask.affinity.bits, full_mask.maps.nbits);
3702f466e5edSAlexey Bayduraev
3703f466e5edSAlexey Bayduraev thread_masks = realloc(rec->thread_masks, (t + 1) * sizeof(struct thread_mask));
3704f466e5edSAlexey Bayduraev if (!thread_masks) {
3705f466e5edSAlexey Bayduraev pr_err("Failed to reallocate thread masks\n");
3706f466e5edSAlexey Bayduraev ret = -ENOMEM;
3707f466e5edSAlexey Bayduraev goto out_free;
3708f466e5edSAlexey Bayduraev }
3709f466e5edSAlexey Bayduraev rec->thread_masks = thread_masks;
3710f466e5edSAlexey Bayduraev rec->thread_masks[t] = thread_mask;
37117c0a6144SYang Jihong if (verbose > 0) {
3712f466e5edSAlexey Bayduraev pr_debug("thread_masks[%d]: ", t);
3713f466e5edSAlexey Bayduraev mmap_cpu_mask__scnprintf(&rec->thread_masks[t].maps, "maps");
3714f466e5edSAlexey Bayduraev pr_debug("thread_masks[%d]: ", t);
3715f466e5edSAlexey Bayduraev mmap_cpu_mask__scnprintf(&rec->thread_masks[t].affinity, "affinity");
3716f466e5edSAlexey Bayduraev }
3717f466e5edSAlexey Bayduraev t++;
3718f466e5edSAlexey Bayduraev ret = record__thread_mask_alloc(&thread_mask, cpu__max_cpu().cpu);
3719f466e5edSAlexey Bayduraev if (ret) {
3720f466e5edSAlexey Bayduraev pr_err("Failed to allocate thread mask\n");
3721f466e5edSAlexey Bayduraev goto out_free_full_and_cpu_masks;
3722f466e5edSAlexey Bayduraev }
3723f466e5edSAlexey Bayduraev }
3724f466e5edSAlexey Bayduraev rec->nr_threads = t;
3725f466e5edSAlexey Bayduraev pr_debug("nr_threads: %d\n", rec->nr_threads);
3726f466e5edSAlexey Bayduraev if (!rec->nr_threads)
3727f466e5edSAlexey Bayduraev ret = -EINVAL;
3728f466e5edSAlexey Bayduraev
3729f466e5edSAlexey Bayduraev out_free:
3730f466e5edSAlexey Bayduraev record__thread_mask_free(&thread_mask);
3731f466e5edSAlexey Bayduraev out_free_full_and_cpu_masks:
3732f466e5edSAlexey Bayduraev record__thread_mask_free(&full_mask);
3733f466e5edSAlexey Bayduraev out_free_cpu_mask:
3734f466e5edSAlexey Bayduraev record__mmap_cpu_mask_free(&cpus_mask);
3735f466e5edSAlexey Bayduraev
3736f466e5edSAlexey Bayduraev return ret;
3737f466e5edSAlexey Bayduraev }
3738f466e5edSAlexey Bayduraev
record__init_thread_core_masks(struct record * rec,struct perf_cpu_map * cpus)3739f466e5edSAlexey Bayduraev static int record__init_thread_core_masks(struct record *rec, struct perf_cpu_map *cpus)
3740f466e5edSAlexey Bayduraev {
3741f466e5edSAlexey Bayduraev int ret;
3742f466e5edSAlexey Bayduraev struct cpu_topology *topo;
3743f466e5edSAlexey Bayduraev
3744f466e5edSAlexey Bayduraev topo = cpu_topology__new();
3745f466e5edSAlexey Bayduraev if (!topo) {
3746f466e5edSAlexey Bayduraev pr_err("Failed to allocate CPU topology\n");
3747f466e5edSAlexey Bayduraev return -ENOMEM;
3748f466e5edSAlexey Bayduraev }
3749f466e5edSAlexey Bayduraev
3750f466e5edSAlexey Bayduraev ret = record__init_thread_masks_spec(rec, cpus, topo->core_cpus_list,
3751f466e5edSAlexey Bayduraev topo->core_cpus_list, topo->core_cpus_lists);
3752f466e5edSAlexey Bayduraev cpu_topology__delete(topo);
3753f466e5edSAlexey Bayduraev
3754f466e5edSAlexey Bayduraev return ret;
3755f466e5edSAlexey Bayduraev }
3756f466e5edSAlexey Bayduraev
record__init_thread_package_masks(struct record * rec,struct perf_cpu_map * cpus)3757f466e5edSAlexey Bayduraev static int record__init_thread_package_masks(struct record *rec, struct perf_cpu_map *cpus)
3758f466e5edSAlexey Bayduraev {
3759f466e5edSAlexey Bayduraev int ret;
3760f466e5edSAlexey Bayduraev struct cpu_topology *topo;
3761f466e5edSAlexey Bayduraev
3762f466e5edSAlexey Bayduraev topo = cpu_topology__new();
3763f466e5edSAlexey Bayduraev if (!topo) {
3764f466e5edSAlexey Bayduraev pr_err("Failed to allocate CPU topology\n");
3765f466e5edSAlexey Bayduraev return -ENOMEM;
3766f466e5edSAlexey Bayduraev }
3767f466e5edSAlexey Bayduraev
3768f466e5edSAlexey Bayduraev ret = record__init_thread_masks_spec(rec, cpus, topo->package_cpus_list,
3769f466e5edSAlexey Bayduraev topo->package_cpus_list, topo->package_cpus_lists);
3770f466e5edSAlexey Bayduraev cpu_topology__delete(topo);
3771f466e5edSAlexey Bayduraev
3772f466e5edSAlexey Bayduraev return ret;
3773f466e5edSAlexey Bayduraev }
3774f466e5edSAlexey Bayduraev
record__init_thread_numa_masks(struct record * rec,struct perf_cpu_map * cpus)3775f466e5edSAlexey Bayduraev static int record__init_thread_numa_masks(struct record *rec, struct perf_cpu_map *cpus)
3776f466e5edSAlexey Bayduraev {
3777f466e5edSAlexey Bayduraev u32 s;
3778f466e5edSAlexey Bayduraev int ret;
3779f466e5edSAlexey Bayduraev const char **spec;
3780f466e5edSAlexey Bayduraev struct numa_topology *topo;
3781f466e5edSAlexey Bayduraev
3782f466e5edSAlexey Bayduraev topo = numa_topology__new();
3783f466e5edSAlexey Bayduraev if (!topo) {
3784f466e5edSAlexey Bayduraev pr_err("Failed to allocate NUMA topology\n");
3785f466e5edSAlexey Bayduraev return -ENOMEM;
3786f466e5edSAlexey Bayduraev }
3787f466e5edSAlexey Bayduraev
3788f466e5edSAlexey Bayduraev spec = zalloc(topo->nr * sizeof(char *));
3789f466e5edSAlexey Bayduraev if (!spec) {
3790f466e5edSAlexey Bayduraev pr_err("Failed to allocate NUMA spec\n");
3791f466e5edSAlexey Bayduraev ret = -ENOMEM;
3792f466e5edSAlexey Bayduraev goto out_delete_topo;
3793f466e5edSAlexey Bayduraev }
3794f466e5edSAlexey Bayduraev for (s = 0; s < topo->nr; s++)
3795f466e5edSAlexey Bayduraev spec[s] = topo->nodes[s].cpus;
3796f466e5edSAlexey Bayduraev
3797f466e5edSAlexey Bayduraev ret = record__init_thread_masks_spec(rec, cpus, spec, spec, topo->nr);
3798f466e5edSAlexey Bayduraev
3799f466e5edSAlexey Bayduraev zfree(&spec);
3800f466e5edSAlexey Bayduraev
3801f466e5edSAlexey Bayduraev out_delete_topo:
3802f466e5edSAlexey Bayduraev numa_topology__delete(topo);
3803f466e5edSAlexey Bayduraev
3804f466e5edSAlexey Bayduraev return ret;
3805f466e5edSAlexey Bayduraev }
3806f466e5edSAlexey Bayduraev
record__init_thread_user_masks(struct record * rec,struct perf_cpu_map * cpus)3807f466e5edSAlexey Bayduraev static int record__init_thread_user_masks(struct record *rec, struct perf_cpu_map *cpus)
3808f466e5edSAlexey Bayduraev {
3809f466e5edSAlexey Bayduraev int t, ret;
3810f466e5edSAlexey Bayduraev u32 s, nr_spec = 0;
3811f466e5edSAlexey Bayduraev char **maps_spec = NULL, **affinity_spec = NULL, **tmp_spec;
3812f466e5edSAlexey Bayduraev char *user_spec, *spec, *spec_ptr, *mask, *mask_ptr, *dup_mask = NULL;
3813f466e5edSAlexey Bayduraev
3814f466e5edSAlexey Bayduraev for (t = 0, user_spec = (char *)rec->opts.threads_user_spec; ; t++, user_spec = NULL) {
3815f466e5edSAlexey Bayduraev spec = strtok_r(user_spec, ":", &spec_ptr);
3816f466e5edSAlexey Bayduraev if (spec == NULL)
3817f466e5edSAlexey Bayduraev break;
3818f466e5edSAlexey Bayduraev pr_debug2("threads_spec[%d]: %s\n", t, spec);
3819f466e5edSAlexey Bayduraev mask = strtok_r(spec, "/", &mask_ptr);
3820f466e5edSAlexey Bayduraev if (mask == NULL)
3821f466e5edSAlexey Bayduraev break;
3822f466e5edSAlexey Bayduraev pr_debug2(" maps mask: %s\n", mask);
3823f466e5edSAlexey Bayduraev tmp_spec = realloc(maps_spec, (nr_spec + 1) * sizeof(char *));
3824f466e5edSAlexey Bayduraev if (!tmp_spec) {
3825f466e5edSAlexey Bayduraev pr_err("Failed to reallocate maps spec\n");
3826f466e5edSAlexey Bayduraev ret = -ENOMEM;
3827f466e5edSAlexey Bayduraev goto out_free;
3828f466e5edSAlexey Bayduraev }
3829f466e5edSAlexey Bayduraev maps_spec = tmp_spec;
3830f466e5edSAlexey Bayduraev maps_spec[nr_spec] = dup_mask = strdup(mask);
3831f466e5edSAlexey Bayduraev if (!maps_spec[nr_spec]) {
3832f466e5edSAlexey Bayduraev pr_err("Failed to allocate maps spec[%d]\n", nr_spec);
3833f466e5edSAlexey Bayduraev ret = -ENOMEM;
3834f466e5edSAlexey Bayduraev goto out_free;
3835f466e5edSAlexey Bayduraev }
3836f466e5edSAlexey Bayduraev mask = strtok_r(NULL, "/", &mask_ptr);
3837f466e5edSAlexey Bayduraev if (mask == NULL) {
3838f466e5edSAlexey Bayduraev pr_err("Invalid thread maps or affinity specs\n");
3839f466e5edSAlexey Bayduraev ret = -EINVAL;
3840f466e5edSAlexey Bayduraev goto out_free;
3841f466e5edSAlexey Bayduraev }
3842f466e5edSAlexey Bayduraev pr_debug2(" affinity mask: %s\n", mask);
3843f466e5edSAlexey Bayduraev tmp_spec = realloc(affinity_spec, (nr_spec + 1) * sizeof(char *));
3844f466e5edSAlexey Bayduraev if (!tmp_spec) {
3845f466e5edSAlexey Bayduraev pr_err("Failed to reallocate affinity spec\n");
3846f466e5edSAlexey Bayduraev ret = -ENOMEM;
3847f466e5edSAlexey Bayduraev goto out_free;
3848f466e5edSAlexey Bayduraev }
3849f466e5edSAlexey Bayduraev affinity_spec = tmp_spec;
3850f466e5edSAlexey Bayduraev affinity_spec[nr_spec] = strdup(mask);
3851f466e5edSAlexey Bayduraev if (!affinity_spec[nr_spec]) {
3852f466e5edSAlexey Bayduraev pr_err("Failed to allocate affinity spec[%d]\n", nr_spec);
3853f466e5edSAlexey Bayduraev ret = -ENOMEM;
3854f466e5edSAlexey Bayduraev goto out_free;
3855f466e5edSAlexey Bayduraev }
3856f466e5edSAlexey Bayduraev dup_mask = NULL;
3857f466e5edSAlexey Bayduraev nr_spec++;
3858f466e5edSAlexey Bayduraev }
3859f466e5edSAlexey Bayduraev
3860f466e5edSAlexey Bayduraev ret = record__init_thread_masks_spec(rec, cpus, (const char **)maps_spec,
3861f466e5edSAlexey Bayduraev (const char **)affinity_spec, nr_spec);
3862f466e5edSAlexey Bayduraev
3863f466e5edSAlexey Bayduraev out_free:
3864f466e5edSAlexey Bayduraev free(dup_mask);
3865f466e5edSAlexey Bayduraev for (s = 0; s < nr_spec; s++) {
3866f466e5edSAlexey Bayduraev if (maps_spec)
3867f466e5edSAlexey Bayduraev free(maps_spec[s]);
3868f466e5edSAlexey Bayduraev if (affinity_spec)
3869f466e5edSAlexey Bayduraev free(affinity_spec[s]);
3870f466e5edSAlexey Bayduraev }
3871f466e5edSAlexey Bayduraev free(affinity_spec);
3872f466e5edSAlexey Bayduraev free(maps_spec);
3873f466e5edSAlexey Bayduraev
3874f466e5edSAlexey Bayduraev return ret;
3875f466e5edSAlexey Bayduraev }
3876f466e5edSAlexey Bayduraev
record__init_thread_default_masks(struct record * rec,struct perf_cpu_map * cpus)38777954f716SAlexey Bayduraev static int record__init_thread_default_masks(struct record *rec, struct perf_cpu_map *cpus)
38787954f716SAlexey Bayduraev {
38797954f716SAlexey Bayduraev int ret;
38807954f716SAlexey Bayduraev
38817954f716SAlexey Bayduraev ret = record__alloc_thread_masks(rec, 1, cpu__max_cpu().cpu);
38827954f716SAlexey Bayduraev if (ret)
38837954f716SAlexey Bayduraev return ret;
38847954f716SAlexey Bayduraev
3885cbd7bfc7SAthira Rajeev if (record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus))
3886cbd7bfc7SAthira Rajeev return -ENODEV;
38877954f716SAlexey Bayduraev
38887954f716SAlexey Bayduraev rec->nr_threads = 1;
38897954f716SAlexey Bayduraev
38907954f716SAlexey Bayduraev return 0;
38917954f716SAlexey Bayduraev }
38927954f716SAlexey Bayduraev
record__init_thread_masks(struct record * rec)38937954f716SAlexey Bayduraev static int record__init_thread_masks(struct record *rec)
38947954f716SAlexey Bayduraev {
3895f466e5edSAlexey Bayduraev int ret = 0;
38967be1feddSAdrian Hunter struct perf_cpu_map *cpus = rec->evlist->core.all_cpus;
38977954f716SAlexey Bayduraev
389806380a84SAlexey Bayduraev if (!record__threads_enabled(rec))
38997954f716SAlexey Bayduraev return record__init_thread_default_masks(rec, cpus);
390006380a84SAlexey Bayduraev
39017be1feddSAdrian Hunter if (evlist__per_thread(rec->evlist)) {
390223380e4dSAlexey Bayduraev pr_err("--per-thread option is mutually exclusive to parallel streaming mode.\n");
390323380e4dSAlexey Bayduraev return -EINVAL;
390423380e4dSAlexey Bayduraev }
390523380e4dSAlexey Bayduraev
3906f466e5edSAlexey Bayduraev switch (rec->opts.threads_spec) {
3907f466e5edSAlexey Bayduraev case THREAD_SPEC__CPU:
3908f466e5edSAlexey Bayduraev ret = record__init_thread_cpu_masks(rec, cpus);
3909f466e5edSAlexey Bayduraev break;
3910f466e5edSAlexey Bayduraev case THREAD_SPEC__CORE:
3911f466e5edSAlexey Bayduraev ret = record__init_thread_core_masks(rec, cpus);
3912f466e5edSAlexey Bayduraev break;
3913f466e5edSAlexey Bayduraev case THREAD_SPEC__PACKAGE:
3914f466e5edSAlexey Bayduraev ret = record__init_thread_package_masks(rec, cpus);
3915f466e5edSAlexey Bayduraev break;
3916f466e5edSAlexey Bayduraev case THREAD_SPEC__NUMA:
3917f466e5edSAlexey Bayduraev ret = record__init_thread_numa_masks(rec, cpus);
3918f466e5edSAlexey Bayduraev break;
3919f466e5edSAlexey Bayduraev case THREAD_SPEC__USER:
3920f466e5edSAlexey Bayduraev ret = record__init_thread_user_masks(rec, cpus);
3921f466e5edSAlexey Bayduraev break;
3922f466e5edSAlexey Bayduraev default:
3923f466e5edSAlexey Bayduraev break;
3924f466e5edSAlexey Bayduraev }
3925f466e5edSAlexey Bayduraev
3926f466e5edSAlexey Bayduraev return ret;
39277954f716SAlexey Bayduraev }
39287954f716SAlexey Bayduraev
cmd_record(int argc,const char ** argv)3929b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
393086470930SIngo Molnar {
3931ef149c25SAdrian Hunter int err;
39328c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record;
393316ad2ffbSNamhyung Kim char errbuf[BUFSIZ];
393486470930SIngo Molnar
393567230479SArnaldo Carvalho de Melo setlocale(LC_ALL, "");
393667230479SArnaldo Carvalho de Melo
3937edc41a10SNamhyung Kim #ifndef HAVE_BPF_SKEL
3938edc41a10SNamhyung Kim # define set_nobuild(s, l, m, c) set_option_nobuild(record_options, s, l, m, c)
39399a2d5178SArnaldo Carvalho de Melo set_nobuild('\0', "off-cpu", "no BUILD_BPF_SKEL=1", true);
3940edc41a10SNamhyung Kim # undef set_nobuild
3941edc41a10SNamhyung Kim #endif
3942edc41a10SNamhyung Kim
39437adc363bSIan Rogers /* Disable eager loading of kernel symbols that adds overhead to perf record. */
39447adc363bSIan Rogers symbol_conf.lazy_load_kernel_maps = true;
39459d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS;
39469d2ed645SAlexey Budankov
39470f98b11cSJiri Olsa rec->evlist = evlist__new();
39483e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL)
3949361c99a6SArnaldo Carvalho de Melo return -ENOMEM;
3950361c99a6SArnaldo Carvalho de Melo
3951ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec);
3952ecc4c561SArnaldo Carvalho de Melo if (err)
3953ecc4c561SArnaldo Carvalho de Melo return err;
3954eb853e80SJiri Olsa
3955bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage,
3956a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION);
395768ba3235SNamhyung Kim if (quiet)
395868ba3235SNamhyung Kim perf_quiet_option();
3959483635a9SJiri Olsa
39607cc72553SJames Clark err = symbol__validate_sym_arguments();
39617cc72553SJames Clark if (err)
39627cc72553SJames Clark return err;
39637cc72553SJames Clark
39649bce13eaSJiri Olsa perf_debuginfod_setup(&record.debuginfod);
39659bce13eaSJiri Olsa
3966483635a9SJiri Olsa /* Make system wide (-a) the default target. */
3967602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target))
3968483635a9SJiri Olsa rec->opts.target.system_wide = true;
396986470930SIngo Molnar
3970bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) {
3971c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options,
3972c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode");
3973c7118369SNamhyung Kim
3974023695d9SStephane Eranian }
3975504c1ad1SAlexey Budankov
3976e29386c8SJiri Olsa if (rec->buildid_mmap) {
3977e29386c8SJiri Olsa if (!perf_can_record_build_id()) {
3978e29386c8SJiri Olsa pr_err("Failed: no support to record build id in mmap events, update your kernel.\n");
3979e29386c8SJiri Olsa err = -EINVAL;
3980e29386c8SJiri Olsa goto out_opts;
3981e29386c8SJiri Olsa }
3982e29386c8SJiri Olsa pr_debug("Enabling build id in mmap2 events.\n");
3983e29386c8SJiri Olsa /* Enable mmap build id synthesizing. */
3984e29386c8SJiri Olsa symbol_conf.buildid_mmap2 = true;
3985e29386c8SJiri Olsa /* Enable perf_event_attr::build_id bit. */
3986e29386c8SJiri Olsa rec->opts.build_id = true;
3987e29386c8SJiri Olsa /* Disable build id cache. */
3988e29386c8SJiri Olsa rec->no_buildid = true;
3989e29386c8SJiri Olsa }
3990e29386c8SJiri Olsa
39914f2abe91SNamhyung Kim if (rec->opts.record_cgroup && !perf_can_record_cgroup()) {
39924f2abe91SNamhyung Kim pr_err("Kernel has no cgroup sampling support.\n");
39934f2abe91SNamhyung Kim err = -EINVAL;
39944f2abe91SNamhyung Kim goto out_opts;
39954f2abe91SNamhyung Kim }
39964f2abe91SNamhyung Kim
3997f42c0ce5SAdrian Hunter if (rec->opts.kcore)
3998f42c0ce5SAdrian Hunter rec->opts.text_poke = true;
3999f42c0ce5SAdrian Hunter
400056f735ffSAlexey Bayduraev if (rec->opts.kcore || record__threads_enabled(rec))
4001eeb399b5SAdrian Hunter rec->data.is_dir = true;
4002eeb399b5SAdrian Hunter
4003b5f2511dSAlexey Bayduraev if (record__threads_enabled(rec)) {
4004b5f2511dSAlexey Bayduraev if (rec->opts.affinity != PERF_AFFINITY_SYS) {
4005b5f2511dSAlexey Bayduraev pr_err("--affinity option is mutually exclusive to parallel streaming mode.\n");
4006b5f2511dSAlexey Bayduraev goto out_opts;
4007b5f2511dSAlexey Bayduraev }
4008b5f2511dSAlexey Bayduraev if (record__aio_enabled(rec)) {
4009b5f2511dSAlexey Bayduraev pr_err("Asynchronous streaming mode (--aio) is mutually exclusive to parallel streaming mode.\n");
4010b5f2511dSAlexey Bayduraev goto out_opts;
4011b5f2511dSAlexey Bayduraev }
4012b5f2511dSAlexey Bayduraev }
4013b5f2511dSAlexey Bayduraev
4014504c1ad1SAlexey Budankov if (rec->opts.comp_level != 0) {
4015504c1ad1SAlexey Budankov pr_debug("Compression enabled, disabling build id collection at the end of the session.\n");
4016504c1ad1SAlexey Budankov rec->no_buildid = true;
4017504c1ad1SAlexey Budankov }
4018504c1ad1SAlexey Budankov
4019b757bb09SAdrian Hunter if (rec->opts.record_switch_events &&
4020b757bb09SAdrian Hunter !perf_can_record_switch_events()) {
4021c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n");
4022c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0);
4023a8fcbd26SAdrian Hunter err = -EINVAL;
4024a8fcbd26SAdrian Hunter goto out_opts;
4025b757bb09SAdrian Hunter }
4026023695d9SStephane Eranian
4027cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) {
4028cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0);
4029a8fcbd26SAdrian Hunter err = -EINVAL;
4030a8fcbd26SAdrian Hunter goto out_opts;
4031cb4e1ebbSJiri Olsa }
4032cb4e1ebbSJiri Olsa
4033bfacbe3bSJiri Olsa if (rec->switch_output.time) {
4034bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler);
4035bfacbe3bSJiri Olsa alarm(rec->switch_output.time);
4036bfacbe3bSJiri Olsa }
4037bfacbe3bSJiri Olsa
403803724b2eSAndi Kleen if (rec->switch_output.num_files) {
403903724b2eSAndi Kleen rec->switch_output.filenames = calloc(sizeof(char *),
404003724b2eSAndi Kleen rec->switch_output.num_files);
4041a8fcbd26SAdrian Hunter if (!rec->switch_output.filenames) {
4042a8fcbd26SAdrian Hunter err = -EINVAL;
4043a8fcbd26SAdrian Hunter goto out_opts;
4044a8fcbd26SAdrian Hunter }
404503724b2eSAndi Kleen }
404603724b2eSAndi Kleen
4047b5f2511dSAlexey Bayduraev if (rec->timestamp_filename && record__threads_enabled(rec)) {
4048b5f2511dSAlexey Bayduraev rec->timestamp_filename = false;
4049b5f2511dSAlexey Bayduraev pr_warning("WARNING: --timestamp-filename option is not available in parallel streaming mode.\n");
4050b5f2511dSAlexey Bayduraev }
4051b5f2511dSAlexey Bayduraev
40521b36c03eSAdrian Hunter /*
40531b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address
40541b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters().
40551b36c03eSAdrian Hunter */
40561b36c03eSAdrian Hunter symbol_conf.allow_aliases = true;
40571b36c03eSAdrian Hunter
40581b36c03eSAdrian Hunter symbol__init(NULL);
40591b36c03eSAdrian Hunter
40604b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec);
40611b36c03eSAdrian Hunter if (err)
40621b36c03eSAdrian Hunter goto out;
40631b36c03eSAdrian Hunter
40640aab2136SWang Nan if (dry_run)
40655c01ad60SAdrian Hunter goto out;
40660aab2136SWang Nan
4067ef149c25SAdrian Hunter err = -ENOMEM;
4068ef149c25SAdrian Hunter
40690c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) {
4070a1ac1d3cSStephane Eranian disable_buildid_cache();
4071dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) {
40720c1d46a8SWang Nan /*
40730c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid
40740c1d46a8SWang Nan * generation by default to reduce data file switching
40750c1d46a8SWang Nan * overhead. Still generate buildid if they are required
40760c1d46a8SWang Nan * explicitly using
40770c1d46a8SWang Nan *
407860437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \
40790c1d46a8SWang Nan * --no-no-buildid-cache
40800c1d46a8SWang Nan *
40810c1d46a8SWang Nan * Following code equals to:
40820c1d46a8SWang Nan *
40830c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) &&
40840c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set))
40850c1d46a8SWang Nan * disable_buildid_cache();
40860c1d46a8SWang Nan */
40870c1d46a8SWang Nan bool disable = true;
40880c1d46a8SWang Nan
40890c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid)
40900c1d46a8SWang Nan disable = false;
40910c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
40920c1d46a8SWang Nan disable = false;
40930c1d46a8SWang Nan if (disable) {
40940c1d46a8SWang Nan rec->no_buildid = true;
40950c1d46a8SWang Nan rec->no_buildid_cache = true;
40960c1d46a8SWang Nan disable_buildid_cache();
40970c1d46a8SWang Nan }
40980c1d46a8SWang Nan }
4099655000e7SArnaldo Carvalho de Melo
41004ea648aeSWang Nan if (record.opts.overwrite)
41014ea648aeSWang Nan record.opts.tail_synthesize = true;
41024ea648aeSWang Nan
4103b53a0755SJin Yao if (rec->evlist->core.nr_entries == 0) {
41047b100989SIan Rogers bool can_profile_kernel = perf_event_paranoid_check(1);
4105b53a0755SJin Yao
41067b100989SIan Rogers err = parse_event(rec->evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu");
41077b100989SIan Rogers if (err)
4108394c01edSAdrian Hunter goto out;
4109bbd36e5eSPeter Zijlstra }
411086470930SIngo Molnar
411169e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set)
411269e7e5b0SAdrian Hunter rec->opts.no_inherit = true;
411369e7e5b0SAdrian Hunter
4114602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target);
411516ad2ffbSNamhyung Kim if (err) {
4116602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
4117c3dec27bSJiri Olsa ui__warning("%s\n", errbuf);
411816ad2ffbSNamhyung Kim }
41194bd0f2d2SNamhyung Kim
4120602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target);
412116ad2ffbSNamhyung Kim if (err) {
412216ad2ffbSNamhyung Kim int saved_errno = errno;
412316ad2ffbSNamhyung Kim
4124602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
41253780f488SNamhyung Kim ui__error("%s", errbuf);
412616ad2ffbSNamhyung Kim
412716ad2ffbSNamhyung Kim err = -saved_errno;
4128394c01edSAdrian Hunter goto out;
412916ad2ffbSNamhyung Kim }
41300d37aa34SArnaldo Carvalho de Melo
4131ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */
4132ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
413323dc4f15SJiri Olsa
41345ac72634SIan Rogers evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list);
41351d3351e6SJin Yao
41367248e308SAlexandre Truong if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP)
41377248e308SAlexandre Truong arch__add_leaf_frame_record_opts(&rec->opts);
41387248e308SAlexandre Truong
413916ad2ffbSNamhyung Kim err = -ENOMEM;
41401bf7d836SMartin Liška if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0) {
41411bf7d836SMartin Liška if (rec->opts.target.pid != NULL) {
41421bf7d836SMartin Liška pr_err("Couldn't create thread/CPU maps: %s\n",
41431bf7d836SMartin Liška errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
41441bf7d836SMartin Liška goto out;
41451bf7d836SMartin Liška }
41461bf7d836SMartin Liška else
4147dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options);
41481bf7d836SMartin Liška }
414969aad6f1SArnaldo Carvalho de Melo
4150ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
4151ef149c25SAdrian Hunter if (err)
4152394c01edSAdrian Hunter goto out;
4153ef149c25SAdrian Hunter
41546156681bSNamhyung Kim /*
41556156681bSNamhyung Kim * We take all buildids when the file contains
41566156681bSNamhyung Kim * AUX area tracing data because we do not decode the
41576156681bSNamhyung Kim * trace because it would take too long.
41586156681bSNamhyung Kim */
41596156681bSNamhyung Kim if (rec->opts.full_auxtrace)
41606156681bSNamhyung Kim rec->buildid_all = true;
41616156681bSNamhyung Kim
4162246eba8eSAdrian Hunter if (rec->opts.text_poke) {
4163246eba8eSAdrian Hunter err = record__config_text_poke(rec->evlist);
4164246eba8eSAdrian Hunter if (err) {
4165246eba8eSAdrian Hunter pr_err("record__config_text_poke failed, error %d\n", err);
4166246eba8eSAdrian Hunter goto out;
4167246eba8eSAdrian Hunter }
4168246eba8eSAdrian Hunter }
4169246eba8eSAdrian Hunter
4170edc41a10SNamhyung Kim if (rec->off_cpu) {
4171edc41a10SNamhyung Kim err = record__config_off_cpu(rec);
4172edc41a10SNamhyung Kim if (err) {
4173edc41a10SNamhyung Kim pr_err("record__config_off_cpu failed, error %d\n", err);
4174edc41a10SNamhyung Kim goto out;
4175edc41a10SNamhyung Kim }
4176edc41a10SNamhyung Kim }
4177edc41a10SNamhyung Kim
4178b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) {
417939d17dacSArnaldo Carvalho de Melo err = -EINVAL;
4180394c01edSAdrian Hunter goto out;
41817e4ff9e3SMike Galbraith }
41827e4ff9e3SMike Galbraith
4183aa4158e3SYang Jihong err = record__config_tracking_events(rec);
4184aa4158e3SYang Jihong if (err) {
4185aa4158e3SYang Jihong pr_err("record__config_tracking_events failed, error %d\n", err);
4186aa4158e3SYang Jihong goto out;
4187aa4158e3SYang Jihong }
4188aa4158e3SYang Jihong
41897954f716SAlexey Bayduraev err = record__init_thread_masks(rec);
41907954f716SAlexey Bayduraev if (err) {
41917954f716SAlexey Bayduraev pr_err("Failed to initialize parallel data streaming masks\n");
41927954f716SAlexey Bayduraev goto out;
41937954f716SAlexey Bayduraev }
41947954f716SAlexey Bayduraev
419593f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max)
419693f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max;
41975d7f4116SAlexey Budankov pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks);
4198d3d1af6fSAlexey Budankov
41999d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
4200470530bbSAlexey Budankov pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
42019d2ed645SAlexey Budankov
420251255a8aSAlexey Budankov if (rec->opts.comp_level > comp_level_max)
420351255a8aSAlexey Budankov rec->opts.comp_level = comp_level_max;
420451255a8aSAlexey Budankov pr_debug("comp level: %d\n", rec->opts.comp_level);
420551255a8aSAlexey Budankov
4206d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv);
4207394c01edSAdrian Hunter out:
4208c12995a5SJiri Olsa evlist__delete(rec->evlist);
4209d65a458bSArnaldo Carvalho de Melo symbol__exit();
4210ef149c25SAdrian Hunter auxtrace_record__free(rec->itr);
4211a8fcbd26SAdrian Hunter out_opts:
42127954f716SAlexey Bayduraev record__free_thread_masks(rec, rec->nr_threads);
42137954f716SAlexey Bayduraev rec->nr_threads = 0;
4214ee7fe31eSAdrian Hunter evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close);
421539d17dacSArnaldo Carvalho de Melo return err;
421686470930SIngo Molnar }
42172dd6d8a1SAdrian Hunter
snapshot_sig_handler(int sig __maybe_unused)42182dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
42192dd6d8a1SAdrian Hunter {
4220dc0c6127SJiri Olsa struct record *rec = &record;
4221dc0c6127SJiri Olsa
4222d20aff15SAdrian Hunter hit_auxtrace_snapshot_trigger(rec);
42233c1cb7e3SWang Nan
4224dc0c6127SJiri Olsa if (switch_output_signal(rec))
42253c1cb7e3SWang Nan trigger_hit(&switch_output_trigger);
42262dd6d8a1SAdrian Hunter }
4227bfacbe3bSJiri Olsa
alarm_sig_handler(int sig __maybe_unused)4228bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
4229bfacbe3bSJiri Olsa {
4230bfacbe3bSJiri Olsa struct record *rec = &record;
4231bfacbe3bSJiri Olsa
4232bfacbe3bSJiri Olsa if (switch_output_time(rec))
4233bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger);
4234bfacbe3bSJiri Olsa }
4235