spi-topcliff-pch: supports a spi mode setup and bit order setup by IO control
[zen-stable.git] / tools / perf / builtin-record.c
blob227b6ae99785118066a7184cc4cb66f27d38c841
1 /*
2 * builtin-record.c
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
7 */
8 #define _FILE_OFFSET_BITS 64
10 #include "builtin.h"
12 #include "perf.h"
14 #include "util/build-id.h"
15 #include "util/util.h"
16 #include "util/parse-options.h"
17 #include "util/parse-events.h"
19 #include "util/header.h"
20 #include "util/event.h"
21 #include "util/evlist.h"
22 #include "util/evsel.h"
23 #include "util/debug.h"
24 #include "util/session.h"
25 #include "util/tool.h"
26 #include "util/symbol.h"
27 #include "util/cpumap.h"
28 #include "util/thread_map.h"
30 #include <unistd.h>
31 #include <sched.h>
32 #include <sys/mman.h>
34 enum write_mode_t {
35 WRITE_FORCE,
36 WRITE_APPEND
39 struct perf_record {
40 struct perf_tool tool;
41 struct perf_record_opts opts;
42 u64 bytes_written;
43 const char *output_name;
44 struct perf_evlist *evlist;
45 struct perf_session *session;
46 const char *progname;
47 int output;
48 unsigned int page_size;
49 int realtime_prio;
50 enum write_mode_t write_mode;
51 bool no_buildid;
52 bool no_buildid_cache;
53 bool force;
54 bool file_new;
55 bool append_file;
56 long samples;
57 off_t post_processing_offset;
60 static void advance_output(struct perf_record *rec, size_t size)
62 rec->bytes_written += size;
65 static void write_output(struct perf_record *rec, void *buf, size_t size)
67 while (size) {
68 int ret = write(rec->output, buf, size);
70 if (ret < 0)
71 die("failed to write");
73 size -= ret;
74 buf += ret;
76 rec->bytes_written += ret;
80 static int process_synthesized_event(struct perf_tool *tool,
81 union perf_event *event,
82 struct perf_sample *sample __used,
83 struct machine *machine __used)
85 struct perf_record *rec = container_of(tool, struct perf_record, tool);
86 write_output(rec, event, event->header.size);
87 return 0;
90 static void perf_record__mmap_read(struct perf_record *rec,
91 struct perf_mmap *md)
93 unsigned int head = perf_mmap__read_head(md);
94 unsigned int old = md->prev;
95 unsigned char *data = md->base + rec->page_size;
96 unsigned long size;
97 void *buf;
99 if (old == head)
100 return;
102 rec->samples++;
104 size = head - old;
106 if ((old & md->mask) + size != (head & md->mask)) {
107 buf = &data[old & md->mask];
108 size = md->mask + 1 - (old & md->mask);
109 old += size;
111 write_output(rec, buf, size);
114 buf = &data[old & md->mask];
115 size = head - old;
116 old += size;
118 write_output(rec, buf, size);
120 md->prev = old;
121 perf_mmap__write_tail(md, old);
124 static volatile int done = 0;
125 static volatile int signr = -1;
126 static volatile int child_finished = 0;
128 static void sig_handler(int sig)
130 if (sig == SIGCHLD)
131 child_finished = 1;
133 done = 1;
134 signr = sig;
137 static void perf_record__sig_exit(int exit_status __used, void *arg)
139 struct perf_record *rec = arg;
140 int status;
142 if (rec->evlist->workload.pid > 0) {
143 if (!child_finished)
144 kill(rec->evlist->workload.pid, SIGTERM);
146 wait(&status);
147 if (WIFSIGNALED(status))
148 psignal(WTERMSIG(status), rec->progname);
151 if (signr == -1 || signr == SIGUSR1)
152 return;
154 signal(signr, SIG_DFL);
155 kill(getpid(), signr);
158 static bool perf_evlist__equal(struct perf_evlist *evlist,
159 struct perf_evlist *other)
161 struct perf_evsel *pos, *pair;
163 if (evlist->nr_entries != other->nr_entries)
164 return false;
166 pair = list_entry(other->entries.next, struct perf_evsel, node);
168 list_for_each_entry(pos, &evlist->entries, node) {
169 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
170 return false;
171 pair = list_entry(pair->node.next, struct perf_evsel, node);
174 return true;
177 static void perf_record__open(struct perf_record *rec)
179 struct perf_evsel *pos, *first;
180 struct perf_evlist *evlist = rec->evlist;
181 struct perf_session *session = rec->session;
182 struct perf_record_opts *opts = &rec->opts;
184 first = list_entry(evlist->entries.next, struct perf_evsel, node);
186 perf_evlist__config_attrs(evlist, opts);
188 list_for_each_entry(pos, &evlist->entries, node) {
189 struct perf_event_attr *attr = &pos->attr;
190 struct xyarray *group_fd = NULL;
192 * Check if parse_single_tracepoint_event has already asked for
193 * PERF_SAMPLE_TIME.
195 * XXX this is kludgy but short term fix for problems introduced by
196 * eac23d1c that broke 'perf script' by having different sample_types
197 * when using multiple tracepoint events when we use a perf binary
198 * that tries to use sample_id_all on an older kernel.
200 * We need to move counter creation to perf_session, support
201 * different sample_types, etc.
203 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
205 if (opts->group && pos != first)
206 group_fd = first->fd;
207 fallback_missing_features:
208 if (opts->exclude_guest_missing)
209 attr->exclude_guest = attr->exclude_host = 0;
210 retry_sample_id:
211 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
212 try_again:
213 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
214 opts->group, group_fd) < 0) {
215 int err = errno;
217 if (err == EPERM || err == EACCES) {
218 ui__error_paranoid();
219 exit(EXIT_FAILURE);
220 } else if (err == ENODEV && opts->cpu_list) {
221 die("No such device - did you specify"
222 " an out-of-range profile CPU?\n");
223 } else if (err == EINVAL) {
224 if (!opts->exclude_guest_missing &&
225 (attr->exclude_guest || attr->exclude_host)) {
226 pr_debug("Old kernel, cannot exclude "
227 "guest or host samples.\n");
228 opts->exclude_guest_missing = true;
229 goto fallback_missing_features;
230 } else if (opts->sample_id_all_avail) {
232 * Old kernel, no attr->sample_id_type_all field
234 opts->sample_id_all_avail = false;
235 if (!opts->sample_time && !opts->raw_samples && !time_needed)
236 attr->sample_type &= ~PERF_SAMPLE_TIME;
238 goto retry_sample_id;
243 * If it's cycles then fall back to hrtimer
244 * based cpu-clock-tick sw counter, which
245 * is always available even if no PMU support:
247 if (attr->type == PERF_TYPE_HARDWARE
248 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
250 if (verbose)
251 ui__warning("The cycles event is not supported, "
252 "trying to fall back to cpu-clock-ticks\n");
253 attr->type = PERF_TYPE_SOFTWARE;
254 attr->config = PERF_COUNT_SW_CPU_CLOCK;
255 goto try_again;
258 if (err == ENOENT) {
259 ui__warning("The %s event is not supported.\n",
260 event_name(pos));
261 exit(EXIT_FAILURE);
264 printf("\n");
265 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
266 err, strerror(err));
268 #if defined(__i386__) || defined(__x86_64__)
269 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
270 die("No hardware sampling interrupt available."
271 " No APIC? If so then you can boot the kernel"
272 " with the \"lapic\" boot parameter to"
273 " force-enable it.\n");
274 #endif
276 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
280 if (perf_evlist__set_filters(evlist)) {
281 error("failed to set filter with %d (%s)\n", errno,
282 strerror(errno));
283 exit(-1);
286 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
287 if (errno == EPERM)
288 die("Permission error mapping pages.\n"
289 "Consider increasing "
290 "/proc/sys/kernel/perf_event_mlock_kb,\n"
291 "or try again with a smaller value of -m/--mmap_pages.\n"
292 "(current value: %d)\n", opts->mmap_pages);
293 else if (!is_power_of_2(opts->mmap_pages))
294 die("--mmap_pages/-m value must be a power of two.");
296 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
299 if (rec->file_new)
300 session->evlist = evlist;
301 else {
302 if (!perf_evlist__equal(session->evlist, evlist)) {
303 fprintf(stderr, "incompatible append\n");
304 exit(-1);
308 perf_session__update_sample_type(session);
311 static int process_buildids(struct perf_record *rec)
313 u64 size = lseek(rec->output, 0, SEEK_CUR);
315 if (size == 0)
316 return 0;
318 rec->session->fd = rec->output;
319 return __perf_session__process_events(rec->session, rec->post_processing_offset,
320 size - rec->post_processing_offset,
321 size, &build_id__mark_dso_hit_ops);
324 static void perf_record__exit(int status __used, void *arg)
326 struct perf_record *rec = arg;
328 if (!rec->opts.pipe_output) {
329 rec->session->header.data_size += rec->bytes_written;
331 if (!rec->no_buildid)
332 process_buildids(rec);
333 perf_session__write_header(rec->session, rec->evlist,
334 rec->output, true);
335 perf_session__delete(rec->session);
336 perf_evlist__delete(rec->evlist);
337 symbol__exit();
341 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
343 int err;
344 struct perf_tool *tool = data;
346 if (machine__is_host(machine))
347 return;
350 *As for guest kernel when processing subcommand record&report,
351 *we arrange module mmap prior to guest kernel mmap and trigger
352 *a preload dso because default guest module symbols are loaded
353 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
354 *method is used to avoid symbol missing when the first addr is
355 *in module instead of in guest kernel.
357 err = perf_event__synthesize_modules(tool, process_synthesized_event,
358 machine);
359 if (err < 0)
360 pr_err("Couldn't record guest kernel [%d]'s reference"
361 " relocation symbol.\n", machine->pid);
364 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
365 * have no _text sometimes.
367 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
368 machine, "_text");
369 if (err < 0)
370 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
371 machine, "_stext");
372 if (err < 0)
373 pr_err("Couldn't record guest kernel [%d]'s reference"
374 " relocation symbol.\n", machine->pid);
377 static struct perf_event_header finished_round_event = {
378 .size = sizeof(struct perf_event_header),
379 .type = PERF_RECORD_FINISHED_ROUND,
382 static void perf_record__mmap_read_all(struct perf_record *rec)
384 int i;
386 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
387 if (rec->evlist->mmap[i].base)
388 perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
391 if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
392 write_output(rec, &finished_round_event, sizeof(finished_round_event));
395 static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
397 struct stat st;
398 int flags;
399 int err, output;
400 unsigned long waking = 0;
401 const bool forks = argc > 0;
402 struct machine *machine;
403 struct perf_tool *tool = &rec->tool;
404 struct perf_record_opts *opts = &rec->opts;
405 struct perf_evlist *evsel_list = rec->evlist;
406 const char *output_name = rec->output_name;
407 struct perf_session *session;
409 rec->progname = argv[0];
411 rec->page_size = sysconf(_SC_PAGE_SIZE);
413 on_exit(perf_record__sig_exit, rec);
414 signal(SIGCHLD, sig_handler);
415 signal(SIGINT, sig_handler);
416 signal(SIGUSR1, sig_handler);
418 if (!output_name) {
419 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
420 opts->pipe_output = true;
421 else
422 rec->output_name = output_name = "perf.data";
424 if (output_name) {
425 if (!strcmp(output_name, "-"))
426 opts->pipe_output = true;
427 else if (!stat(output_name, &st) && st.st_size) {
428 if (rec->write_mode == WRITE_FORCE) {
429 char oldname[PATH_MAX];
430 snprintf(oldname, sizeof(oldname), "%s.old",
431 output_name);
432 unlink(oldname);
433 rename(output_name, oldname);
435 } else if (rec->write_mode == WRITE_APPEND) {
436 rec->write_mode = WRITE_FORCE;
440 flags = O_CREAT|O_RDWR;
441 if (rec->write_mode == WRITE_APPEND)
442 rec->file_new = 0;
443 else
444 flags |= O_TRUNC;
446 if (opts->pipe_output)
447 output = STDOUT_FILENO;
448 else
449 output = open(output_name, flags, S_IRUSR | S_IWUSR);
450 if (output < 0) {
451 perror("failed to create output file");
452 exit(-1);
455 rec->output = output;
457 session = perf_session__new(output_name, O_WRONLY,
458 rec->write_mode == WRITE_FORCE, false, NULL);
459 if (session == NULL) {
460 pr_err("Not enough memory for reading perf file header\n");
461 return -1;
464 rec->session = session;
466 if (!rec->no_buildid)
467 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
469 if (!rec->file_new) {
470 err = perf_session__read_header(session, output);
471 if (err < 0)
472 goto out_delete_session;
475 if (have_tracepoints(&evsel_list->entries))
476 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
478 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
479 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
480 perf_header__set_feat(&session->header, HEADER_ARCH);
481 perf_header__set_feat(&session->header, HEADER_CPUDESC);
482 perf_header__set_feat(&session->header, HEADER_NRCPUS);
483 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
484 perf_header__set_feat(&session->header, HEADER_CMDLINE);
485 perf_header__set_feat(&session->header, HEADER_VERSION);
486 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
487 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
488 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
489 perf_header__set_feat(&session->header, HEADER_CPUID);
491 if (forks) {
492 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
493 if (err < 0) {
494 pr_err("Couldn't run the workload!\n");
495 goto out_delete_session;
499 perf_record__open(rec);
502 * perf_session__delete(session) will be called at perf_record__exit()
504 on_exit(perf_record__exit, rec);
506 if (opts->pipe_output) {
507 err = perf_header__write_pipe(output);
508 if (err < 0)
509 return err;
510 } else if (rec->file_new) {
511 err = perf_session__write_header(session, evsel_list,
512 output, false);
513 if (err < 0)
514 return err;
517 if (!rec->no_buildid
518 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
519 pr_err("Couldn't generate buildids. "
520 "Use --no-buildid to profile anyway.\n");
521 return -1;
524 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
526 machine = perf_session__find_host_machine(session);
527 if (!machine) {
528 pr_err("Couldn't find native kernel information.\n");
529 return -1;
532 if (opts->pipe_output) {
533 err = perf_event__synthesize_attrs(tool, session,
534 process_synthesized_event);
535 if (err < 0) {
536 pr_err("Couldn't synthesize attrs.\n");
537 return err;
540 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
541 machine);
542 if (err < 0) {
543 pr_err("Couldn't synthesize event_types.\n");
544 return err;
547 if (have_tracepoints(&evsel_list->entries)) {
549 * FIXME err <= 0 here actually means that
550 * there were no tracepoints so its not really
551 * an error, just that we don't need to
552 * synthesize anything. We really have to
553 * return this more properly and also
554 * propagate errors that now are calling die()
556 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
557 process_synthesized_event);
558 if (err <= 0) {
559 pr_err("Couldn't record tracing data.\n");
560 return err;
562 advance_output(rec, err);
566 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
567 machine, "_text");
568 if (err < 0)
569 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
570 machine, "_stext");
571 if (err < 0)
572 pr_err("Couldn't record kernel reference relocation symbol\n"
573 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
574 "Check /proc/kallsyms permission or run as root.\n");
576 err = perf_event__synthesize_modules(tool, process_synthesized_event,
577 machine);
578 if (err < 0)
579 pr_err("Couldn't record kernel module information.\n"
580 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
581 "Check /proc/modules permission or run as root.\n");
583 if (perf_guest)
584 perf_session__process_machines(session, tool,
585 perf_event__synthesize_guest_os);
587 if (!opts->system_wide)
588 perf_event__synthesize_thread_map(tool, evsel_list->threads,
589 process_synthesized_event,
590 machine);
591 else
592 perf_event__synthesize_threads(tool, process_synthesized_event,
593 machine);
595 if (rec->realtime_prio) {
596 struct sched_param param;
598 param.sched_priority = rec->realtime_prio;
599 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
600 pr_err("Could not set realtime priority.\n");
601 exit(-1);
605 perf_evlist__enable(evsel_list);
608 * Let the child rip
610 if (forks)
611 perf_evlist__start_workload(evsel_list);
613 for (;;) {
614 int hits = rec->samples;
616 perf_record__mmap_read_all(rec);
618 if (hits == rec->samples) {
619 if (done)
620 break;
621 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
622 waking++;
625 if (done)
626 perf_evlist__disable(evsel_list);
629 if (quiet || signr == SIGUSR1)
630 return 0;
632 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
635 * Approximate RIP event size: 24 bytes.
637 fprintf(stderr,
638 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
639 (double)rec->bytes_written / 1024.0 / 1024.0,
640 output_name,
641 rec->bytes_written / 24);
643 return 0;
645 out_delete_session:
646 perf_session__delete(session);
647 return err;
650 static const char * const record_usage[] = {
651 "perf record [<options>] [<command>]",
652 "perf record [<options>] -- <command> [<options>]",
653 NULL
657 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
658 * because we need to have access to it in perf_record__exit, that is called
659 * after cmd_record() exits, but since record_options need to be accessible to
660 * builtin-script, leave it here.
662 * At least we don't ouch it in all the other functions here directly.
664 * Just say no to tons of global variables, sigh.
666 static struct perf_record record = {
667 .opts = {
668 .target_pid = -1,
669 .target_tid = -1,
670 .mmap_pages = UINT_MAX,
671 .user_freq = UINT_MAX,
672 .user_interval = ULLONG_MAX,
673 .freq = 1000,
674 .sample_id_all_avail = true,
676 .write_mode = WRITE_FORCE,
677 .file_new = true,
681 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
682 * with it and switch to use the library functions in perf_evlist that came
683 * from builtin-record.c, i.e. use perf_record_opts,
684 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
685 * using pipes, etc.
687 const struct option record_options[] = {
688 OPT_CALLBACK('e', "event", &record.evlist, "event",
689 "event selector. use 'perf list' to list available events",
690 parse_events_option),
691 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
692 "event filter", parse_filter),
693 OPT_INTEGER('p', "pid", &record.opts.target_pid,
694 "record events on existing process id"),
695 OPT_INTEGER('t', "tid", &record.opts.target_tid,
696 "record events on existing thread id"),
697 OPT_INTEGER('r', "realtime", &record.realtime_prio,
698 "collect data with this RT SCHED_FIFO priority"),
699 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
700 "collect data without buffering"),
701 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
702 "collect raw sample records from all opened counters"),
703 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
704 "system-wide collection from all CPUs"),
705 OPT_BOOLEAN('A', "append", &record.append_file,
706 "append to the output file to do incremental profiling"),
707 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
708 "list of cpus to monitor"),
709 OPT_BOOLEAN('f', "force", &record.force,
710 "overwrite existing data file (deprecated)"),
711 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
712 OPT_STRING('o', "output", &record.output_name, "file",
713 "output file name"),
714 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
715 "child tasks do not inherit counters"),
716 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
717 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
718 "number of mmap data pages"),
719 OPT_BOOLEAN(0, "group", &record.opts.group,
720 "put the counters into a counter group"),
721 OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
722 "do call-graph (stack chain/backtrace) recording"),
723 OPT_INCR('v', "verbose", &verbose,
724 "be more verbose (show counter open errors, etc)"),
725 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
726 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
727 "per thread counts"),
728 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
729 "Sample addresses"),
730 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
731 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
732 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
733 "don't sample"),
734 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
735 "do not update the buildid cache"),
736 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
737 "do not collect buildids in perf.data"),
738 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
739 "monitor event in cgroup name only",
740 parse_cgroups),
741 OPT_END()
744 int cmd_record(int argc, const char **argv, const char *prefix __used)
746 int err = -ENOMEM;
747 struct perf_evsel *pos;
748 struct perf_evlist *evsel_list;
749 struct perf_record *rec = &record;
751 perf_header__set_cmdline(argc, argv);
753 evsel_list = perf_evlist__new(NULL, NULL);
754 if (evsel_list == NULL)
755 return -ENOMEM;
757 rec->evlist = evsel_list;
759 argc = parse_options(argc, argv, record_options, record_usage,
760 PARSE_OPT_STOP_AT_NON_OPTION);
761 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
762 !rec->opts.system_wide && !rec->opts.cpu_list)
763 usage_with_options(record_usage, record_options);
765 if (rec->force && rec->append_file) {
766 fprintf(stderr, "Can't overwrite and append at the same time."
767 " You need to choose between -f and -A");
768 usage_with_options(record_usage, record_options);
769 } else if (rec->append_file) {
770 rec->write_mode = WRITE_APPEND;
771 } else {
772 rec->write_mode = WRITE_FORCE;
775 if (nr_cgroups && !rec->opts.system_wide) {
776 fprintf(stderr, "cgroup monitoring only available in"
777 " system-wide mode\n");
778 usage_with_options(record_usage, record_options);
781 symbol__init();
783 if (symbol_conf.kptr_restrict)
784 pr_warning(
785 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
786 "check /proc/sys/kernel/kptr_restrict.\n\n"
787 "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
788 "file is not found in the buildid cache or in the vmlinux path.\n\n"
789 "Samples in kernel modules won't be resolved at all.\n\n"
790 "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
791 "even with a suitable vmlinux or kallsyms file.\n\n");
793 if (rec->no_buildid_cache || rec->no_buildid)
794 disable_buildid_cache();
796 if (evsel_list->nr_entries == 0 &&
797 perf_evlist__add_default(evsel_list) < 0) {
798 pr_err("Not enough memory for event selector list\n");
799 goto out_symbol_exit;
802 if (rec->opts.target_pid != -1)
803 rec->opts.target_tid = rec->opts.target_pid;
805 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
806 rec->opts.target_tid, rec->opts.cpu_list) < 0)
807 usage_with_options(record_usage, record_options);
809 list_for_each_entry(pos, &evsel_list->entries, node) {
810 if (perf_header__push_event(pos->attr.config, event_name(pos)))
811 goto out_free_fd;
814 if (rec->opts.user_interval != ULLONG_MAX)
815 rec->opts.default_interval = rec->opts.user_interval;
816 if (rec->opts.user_freq != UINT_MAX)
817 rec->opts.freq = rec->opts.user_freq;
820 * User specified count overrides default frequency.
822 if (rec->opts.default_interval)
823 rec->opts.freq = 0;
824 else if (rec->opts.freq) {
825 rec->opts.default_interval = rec->opts.freq;
826 } else {
827 fprintf(stderr, "frequency and count are zero, aborting\n");
828 err = -EINVAL;
829 goto out_free_fd;
832 err = __cmd_record(&record, argc, argv);
833 out_free_fd:
834 perf_evlist__delete_maps(evsel_list);
835 out_symbol_exit:
836 symbol__exit();
837 return err;