1 /* 2 * builtin-record.c 3 * 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 9 10 #include "builtin.h" 11 12 #include "perf.h" 13 14 #include "util/build-id.h" 15 #include "util/util.h" 16 #include "util/parse-options.h" 17 #include "util/parse-events.h" 18 19 #include "util/header.h" 20 #include "util/event.h" 21 #include "util/debug.h" 22 #include "util/session.h" 23 #include "util/symbol.h" 24 #include "util/cpumap.h" 25 26 #include <unistd.h> 27 #include <sched.h> 28 29 enum write_mode_t { 30 WRITE_FORCE, 31 WRITE_APPEND 32 }; 33 34 static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 35 36 static u64 user_interval = ULLONG_MAX; 37 static u64 default_interval = 0; 38 39 static int nr_cpus = 0; 40 static unsigned int page_size; 41 static unsigned int mmap_pages = 128; 42 static unsigned int user_freq = UINT_MAX; 43 static int freq = 1000; 44 static int output; 45 static int pipe_output = 0; 46 static const char *output_name = "perf.data"; 47 static int group = 0; 48 static int realtime_prio = 0; 49 static bool raw_samples = false; 50 static bool system_wide = false; 51 static int profile_cpu = -1; 52 static pid_t target_pid = -1; 53 static pid_t target_tid = -1; 54 static pid_t *all_tids = NULL; 55 static int thread_num = 0; 56 static pid_t child_pid = -1; 57 static bool no_inherit = false; 58 static enum write_mode_t write_mode = WRITE_FORCE; 59 static bool call_graph = false; 60 static bool inherit_stat = false; 61 static bool no_samples = false; 62 static bool sample_address = false; 63 static bool multiplex = false; 64 static int multiplex_fd = -1; 65 66 static long samples = 0; 67 static struct timeval last_read; 68 static struct timeval this_read; 69 70 static u64 bytes_written = 0; 71 72 static struct pollfd *event_array; 73 74 static int nr_poll = 0; 75 static int nr_cpu = 0; 76 77 static int file_new = 1; 78 static off_t post_processing_offset; 79 80 static struct perf_session *session; 81 82 struct mmap_data { 83 int counter; 84 void *base; 85 unsigned int mask; 86 unsigned int prev; 87 }; 88 89 static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; 90 91 static unsigned long mmap_read_head(struct mmap_data *md) 92 { 93 struct perf_event_mmap_page *pc = md->base; 94 long head; 95 96 head = pc->data_head; 97 rmb(); 98 99 return head; 100 } 101 102 static void mmap_write_tail(struct mmap_data *md, unsigned long tail) 103 { 104 struct perf_event_mmap_page *pc = md->base; 105 106 /* 107 * ensure all reads are done before we write the tail out. 108 */ 109 /* mb(); */ 110 pc->data_tail = tail; 111 } 112 113 static void advance_output(size_t size) 114 { 115 bytes_written += size; 116 } 117 118 static void write_output(void *buf, size_t size) 119 { 120 while (size) { 121 int ret = write(output, buf, size); 122 123 if (ret < 0) 124 die("failed to write"); 125 126 size -= ret; 127 buf += ret; 128 129 bytes_written += ret; 130 } 131 } 132 133 static int process_synthesized_event(event_t *event, 134 struct perf_session *self __used) 135 { 136 write_output(event, event->header.size); 137 return 0; 138 } 139 140 static void mmap_read(struct mmap_data *md) 141 { 142 unsigned int head = mmap_read_head(md); 143 unsigned int old = md->prev; 144 unsigned char *data = md->base + page_size; 145 unsigned long size; 146 void *buf; 147 int diff; 148 149 gettimeofday(&this_read, NULL); 150 151 /* 152 * If we're further behind than half the buffer, there's a chance 153 * the writer will bite our tail and mess up the samples under us. 154 * 155 * If we somehow ended up ahead of the head, we got messed up. 156 * 157 * In either case, truncate and restart at head. 158 */ 159 diff = head - old; 160 if (diff < 0) { 161 struct timeval iv; 162 unsigned long msecs; 163 164 timersub(&this_read, &last_read, &iv); 165 msecs = iv.tv_sec*1000 + iv.tv_usec/1000; 166 167 fprintf(stderr, "WARNING: failed to keep up with mmap data." 168 " Last read %lu msecs ago.\n", msecs); 169 170 /* 171 * head points to a known good entry, start there. 172 */ 173 old = head; 174 } 175 176 last_read = this_read; 177 178 if (old != head) 179 samples++; 180 181 size = head - old; 182 183 if ((old & md->mask) + size != (head & md->mask)) { 184 buf = &data[old & md->mask]; 185 size = md->mask + 1 - (old & md->mask); 186 old += size; 187 188 write_output(buf, size); 189 } 190 191 buf = &data[old & md->mask]; 192 size = head - old; 193 old += size; 194 195 write_output(buf, size); 196 197 md->prev = old; 198 mmap_write_tail(md, old); 199 } 200 201 static volatile int done = 0; 202 static volatile int signr = -1; 203 204 static void sig_handler(int sig) 205 { 206 done = 1; 207 signr = sig; 208 } 209 210 static void sig_atexit(void) 211 { 212 if (child_pid != -1) 213 kill(child_pid, SIGTERM); 214 215 if (signr == -1) 216 return; 217 218 signal(signr, SIG_DFL); 219 kill(getpid(), signr); 220 } 221 222 static int group_fd; 223 224 static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr) 225 { 226 struct perf_header_attr *h_attr; 227 228 if (nr < session->header.attrs) { 229 h_attr = session->header.attr[nr]; 230 } else { 231 h_attr = perf_header_attr__new(a); 232 if (h_attr != NULL) 233 if (perf_header__add_attr(&session->header, h_attr) < 0) { 234 perf_header_attr__delete(h_attr); 235 h_attr = NULL; 236 } 237 } 238 239 return h_attr; 240 } 241 242 static void create_counter(int counter, int cpu) 243 { 244 char *filter = filters[counter]; 245 struct perf_event_attr *attr = attrs + counter; 246 struct perf_header_attr *h_attr; 247 int track = !counter; /* only the first counter needs these */ 248 int thread_index; 249 int ret; 250 struct { 251 u64 count; 252 u64 time_enabled; 253 u64 time_running; 254 u64 id; 255 } read_data; 256 257 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 258 PERF_FORMAT_TOTAL_TIME_RUNNING | 259 PERF_FORMAT_ID; 260 261 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 262 263 if (nr_counters > 1) 264 attr->sample_type |= PERF_SAMPLE_ID; 265 266 /* 267 * We default some events to a 1 default interval. But keep 268 * it a weak assumption overridable by the user. 269 */ 270 if (!attr->sample_period || (user_freq != UINT_MAX && 271 user_interval != ULLONG_MAX)) { 272 if (freq) { 273 attr->sample_type |= PERF_SAMPLE_PERIOD; 274 attr->freq = 1; 275 attr->sample_freq = freq; 276 } else { 277 attr->sample_period = default_interval; 278 } 279 } 280 281 if (no_samples) 282 attr->sample_freq = 0; 283 284 if (inherit_stat) 285 attr->inherit_stat = 1; 286 287 if (sample_address) 288 attr->sample_type |= PERF_SAMPLE_ADDR; 289 290 if (call_graph) 291 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 292 293 if (raw_samples) { 294 attr->sample_type |= PERF_SAMPLE_TIME; 295 attr->sample_type |= PERF_SAMPLE_RAW; 296 attr->sample_type |= PERF_SAMPLE_CPU; 297 } 298 299 attr->mmap = track; 300 attr->comm = track; 301 attr->inherit = !no_inherit; 302 if (target_pid == -1 && target_tid == -1 && !system_wide) { 303 attr->disabled = 1; 304 attr->enable_on_exec = 1; 305 } 306 307 for (thread_index = 0; thread_index < thread_num; thread_index++) { 308 try_again: 309 fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, 310 all_tids[thread_index], cpu, group_fd, 0); 311 312 if (fd[nr_cpu][counter][thread_index] < 0) { 313 int err = errno; 314 315 if (err == EPERM || err == EACCES) 316 die("Permission error - are you root?\n" 317 "\t Consider tweaking" 318 " /proc/sys/kernel/perf_event_paranoid.\n"); 319 else if (err == ENODEV && profile_cpu != -1) { 320 die("No such device - did you specify" 321 " an out-of-range profile CPU?\n"); 322 } 323 324 /* 325 * If it's cycles then fall back to hrtimer 326 * based cpu-clock-tick sw counter, which 327 * is always available even if no PMU support: 328 */ 329 if (attr->type == PERF_TYPE_HARDWARE 330 && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 331 332 if (verbose) 333 warning(" ... trying to fall back to cpu-clock-ticks\n"); 334 attr->type = PERF_TYPE_SOFTWARE; 335 attr->config = PERF_COUNT_SW_CPU_CLOCK; 336 goto try_again; 337 } 338 printf("\n"); 339 error("perfcounter syscall returned with %d (%s)\n", 340 fd[nr_cpu][counter][thread_index], strerror(err)); 341 342 #if defined(__i386__) || defined(__x86_64__) 343 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 344 die("No hardware sampling interrupt available." 345 " No APIC? If so then you can boot the kernel" 346 " with the \"lapic\" boot parameter to" 347 " force-enable it.\n"); 348 #endif 349 350 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 351 exit(-1); 352 } 353 354 h_attr = get_header_attr(attr, counter); 355 if (h_attr == NULL) 356 die("nomem\n"); 357 358 if (!file_new) { 359 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { 360 fprintf(stderr, "incompatible append\n"); 361 exit(-1); 362 } 363 } 364 365 if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { 366 perror("Unable to read perf file descriptor\n"); 367 exit(-1); 368 } 369 370 if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { 371 pr_warning("Not enough memory to add id\n"); 372 exit(-1); 373 } 374 375 assert(fd[nr_cpu][counter][thread_index] >= 0); 376 fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK); 377 378 /* 379 * First counter acts as the group leader: 380 */ 381 if (group && group_fd == -1) 382 group_fd = fd[nr_cpu][counter][thread_index]; 383 if (multiplex && multiplex_fd == -1) 384 multiplex_fd = fd[nr_cpu][counter][thread_index]; 385 386 if (multiplex && fd[nr_cpu][counter][thread_index] != multiplex_fd) { 387 388 ret = ioctl(fd[nr_cpu][counter][thread_index], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); 389 assert(ret != -1); 390 } else { 391 event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; 392 event_array[nr_poll].events = POLLIN; 393 nr_poll++; 394 395 mmap_array[nr_cpu][counter][thread_index].counter = counter; 396 mmap_array[nr_cpu][counter][thread_index].prev = 0; 397 mmap_array[nr_cpu][counter][thread_index].mask = mmap_pages*page_size - 1; 398 mmap_array[nr_cpu][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, 399 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0); 400 if (mmap_array[nr_cpu][counter][thread_index].base == MAP_FAILED) { 401 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 402 exit(-1); 403 } 404 } 405 406 if (filter != NULL) { 407 ret = ioctl(fd[nr_cpu][counter][thread_index], 408 PERF_EVENT_IOC_SET_FILTER, filter); 409 if (ret) { 410 error("failed to set filter with %d (%s)\n", errno, 411 strerror(errno)); 412 exit(-1); 413 } 414 } 415 } 416 } 417 418 static void open_counters(int cpu) 419 { 420 int counter; 421 422 group_fd = -1; 423 for (counter = 0; counter < nr_counters; counter++) 424 create_counter(counter, cpu); 425 426 nr_cpu++; 427 } 428 429 static int process_buildids(void) 430 { 431 u64 size = lseek(output, 0, SEEK_CUR); 432 433 if (size == 0) 434 return 0; 435 436 session->fd = output; 437 return __perf_session__process_events(session, post_processing_offset, 438 size - post_processing_offset, 439 size, &build_id__mark_dso_hit_ops); 440 } 441 442 static void atexit_header(void) 443 { 444 if (!pipe_output) { 445 session->header.data_size += bytes_written; 446 447 process_buildids(); 448 perf_header__write(&session->header, output, true); 449 } 450 } 451 452 static void event__synthesize_guest_os(struct machine *machine, void *data) 453 { 454 int err; 455 char *guest_kallsyms; 456 char path[PATH_MAX]; 457 struct perf_session *psession = data; 458 459 if (machine__is_host(machine)) 460 return; 461 462 /* 463 *As for guest kernel when processing subcommand record&report, 464 *we arrange module mmap prior to guest kernel mmap and trigger 465 *a preload dso because default guest module symbols are loaded 466 *from guest kallsyms instead of /lib/modules/XXX/XXX. This 467 *method is used to avoid symbol missing when the first addr is 468 *in module instead of in guest kernel. 469 */ 470 err = event__synthesize_modules(process_synthesized_event, 471 psession, machine); 472 if (err < 0) 473 pr_err("Couldn't record guest kernel [%d]'s reference" 474 " relocation symbol.\n", machine->pid); 475 476 if (machine__is_default_guest(machine)) 477 guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; 478 else { 479 sprintf(path, "%s/proc/kallsyms", machine->root_dir); 480 guest_kallsyms = path; 481 } 482 483 /* 484 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 485 * have no _text sometimes. 486 */ 487 err = event__synthesize_kernel_mmap(process_synthesized_event, 488 psession, machine, "_text"); 489 if (err < 0) 490 err = event__synthesize_kernel_mmap(process_synthesized_event, 491 psession, machine, "_stext"); 492 if (err < 0) 493 pr_err("Couldn't record guest kernel [%d]'s reference" 494 " relocation symbol.\n", machine->pid); 495 } 496 497 static struct perf_event_header finished_round_event = { 498 .size = sizeof(struct perf_event_header), 499 .type = PERF_RECORD_FINISHED_ROUND, 500 }; 501 502 static void mmap_read_all(void) 503 { 504 int i, counter, thread; 505 506 for (i = 0; i < nr_cpu; i++) { 507 for (counter = 0; counter < nr_counters; counter++) { 508 for (thread = 0; thread < thread_num; thread++) { 509 if (mmap_array[i][counter][thread].base) 510 mmap_read(&mmap_array[i][counter][thread]); 511 } 512 513 } 514 } 515 516 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 517 write_output(&finished_round_event, sizeof(finished_round_event)); 518 } 519 520 static int __cmd_record(int argc, const char **argv) 521 { 522 int i, counter; 523 struct stat st; 524 pid_t pid = 0; 525 int flags; 526 int err; 527 unsigned long waking = 0; 528 int child_ready_pipe[2], go_pipe[2]; 529 const bool forks = argc > 0; 530 char buf; 531 struct machine *machine; 532 533 page_size = sysconf(_SC_PAGE_SIZE); 534 535 atexit(sig_atexit); 536 signal(SIGCHLD, sig_handler); 537 signal(SIGINT, sig_handler); 538 539 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 540 perror("failed to create pipes"); 541 exit(-1); 542 } 543 544 if (!strcmp(output_name, "-")) 545 pipe_output = 1; 546 else if (!stat(output_name, &st) && st.st_size) { 547 if (write_mode == WRITE_FORCE) { 548 char oldname[PATH_MAX]; 549 snprintf(oldname, sizeof(oldname), "%s.old", 550 output_name); 551 unlink(oldname); 552 rename(output_name, oldname); 553 } 554 } else if (write_mode == WRITE_APPEND) { 555 write_mode = WRITE_FORCE; 556 } 557 558 flags = O_CREAT|O_RDWR; 559 if (write_mode == WRITE_APPEND) 560 file_new = 0; 561 else 562 flags |= O_TRUNC; 563 564 if (pipe_output) 565 output = STDOUT_FILENO; 566 else 567 output = open(output_name, flags, S_IRUSR | S_IWUSR); 568 if (output < 0) { 569 perror("failed to create output file"); 570 exit(-1); 571 } 572 573 session = perf_session__new(output_name, O_WRONLY, 574 write_mode == WRITE_FORCE, false); 575 if (session == NULL) { 576 pr_err("Not enough memory for reading perf file header\n"); 577 return -1; 578 } 579 580 if (!file_new) { 581 err = perf_header__read(session, output); 582 if (err < 0) 583 return err; 584 } 585 586 if (have_tracepoints(attrs, nr_counters)) 587 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 588 589 atexit(atexit_header); 590 591 if (forks) { 592 child_pid = fork(); 593 if (pid < 0) { 594 perror("failed to fork"); 595 exit(-1); 596 } 597 598 if (!child_pid) { 599 if (pipe_output) 600 dup2(2, 1); 601 close(child_ready_pipe[0]); 602 close(go_pipe[1]); 603 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 604 605 /* 606 * Do a dummy execvp to get the PLT entry resolved, 607 * so we avoid the resolver overhead on the real 608 * execvp call. 609 */ 610 execvp("", (char **)argv); 611 612 /* 613 * Tell the parent we're ready to go 614 */ 615 close(child_ready_pipe[1]); 616 617 /* 618 * Wait until the parent tells us to go. 619 */ 620 if (read(go_pipe[0], &buf, 1) == -1) 621 perror("unable to read pipe"); 622 623 execvp(argv[0], (char **)argv); 624 625 perror(argv[0]); 626 exit(-1); 627 } 628 629 if (!system_wide && target_tid == -1 && target_pid == -1) 630 all_tids[0] = child_pid; 631 632 close(child_ready_pipe[1]); 633 close(go_pipe[0]); 634 /* 635 * wait for child to settle 636 */ 637 if (read(child_ready_pipe[0], &buf, 1) == -1) { 638 perror("unable to read pipe"); 639 exit(-1); 640 } 641 close(child_ready_pipe[0]); 642 } 643 644 if ((!system_wide && no_inherit) || profile_cpu != -1) { 645 open_counters(profile_cpu); 646 } else { 647 nr_cpus = read_cpu_map(); 648 for (i = 0; i < nr_cpus; i++) 649 open_counters(cpumap[i]); 650 } 651 652 if (pipe_output) { 653 err = perf_header__write_pipe(output); 654 if (err < 0) 655 return err; 656 } else if (file_new) { 657 err = perf_header__write(&session->header, output, false); 658 if (err < 0) 659 return err; 660 } 661 662 post_processing_offset = lseek(output, 0, SEEK_CUR); 663 664 if (pipe_output) { 665 err = event__synthesize_attrs(&session->header, 666 process_synthesized_event, 667 session); 668 if (err < 0) { 669 pr_err("Couldn't synthesize attrs.\n"); 670 return err; 671 } 672 673 err = event__synthesize_event_types(process_synthesized_event, 674 session); 675 if (err < 0) { 676 pr_err("Couldn't synthesize event_types.\n"); 677 return err; 678 } 679 680 if (have_tracepoints(attrs, nr_counters)) { 681 /* 682 * FIXME err <= 0 here actually means that 683 * there were no tracepoints so its not really 684 * an error, just that we don't need to 685 * synthesize anything. We really have to 686 * return this more properly and also 687 * propagate errors that now are calling die() 688 */ 689 err = event__synthesize_tracing_data(output, attrs, 690 nr_counters, 691 process_synthesized_event, 692 session); 693 if (err <= 0) { 694 pr_err("Couldn't record tracing data.\n"); 695 return err; 696 } 697 advance_output(err); 698 } 699 } 700 701 machine = perf_session__find_host_machine(session); 702 if (!machine) { 703 pr_err("Couldn't find native kernel information.\n"); 704 return -1; 705 } 706 707 err = event__synthesize_kernel_mmap(process_synthesized_event, 708 session, machine, "_text"); 709 if (err < 0) 710 err = event__synthesize_kernel_mmap(process_synthesized_event, 711 session, machine, "_stext"); 712 if (err < 0) { 713 pr_err("Couldn't record kernel reference relocation symbol.\n"); 714 return err; 715 } 716 717 err = event__synthesize_modules(process_synthesized_event, 718 session, machine); 719 if (err < 0) { 720 pr_err("Couldn't record kernel reference relocation symbol.\n"); 721 return err; 722 } 723 if (perf_guest) 724 perf_session__process_machines(session, event__synthesize_guest_os); 725 726 if (!system_wide && profile_cpu == -1) 727 event__synthesize_thread(target_tid, process_synthesized_event, 728 session); 729 else 730 event__synthesize_threads(process_synthesized_event, session); 731 732 if (realtime_prio) { 733 struct sched_param param; 734 735 param.sched_priority = realtime_prio; 736 if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 737 pr_err("Could not set realtime priority.\n"); 738 exit(-1); 739 } 740 } 741 742 /* 743 * Let the child rip 744 */ 745 if (forks) 746 close(go_pipe[1]); 747 748 for (;;) { 749 int hits = samples; 750 int thread; 751 752 mmap_read_all(); 753 754 if (hits == samples) { 755 if (done) 756 break; 757 err = poll(event_array, nr_poll, -1); 758 waking++; 759 } 760 761 if (done) { 762 for (i = 0; i < nr_cpu; i++) { 763 for (counter = 0; 764 counter < nr_counters; 765 counter++) { 766 for (thread = 0; 767 thread < thread_num; 768 thread++) 769 ioctl(fd[i][counter][thread], 770 PERF_EVENT_IOC_DISABLE); 771 } 772 } 773 } 774 } 775 776 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 777 778 /* 779 * Approximate RIP event size: 24 bytes. 780 */ 781 fprintf(stderr, 782 "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n", 783 (double)bytes_written / 1024.0 / 1024.0, 784 output_name, 785 bytes_written / 24); 786 787 return 0; 788 } 789 790 static const char * const record_usage[] = { 791 "perf record [<options>] [<command>]", 792 "perf record [<options>] -- <command> [<options>]", 793 NULL 794 }; 795 796 static bool force, append_file; 797 798 static const struct option options[] = { 799 OPT_CALLBACK('e', "event", NULL, "event", 800 "event selector. use 'perf list' to list available events", 801 parse_events), 802 OPT_CALLBACK(0, "filter", NULL, "filter", 803 "event filter", parse_filter), 804 OPT_INTEGER('p', "pid", &target_pid, 805 "record events on existing process id"), 806 OPT_INTEGER('t', "tid", &target_tid, 807 "record events on existing thread id"), 808 OPT_INTEGER('r', "realtime", &realtime_prio, 809 "collect data with this RT SCHED_FIFO priority"), 810 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 811 "collect raw sample records from all opened counters"), 812 OPT_BOOLEAN('a', "all-cpus", &system_wide, 813 "system-wide collection from all CPUs"), 814 OPT_BOOLEAN('A', "append", &append_file, 815 "append to the output file to do incremental profiling"), 816 OPT_INTEGER('C', "profile_cpu", &profile_cpu, 817 "CPU to profile on"), 818 OPT_BOOLEAN('f', "force", &force, 819 "overwrite existing data file (deprecated)"), 820 OPT_U64('c', "count", &user_interval, "event period to sample"), 821 OPT_STRING('o', "output", &output_name, "file", 822 "output file name"), 823 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 824 "child tasks do not inherit counters"), 825 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 826 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 827 OPT_BOOLEAN('g', "call-graph", &call_graph, 828 "do call-graph (stack chain/backtrace) recording"), 829 OPT_INCR('v', "verbose", &verbose, 830 "be more verbose (show counter open errors, etc)"), 831 OPT_BOOLEAN('s', "stat", &inherit_stat, 832 "per thread counts"), 833 OPT_BOOLEAN('d', "data", &sample_address, 834 "Sample addresses"), 835 OPT_BOOLEAN('n', "no-samples", &no_samples, 836 "don't sample"), 837 OPT_BOOLEAN('M', "multiplex", &multiplex, 838 "multiplex counter output in a single channel"), 839 OPT_END() 840 }; 841 842 int cmd_record(int argc, const char **argv, const char *prefix __used) 843 { 844 int i,j; 845 846 argc = parse_options(argc, argv, options, record_usage, 847 PARSE_OPT_STOP_AT_NON_OPTION); 848 if (!argc && target_pid == -1 && target_tid == -1 && 849 !system_wide && profile_cpu == -1) 850 usage_with_options(record_usage, options); 851 852 if (force && append_file) { 853 fprintf(stderr, "Can't overwrite and append at the same time." 854 " You need to choose between -f and -A"); 855 usage_with_options(record_usage, options); 856 } else if (append_file) { 857 write_mode = WRITE_APPEND; 858 } else { 859 write_mode = WRITE_FORCE; 860 } 861 862 symbol__init(); 863 864 if (!nr_counters) { 865 nr_counters = 1; 866 attrs[0].type = PERF_TYPE_HARDWARE; 867 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 868 } 869 870 if (target_pid != -1) { 871 target_tid = target_pid; 872 thread_num = find_all_tid(target_pid, &all_tids); 873 if (thread_num <= 0) { 874 fprintf(stderr, "Can't find all threads of pid %d\n", 875 target_pid); 876 usage_with_options(record_usage, options); 877 } 878 } else { 879 all_tids=malloc(sizeof(pid_t)); 880 if (!all_tids) 881 return -ENOMEM; 882 883 all_tids[0] = target_tid; 884 thread_num = 1; 885 } 886 887 for (i = 0; i < MAX_NR_CPUS; i++) { 888 for (j = 0; j < MAX_COUNTERS; j++) { 889 fd[i][j] = malloc(sizeof(int)*thread_num); 890 mmap_array[i][j] = zalloc( 891 sizeof(struct mmap_data)*thread_num); 892 if (!fd[i][j] || !mmap_array[i][j]) 893 return -ENOMEM; 894 } 895 } 896 event_array = malloc( 897 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 898 if (!event_array) 899 return -ENOMEM; 900 901 if (user_interval != ULLONG_MAX) 902 default_interval = user_interval; 903 if (user_freq != UINT_MAX) 904 freq = user_freq; 905 906 /* 907 * User specified count overrides default frequency. 908 */ 909 if (default_interval) 910 freq = 0; 911 else if (freq) { 912 default_interval = freq; 913 } else { 914 fprintf(stderr, "frequency and count are zero, aborting\n"); 915 exit(EXIT_FAILURE); 916 } 917 918 return __cmd_record(argc, argv); 919 } 920