diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 168 |
1 files changed, 63 insertions, 105 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d04651484640..15280b5e5574 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -24,12 +24,13 @@ | |||
24 | #include "util/symbol.h" | 24 | #include "util/symbol.h" |
25 | #include "util/cpumap.h" | 25 | #include "util/cpumap.h" |
26 | #include "util/thread_map.h" | 26 | #include "util/thread_map.h" |
27 | #include "util/data.h" | ||
27 | 28 | ||
28 | #include <unistd.h> | 29 | #include <unistd.h> |
29 | #include <sched.h> | 30 | #include <sched.h> |
30 | #include <sys/mman.h> | 31 | #include <sys/mman.h> |
31 | 32 | ||
32 | #ifndef HAVE_ON_EXIT | 33 | #ifndef HAVE_ON_EXIT_SUPPORT |
33 | #ifndef ATEXIT_MAX | 34 | #ifndef ATEXIT_MAX |
34 | #define ATEXIT_MAX 32 | 35 | #define ATEXIT_MAX 32 |
35 | #endif | 36 | #endif |
@@ -65,31 +66,25 @@ struct perf_record { | |||
65 | struct perf_tool tool; | 66 | struct perf_tool tool; |
66 | struct perf_record_opts opts; | 67 | struct perf_record_opts opts; |
67 | u64 bytes_written; | 68 | u64 bytes_written; |
68 | const char *output_name; | 69 | struct perf_data_file file; |
69 | struct perf_evlist *evlist; | 70 | struct perf_evlist *evlist; |
70 | struct perf_session *session; | 71 | struct perf_session *session; |
71 | const char *progname; | 72 | const char *progname; |
72 | int output; | ||
73 | unsigned int page_size; | ||
74 | int realtime_prio; | 73 | int realtime_prio; |
75 | bool no_buildid; | 74 | bool no_buildid; |
76 | bool no_buildid_cache; | 75 | bool no_buildid_cache; |
77 | long samples; | 76 | long samples; |
78 | off_t post_processing_offset; | ||
79 | }; | 77 | }; |
80 | 78 | ||
81 | static void advance_output(struct perf_record *rec, size_t size) | ||
82 | { | ||
83 | rec->bytes_written += size; | ||
84 | } | ||
85 | |||
86 | static int write_output(struct perf_record *rec, void *buf, size_t size) | 79 | static int write_output(struct perf_record *rec, void *buf, size_t size) |
87 | { | 80 | { |
81 | struct perf_data_file *file = &rec->file; | ||
82 | |||
88 | while (size) { | 83 | while (size) { |
89 | int ret = write(rec->output, buf, size); | 84 | int ret = write(file->fd, buf, size); |
90 | 85 | ||
91 | if (ret < 0) { | 86 | if (ret < 0) { |
92 | pr_err("failed to write\n"); | 87 | pr_err("failed to write perf data, error: %m\n"); |
93 | return -1; | 88 | return -1; |
94 | } | 89 | } |
95 | 90 | ||
@@ -119,7 +114,7 @@ static int perf_record__mmap_read(struct perf_record *rec, | |||
119 | { | 114 | { |
120 | unsigned int head = perf_mmap__read_head(md); | 115 | unsigned int head = perf_mmap__read_head(md); |
121 | unsigned int old = md->prev; | 116 | unsigned int old = md->prev; |
122 | unsigned char *data = md->base + rec->page_size; | 117 | unsigned char *data = md->base + page_size; |
123 | unsigned long size; | 118 | unsigned long size; |
124 | void *buf; | 119 | void *buf; |
125 | int rc = 0; | 120 | int rc = 0; |
@@ -234,10 +229,6 @@ try_again: | |||
234 | "or try again with a smaller value of -m/--mmap_pages.\n" | 229 | "or try again with a smaller value of -m/--mmap_pages.\n" |
235 | "(current value: %d)\n", opts->mmap_pages); | 230 | "(current value: %d)\n", opts->mmap_pages); |
236 | rc = -errno; | 231 | rc = -errno; |
237 | } else if (!is_power_of_2(opts->mmap_pages) && | ||
238 | (opts->mmap_pages != UINT_MAX)) { | ||
239 | pr_err("--mmap_pages/-m value must be a power of two."); | ||
240 | rc = -EINVAL; | ||
241 | } else { | 232 | } else { |
242 | pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); | 233 | pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); |
243 | rc = -errno; | 234 | rc = -errno; |
@@ -253,31 +244,34 @@ out: | |||
253 | 244 | ||
254 | static int process_buildids(struct perf_record *rec) | 245 | static int process_buildids(struct perf_record *rec) |
255 | { | 246 | { |
256 | u64 size = lseek(rec->output, 0, SEEK_CUR); | 247 | struct perf_data_file *file = &rec->file; |
248 | struct perf_session *session = rec->session; | ||
249 | u64 start = session->header.data_offset; | ||
257 | 250 | ||
251 | u64 size = lseek(file->fd, 0, SEEK_CUR); | ||
258 | if (size == 0) | 252 | if (size == 0) |
259 | return 0; | 253 | return 0; |
260 | 254 | ||
261 | rec->session->fd = rec->output; | 255 | return __perf_session__process_events(session, start, |
262 | return __perf_session__process_events(rec->session, rec->post_processing_offset, | 256 | size - start, |
263 | size - rec->post_processing_offset, | ||
264 | size, &build_id__mark_dso_hit_ops); | 257 | size, &build_id__mark_dso_hit_ops); |
265 | } | 258 | } |
266 | 259 | ||
267 | static void perf_record__exit(int status, void *arg) | 260 | static void perf_record__exit(int status, void *arg) |
268 | { | 261 | { |
269 | struct perf_record *rec = arg; | 262 | struct perf_record *rec = arg; |
263 | struct perf_data_file *file = &rec->file; | ||
270 | 264 | ||
271 | if (status != 0) | 265 | if (status != 0) |
272 | return; | 266 | return; |
273 | 267 | ||
274 | if (!rec->opts.pipe_output) { | 268 | if (!file->is_pipe) { |
275 | rec->session->header.data_size += rec->bytes_written; | 269 | rec->session->header.data_size += rec->bytes_written; |
276 | 270 | ||
277 | if (!rec->no_buildid) | 271 | if (!rec->no_buildid) |
278 | process_buildids(rec); | 272 | process_buildids(rec); |
279 | perf_session__write_header(rec->session, rec->evlist, | 273 | perf_session__write_header(rec->session, rec->evlist, |
280 | rec->output, true); | 274 | file->fd, true); |
281 | perf_session__delete(rec->session); | 275 | perf_session__delete(rec->session); |
282 | perf_evlist__delete(rec->evlist); | 276 | perf_evlist__delete(rec->evlist); |
283 | symbol__exit(); | 277 | symbol__exit(); |
@@ -343,64 +337,47 @@ out: | |||
343 | return rc; | 337 | return rc; |
344 | } | 338 | } |
345 | 339 | ||
340 | static void perf_record__init_features(struct perf_record *rec) | ||
341 | { | ||
342 | struct perf_evlist *evsel_list = rec->evlist; | ||
343 | struct perf_session *session = rec->session; | ||
344 | int feat; | ||
345 | |||
346 | for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) | ||
347 | perf_header__set_feat(&session->header, feat); | ||
348 | |||
349 | if (rec->no_buildid) | ||
350 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); | ||
351 | |||
352 | if (!have_tracepoints(&evsel_list->entries)) | ||
353 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); | ||
354 | |||
355 | if (!rec->opts.branch_stack) | ||
356 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); | ||
357 | } | ||
358 | |||
346 | static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | 359 | static int __cmd_record(struct perf_record *rec, int argc, const char **argv) |
347 | { | 360 | { |
348 | struct stat st; | 361 | int err; |
349 | int flags; | ||
350 | int err, output, feat; | ||
351 | unsigned long waking = 0; | 362 | unsigned long waking = 0; |
352 | const bool forks = argc > 0; | 363 | const bool forks = argc > 0; |
353 | struct machine *machine; | 364 | struct machine *machine; |
354 | struct perf_tool *tool = &rec->tool; | 365 | struct perf_tool *tool = &rec->tool; |
355 | struct perf_record_opts *opts = &rec->opts; | 366 | struct perf_record_opts *opts = &rec->opts; |
356 | struct perf_evlist *evsel_list = rec->evlist; | 367 | struct perf_evlist *evsel_list = rec->evlist; |
357 | const char *output_name = rec->output_name; | 368 | struct perf_data_file *file = &rec->file; |
358 | struct perf_session *session; | 369 | struct perf_session *session; |
359 | bool disabled = false; | 370 | bool disabled = false; |
360 | 371 | ||
361 | rec->progname = argv[0]; | 372 | rec->progname = argv[0]; |
362 | 373 | ||
363 | rec->page_size = sysconf(_SC_PAGE_SIZE); | ||
364 | |||
365 | on_exit(perf_record__sig_exit, rec); | 374 | on_exit(perf_record__sig_exit, rec); |
366 | signal(SIGCHLD, sig_handler); | 375 | signal(SIGCHLD, sig_handler); |
367 | signal(SIGINT, sig_handler); | 376 | signal(SIGINT, sig_handler); |
368 | signal(SIGUSR1, sig_handler); | 377 | signal(SIGUSR1, sig_handler); |
369 | signal(SIGTERM, sig_handler); | 378 | signal(SIGTERM, sig_handler); |
370 | 379 | ||
371 | if (!output_name) { | 380 | session = perf_session__new(file, false, NULL); |
372 | if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) | ||
373 | opts->pipe_output = true; | ||
374 | else | ||
375 | rec->output_name = output_name = "perf.data"; | ||
376 | } | ||
377 | if (output_name) { | ||
378 | if (!strcmp(output_name, "-")) | ||
379 | opts->pipe_output = true; | ||
380 | else if (!stat(output_name, &st) && st.st_size) { | ||
381 | char oldname[PATH_MAX]; | ||
382 | snprintf(oldname, sizeof(oldname), "%s.old", | ||
383 | output_name); | ||
384 | unlink(oldname); | ||
385 | rename(output_name, oldname); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | flags = O_CREAT|O_RDWR|O_TRUNC; | ||
390 | |||
391 | if (opts->pipe_output) | ||
392 | output = STDOUT_FILENO; | ||
393 | else | ||
394 | output = open(output_name, flags, S_IRUSR | S_IWUSR); | ||
395 | if (output < 0) { | ||
396 | perror("failed to create output file"); | ||
397 | return -1; | ||
398 | } | ||
399 | |||
400 | rec->output = output; | ||
401 | |||
402 | session = perf_session__new(output_name, O_WRONLY, | ||
403 | true, false, NULL); | ||
404 | if (session == NULL) { | 381 | if (session == NULL) { |
405 | pr_err("Not enough memory for reading perf file header\n"); | 382 | pr_err("Not enough memory for reading perf file header\n"); |
406 | return -1; | 383 | return -1; |
@@ -408,21 +385,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
408 | 385 | ||
409 | rec->session = session; | 386 | rec->session = session; |
410 | 387 | ||
411 | for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) | 388 | perf_record__init_features(rec); |
412 | perf_header__set_feat(&session->header, feat); | ||
413 | |||
414 | if (rec->no_buildid) | ||
415 | perf_header__clear_feat(&session->header, HEADER_BUILD_ID); | ||
416 | |||
417 | if (!have_tracepoints(&evsel_list->entries)) | ||
418 | perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); | ||
419 | |||
420 | if (!rec->opts.branch_stack) | ||
421 | perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); | ||
422 | 389 | ||
423 | if (forks) { | 390 | if (forks) { |
424 | err = perf_evlist__prepare_workload(evsel_list, &opts->target, | 391 | err = perf_evlist__prepare_workload(evsel_list, &opts->target, |
425 | argv, opts->pipe_output, | 392 | argv, file->is_pipe, |
426 | true); | 393 | true); |
427 | if (err < 0) { | 394 | if (err < 0) { |
428 | pr_err("Couldn't run the workload!\n"); | 395 | pr_err("Couldn't run the workload!\n"); |
@@ -443,13 +410,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
443 | */ | 410 | */ |
444 | on_exit(perf_record__exit, rec); | 411 | on_exit(perf_record__exit, rec); |
445 | 412 | ||
446 | if (opts->pipe_output) { | 413 | if (file->is_pipe) { |
447 | err = perf_header__write_pipe(output); | 414 | err = perf_header__write_pipe(file->fd); |
448 | if (err < 0) | 415 | if (err < 0) |
449 | goto out_delete_session; | 416 | goto out_delete_session; |
450 | } else { | 417 | } else { |
451 | err = perf_session__write_header(session, evsel_list, | 418 | err = perf_session__write_header(session, evsel_list, |
452 | output, false); | 419 | file->fd, false); |
453 | if (err < 0) | 420 | if (err < 0) |
454 | goto out_delete_session; | 421 | goto out_delete_session; |
455 | } | 422 | } |
@@ -462,11 +429,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
462 | goto out_delete_session; | 429 | goto out_delete_session; |
463 | } | 430 | } |
464 | 431 | ||
465 | rec->post_processing_offset = lseek(output, 0, SEEK_CUR); | ||
466 | |||
467 | machine = &session->machines.host; | 432 | machine = &session->machines.host; |
468 | 433 | ||
469 | if (opts->pipe_output) { | 434 | if (file->is_pipe) { |
470 | err = perf_event__synthesize_attrs(tool, session, | 435 | err = perf_event__synthesize_attrs(tool, session, |
471 | process_synthesized_event); | 436 | process_synthesized_event); |
472 | if (err < 0) { | 437 | if (err < 0) { |
@@ -483,13 +448,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
483 | * return this more properly and also | 448 | * return this more properly and also |
484 | * propagate errors that now are calling die() | 449 | * propagate errors that now are calling die() |
485 | */ | 450 | */ |
486 | err = perf_event__synthesize_tracing_data(tool, output, evsel_list, | 451 | err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, |
487 | process_synthesized_event); | 452 | process_synthesized_event); |
488 | if (err <= 0) { | 453 | if (err <= 0) { |
489 | pr_err("Couldn't record tracing data.\n"); | 454 | pr_err("Couldn't record tracing data.\n"); |
490 | goto out_delete_session; | 455 | goto out_delete_session; |
491 | } | 456 | } |
492 | advance_output(rec, err); | 457 | rec->bytes_written += err; |
493 | } | 458 | } |
494 | } | 459 | } |
495 | 460 | ||
@@ -590,7 +555,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
590 | fprintf(stderr, | 555 | fprintf(stderr, |
591 | "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", | 556 | "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", |
592 | (double)rec->bytes_written / 1024.0 / 1024.0, | 557 | (double)rec->bytes_written / 1024.0 / 1024.0, |
593 | output_name, | 558 | file->path, |
594 | rec->bytes_written / 24); | 559 | rec->bytes_written / 24); |
595 | 560 | ||
596 | return 0; | 561 | return 0; |
@@ -618,6 +583,9 @@ static const struct branch_mode branch_modes[] = { | |||
618 | BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), | 583 | BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), |
619 | BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), | 584 | BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), |
620 | BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), | 585 | BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), |
586 | BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), | ||
587 | BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), | ||
588 | BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), | ||
621 | BRANCH_END | 589 | BRANCH_END |
622 | }; | 590 | }; |
623 | 591 | ||
@@ -684,7 +652,7 @@ error: | |||
684 | return ret; | 652 | return ret; |
685 | } | 653 | } |
686 | 654 | ||
687 | #ifdef LIBUNWIND_SUPPORT | 655 | #ifdef HAVE_LIBUNWIND_SUPPORT |
688 | static int get_stack_size(char *str, unsigned long *_size) | 656 | static int get_stack_size(char *str, unsigned long *_size) |
689 | { | 657 | { |
690 | char *endptr; | 658 | char *endptr; |
@@ -710,7 +678,7 @@ static int get_stack_size(char *str, unsigned long *_size) | |||
710 | max_size, str); | 678 | max_size, str); |
711 | return -1; | 679 | return -1; |
712 | } | 680 | } |
713 | #endif /* LIBUNWIND_SUPPORT */ | 681 | #endif /* HAVE_LIBUNWIND_SUPPORT */ |
714 | 682 | ||
715 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts) | 683 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts) |
716 | { | 684 | { |
@@ -739,7 +707,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts) | |||
739 | "needed for -g fp\n"); | 707 | "needed for -g fp\n"); |
740 | break; | 708 | break; |
741 | 709 | ||
742 | #ifdef LIBUNWIND_SUPPORT | 710 | #ifdef HAVE_LIBUNWIND_SUPPORT |
743 | /* Dwarf style */ | 711 | /* Dwarf style */ |
744 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { | 712 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { |
745 | const unsigned long default_stack_dump_size = 8192; | 713 | const unsigned long default_stack_dump_size = 8192; |
@@ -755,7 +723,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts) | |||
755 | ret = get_stack_size(tok, &size); | 723 | ret = get_stack_size(tok, &size); |
756 | opts->stack_dump_size = size; | 724 | opts->stack_dump_size = size; |
757 | } | 725 | } |
758 | #endif /* LIBUNWIND_SUPPORT */ | 726 | #endif /* HAVE_LIBUNWIND_SUPPORT */ |
759 | } else { | 727 | } else { |
760 | pr_err("callchain: Unknown --call-graph option " | 728 | pr_err("callchain: Unknown --call-graph option " |
761 | "value: %s\n", arg); | 729 | "value: %s\n", arg); |
@@ -841,7 +809,7 @@ static struct perf_record record = { | |||
841 | 809 | ||
842 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " | 810 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " |
843 | 811 | ||
844 | #ifdef LIBUNWIND_SUPPORT | 812 | #ifdef HAVE_LIBUNWIND_SUPPORT |
845 | const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; | 813 | const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; |
846 | #else | 814 | #else |
847 | const char record_callchain_help[] = CALLCHAIN_HELP "fp"; | 815 | const char record_callchain_help[] = CALLCHAIN_HELP "fp"; |
@@ -875,13 +843,14 @@ const struct option record_options[] = { | |||
875 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", | 843 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", |
876 | "list of cpus to monitor"), | 844 | "list of cpus to monitor"), |
877 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), | 845 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), |
878 | OPT_STRING('o', "output", &record.output_name, "file", | 846 | OPT_STRING('o', "output", &record.file.path, "file", |
879 | "output file name"), | 847 | "output file name"), |
880 | OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, | 848 | OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, |
881 | "child tasks do not inherit counters"), | 849 | "child tasks do not inherit counters"), |
882 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), | 850 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), |
883 | OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, | 851 | OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", |
884 | "number of mmap data pages"), | 852 | "number of mmap data pages", |
853 | perf_evlist__parse_mmap_pages), | ||
885 | OPT_BOOLEAN(0, "group", &record.opts.group, | 854 | OPT_BOOLEAN(0, "group", &record.opts.group, |
886 | "put the counters into a counter group"), | 855 | "put the counters into a counter group"), |
887 | OPT_CALLBACK_NOOPT('g', NULL, &record.opts, | 856 | OPT_CALLBACK_NOOPT('g', NULL, &record.opts, |
@@ -920,6 +889,8 @@ const struct option record_options[] = { | |||
920 | parse_branch_stack), | 889 | parse_branch_stack), |
921 | OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, | 890 | OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, |
922 | "sample by weight (on special events only)"), | 891 | "sample by weight (on special events only)"), |
892 | OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, | ||
893 | "sample transaction flags (special events only)"), | ||
923 | OPT_END() | 894 | OPT_END() |
924 | }; | 895 | }; |
925 | 896 | ||
@@ -989,20 +960,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
989 | if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) | 960 | if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) |
990 | usage_with_options(record_usage, record_options); | 961 | usage_with_options(record_usage, record_options); |
991 | 962 | ||
992 | if (rec->opts.user_interval != ULLONG_MAX) | 963 | if (perf_record_opts__config(&rec->opts)) { |
993 | rec->opts.default_interval = rec->opts.user_interval; | ||
994 | if (rec->opts.user_freq != UINT_MAX) | ||
995 | rec->opts.freq = rec->opts.user_freq; | ||
996 | |||
997 | /* | ||
998 | * User specified count overrides default frequency. | ||
999 | */ | ||
1000 | if (rec->opts.default_interval) | ||
1001 | rec->opts.freq = 0; | ||
1002 | else if (rec->opts.freq) { | ||
1003 | rec->opts.default_interval = rec->opts.freq; | ||
1004 | } else { | ||
1005 | ui__error("frequency and count are zero, aborting\n"); | ||
1006 | err = -EINVAL; | 964 | err = -EINVAL; |
1007 | goto out_free_fd; | 965 | goto out_free_fd; |
1008 | } | 966 | } |