aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c81
1 files changed, 55 insertions, 26 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 711745f56bba..ff77b805de71 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -49,7 +49,6 @@ static int group = 0;
49static int realtime_prio = 0; 49static int realtime_prio = 0;
50static bool raw_samples = false; 50static bool raw_samples = false;
51static bool system_wide = false; 51static bool system_wide = false;
52static int profile_cpu = -1;
53static pid_t target_pid = -1; 52static pid_t target_pid = -1;
54static pid_t target_tid = -1; 53static pid_t target_tid = -1;
55static pid_t *all_tids = NULL; 54static pid_t *all_tids = NULL;
@@ -61,6 +60,7 @@ static bool call_graph = false;
61static bool inherit_stat = false; 60static bool inherit_stat = false;
62static bool no_samples = false; 61static bool no_samples = false;
63static bool sample_address = false; 62static bool sample_address = false;
63static bool no_buildid = false;
64 64
65static long samples = 0; 65static long samples = 0;
66static u64 bytes_written = 0; 66static u64 bytes_written = 0;
@@ -74,6 +74,7 @@ static int file_new = 1;
74static off_t post_processing_offset; 74static off_t post_processing_offset;
75 75
76static struct perf_session *session; 76static struct perf_session *session;
77static const char *cpu_list;
77 78
78struct mmap_data { 79struct mmap_data {
79 int counter; 80 int counter;
@@ -268,12 +269,17 @@ static void create_counter(int counter, int cpu)
268 if (inherit_stat) 269 if (inherit_stat)
269 attr->inherit_stat = 1; 270 attr->inherit_stat = 1;
270 271
271 if (sample_address) 272 if (sample_address) {
272 attr->sample_type |= PERF_SAMPLE_ADDR; 273 attr->sample_type |= PERF_SAMPLE_ADDR;
274 attr->mmap_data = track;
275 }
273 276
274 if (call_graph) 277 if (call_graph)
275 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 278 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
276 279
280 if (system_wide)
281 attr->sample_type |= PERF_SAMPLE_CPU;
282
277 if (raw_samples) { 283 if (raw_samples) {
278 attr->sample_type |= PERF_SAMPLE_TIME; 284 attr->sample_type |= PERF_SAMPLE_TIME;
279 attr->sample_type |= PERF_SAMPLE_RAW; 285 attr->sample_type |= PERF_SAMPLE_RAW;
@@ -300,7 +306,7 @@ try_again:
300 die("Permission error - are you root?\n" 306 die("Permission error - are you root?\n"
301 "\t Consider tweaking" 307 "\t Consider tweaking"
302 " /proc/sys/kernel/perf_event_paranoid.\n"); 308 " /proc/sys/kernel/perf_event_paranoid.\n");
303 else if (err == ENODEV && profile_cpu != -1) { 309 else if (err == ENODEV && cpu_list) {
304 die("No such device - did you specify" 310 die("No such device - did you specify"
305 " an out-of-range profile CPU?\n"); 311 " an out-of-range profile CPU?\n");
306 } 312 }
@@ -433,14 +439,14 @@ static void atexit_header(void)
433 439
434 process_buildids(); 440 process_buildids();
435 perf_header__write(&session->header, output, true); 441 perf_header__write(&session->header, output, true);
442 perf_session__delete(session);
443 symbol__exit();
436 } 444 }
437} 445}
438 446
439static void event__synthesize_guest_os(struct machine *machine, void *data) 447static void event__synthesize_guest_os(struct machine *machine, void *data)
440{ 448{
441 int err; 449 int err;
442 char *guest_kallsyms;
443 char path[PATH_MAX];
444 struct perf_session *psession = data; 450 struct perf_session *psession = data;
445 451
446 if (machine__is_host(machine)) 452 if (machine__is_host(machine))
@@ -460,13 +466,6 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
460 pr_err("Couldn't record guest kernel [%d]'s reference" 466 pr_err("Couldn't record guest kernel [%d]'s reference"
461 " relocation symbol.\n", machine->pid); 467 " relocation symbol.\n", machine->pid);
462 468
463 if (machine__is_default_guest(machine))
464 guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms;
465 else {
466 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
467 guest_kallsyms = path;
468 }
469
470 /* 469 /*
471 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 470 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
472 * have no _text sometimes. 471 * have no _text sometimes.
@@ -561,12 +560,15 @@ static int __cmd_record(int argc, const char **argv)
561 if (!file_new) { 560 if (!file_new) {
562 err = perf_header__read(session, output); 561 err = perf_header__read(session, output);
563 if (err < 0) 562 if (err < 0)
564 return err; 563 goto out_delete_session;
565 } 564 }
566 565
567 if (have_tracepoints(attrs, nr_counters)) 566 if (have_tracepoints(attrs, nr_counters))
568 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 567 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
569 568
569 /*
570 * perf_session__delete(session) will be called at atexit_header()
571 */
570 atexit(atexit_header); 572 atexit(atexit_header);
571 573
572 if (forks) { 574 if (forks) {
@@ -622,10 +624,15 @@ static int __cmd_record(int argc, const char **argv)
622 close(child_ready_pipe[0]); 624 close(child_ready_pipe[0]);
623 } 625 }
624 626
625 if ((!system_wide && no_inherit) || profile_cpu != -1) { 627 nr_cpus = read_cpu_map(cpu_list);
626 open_counters(profile_cpu); 628 if (nr_cpus < 1) {
629 perror("failed to collect number of CPUs\n");
630 return -1;
631 }
632
633 if (!system_wide && no_inherit && !cpu_list) {
634 open_counters(-1);
627 } else { 635 } else {
628 nr_cpus = read_cpu_map();
629 for (i = 0; i < nr_cpus; i++) 636 for (i = 0; i < nr_cpus; i++)
630 open_counters(cpumap[i]); 637 open_counters(cpumap[i]);
631 } 638 }
@@ -704,7 +711,7 @@ static int __cmd_record(int argc, const char **argv)
704 if (perf_guest) 711 if (perf_guest)
705 perf_session__process_machines(session, event__synthesize_guest_os); 712 perf_session__process_machines(session, event__synthesize_guest_os);
706 713
707 if (!system_wide && profile_cpu == -1) 714 if (!system_wide)
708 event__synthesize_thread(target_tid, process_synthesized_event, 715 event__synthesize_thread(target_tid, process_synthesized_event,
709 session); 716 session);
710 else 717 else
@@ -766,6 +773,10 @@ static int __cmd_record(int argc, const char **argv)
766 bytes_written / 24); 773 bytes_written / 24);
767 774
768 return 0; 775 return 0;
776
777out_delete_session:
778 perf_session__delete(session);
779 return err;
769} 780}
770 781
771static const char * const record_usage[] = { 782static const char * const record_usage[] = {
@@ -794,8 +805,8 @@ static const struct option options[] = {
794 "system-wide collection from all CPUs"), 805 "system-wide collection from all CPUs"),
795 OPT_BOOLEAN('A', "append", &append_file, 806 OPT_BOOLEAN('A', "append", &append_file,
796 "append to the output file to do incremental profiling"), 807 "append to the output file to do incremental profiling"),
797 OPT_INTEGER('C', "profile_cpu", &profile_cpu, 808 OPT_STRING('C', "cpu", &cpu_list, "cpu",
798 "CPU to profile on"), 809 "list of cpus to monitor"),
799 OPT_BOOLEAN('f', "force", &force, 810 OPT_BOOLEAN('f', "force", &force,
800 "overwrite existing data file (deprecated)"), 811 "overwrite existing data file (deprecated)"),
801 OPT_U64('c', "count", &user_interval, "event period to sample"), 812 OPT_U64('c', "count", &user_interval, "event period to sample"),
@@ -815,17 +826,19 @@ static const struct option options[] = {
815 "Sample addresses"), 826 "Sample addresses"),
816 OPT_BOOLEAN('n', "no-samples", &no_samples, 827 OPT_BOOLEAN('n', "no-samples", &no_samples,
817 "don't sample"), 828 "don't sample"),
829 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid,
830 "do not update the buildid cache"),
818 OPT_END() 831 OPT_END()
819}; 832};
820 833
821int cmd_record(int argc, const char **argv, const char *prefix __used) 834int cmd_record(int argc, const char **argv, const char *prefix __used)
822{ 835{
823 int i,j; 836 int i, j, err = -ENOMEM;
824 837
825 argc = parse_options(argc, argv, options, record_usage, 838 argc = parse_options(argc, argv, options, record_usage,
826 PARSE_OPT_STOP_AT_NON_OPTION); 839 PARSE_OPT_STOP_AT_NON_OPTION);
827 if (!argc && target_pid == -1 && target_tid == -1 && 840 if (!argc && target_pid == -1 && target_tid == -1 &&
828 !system_wide && profile_cpu == -1) 841 !system_wide && !cpu_list)
829 usage_with_options(record_usage, options); 842 usage_with_options(record_usage, options);
830 843
831 if (force && append_file) { 844 if (force && append_file) {
@@ -839,6 +852,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
839 } 852 }
840 853
841 symbol__init(); 854 symbol__init();
855 if (no_buildid)
856 disable_buildid_cache();
842 857
843 if (!nr_counters) { 858 if (!nr_counters) {
844 nr_counters = 1; 859 nr_counters = 1;
@@ -857,7 +872,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
857 } else { 872 } else {
858 all_tids=malloc(sizeof(pid_t)); 873 all_tids=malloc(sizeof(pid_t));
859 if (!all_tids) 874 if (!all_tids)
860 return -ENOMEM; 875 goto out_symbol_exit;
861 876
862 all_tids[0] = target_tid; 877 all_tids[0] = target_tid;
863 thread_num = 1; 878 thread_num = 1;
@@ -867,13 +882,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
867 for (j = 0; j < MAX_COUNTERS; j++) { 882 for (j = 0; j < MAX_COUNTERS; j++) {
868 fd[i][j] = malloc(sizeof(int)*thread_num); 883 fd[i][j] = malloc(sizeof(int)*thread_num);
869 if (!fd[i][j]) 884 if (!fd[i][j])
870 return -ENOMEM; 885 goto out_free_fd;
871 } 886 }
872 } 887 }
873 event_array = malloc( 888 event_array = malloc(
874 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 889 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
875 if (!event_array) 890 if (!event_array)
876 return -ENOMEM; 891 goto out_free_fd;
877 892
878 if (user_interval != ULLONG_MAX) 893 if (user_interval != ULLONG_MAX)
879 default_interval = user_interval; 894 default_interval = user_interval;
@@ -889,8 +904,22 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
889 default_interval = freq; 904 default_interval = freq;
890 } else { 905 } else {
891 fprintf(stderr, "frequency and count are zero, aborting\n"); 906 fprintf(stderr, "frequency and count are zero, aborting\n");
892 exit(EXIT_FAILURE); 907 err = -EINVAL;
908 goto out_free_event_array;
893 } 909 }
894 910
895 return __cmd_record(argc, argv); 911 err = __cmd_record(argc, argv);
912
913out_free_event_array:
914 free(event_array);
915out_free_fd:
916 for (i = 0; i < MAX_NR_CPUS; i++) {
917 for (j = 0; j < MAX_COUNTERS; j++)
918 free(fd[i][j]);
919 }
920 free(all_tids);
921 all_tids = NULL;
922out_symbol_exit:
923 symbol__exit();
924 return err;
896} 925}