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.c180
1 files changed, 48 insertions, 132 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6ab58cc99d53..c3ac5415c097 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -35,32 +35,24 @@ enum write_mode_t {
35 WRITE_APPEND 35 WRITE_APPEND
36}; 36};
37 37
38static u64 user_interval = ULLONG_MAX; 38static struct perf_record_opts record_opts = {
39static u64 default_interval = 0; 39 .target_pid = -1,
40 .target_tid = -1,
41 .user_freq = UINT_MAX,
42 .user_interval = ULLONG_MAX,
43 .freq = 1000,
44 .sample_id_all_avail = true,
45};
40 46
41static unsigned int page_size; 47static unsigned int page_size;
42static unsigned int mmap_pages = UINT_MAX; 48static unsigned int mmap_pages = UINT_MAX;
43static unsigned int user_freq = UINT_MAX;
44static int freq = 1000;
45static int output; 49static int output;
46static int pipe_output = 0; 50static int pipe_output = 0;
47static const char *output_name = NULL; 51static const char *output_name = NULL;
48static bool group = false; 52static bool group = false;
49static int realtime_prio = 0; 53static int realtime_prio = 0;
50static bool nodelay = false;
51static bool raw_samples = false;
52static bool sample_id_all_avail = true;
53static bool system_wide = false;
54static pid_t target_pid = -1;
55static pid_t target_tid = -1;
56static pid_t child_pid = -1; 54static pid_t child_pid = -1;
57static bool no_inherit = false;
58static enum write_mode_t write_mode = WRITE_FORCE; 55static enum write_mode_t write_mode = WRITE_FORCE;
59static bool call_graph = false;
60static bool inherit_stat = false;
61static bool no_samples = false;
62static bool sample_address = false;
63static bool sample_time = false;
64static bool no_buildid = false; 56static bool no_buildid = false;
65static bool no_buildid_cache = false; 57static bool no_buildid_cache = false;
66static struct perf_evlist *evsel_list; 58static struct perf_evlist *evsel_list;
@@ -72,7 +64,6 @@ static int file_new = 1;
72static off_t post_processing_offset; 64static off_t post_processing_offset;
73 65
74static struct perf_session *session; 66static struct perf_session *session;
75static const char *cpu_list;
76static const char *progname; 67static const char *progname;
77 68
78static void advance_output(size_t size) 69static void advance_output(size_t size)
@@ -169,78 +160,6 @@ static void sig_atexit(void)
169 kill(getpid(), signr); 160 kill(getpid(), signr);
170} 161}
171 162
172static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
173{
174 struct perf_event_attr *attr = &evsel->attr;
175 int track = !evsel->idx; /* only the first counter needs these */
176
177 attr->disabled = 1;
178 attr->inherit = !no_inherit;
179 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING |
181 PERF_FORMAT_ID;
182
183 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
184
185 if (evlist->nr_entries > 1)
186 attr->sample_type |= PERF_SAMPLE_ID;
187
188 /*
189 * We default some events to a 1 default interval. But keep
190 * it a weak assumption overridable by the user.
191 */
192 if (!attr->sample_period || (user_freq != UINT_MAX &&
193 user_interval != ULLONG_MAX)) {
194 if (freq) {
195 attr->sample_type |= PERF_SAMPLE_PERIOD;
196 attr->freq = 1;
197 attr->sample_freq = freq;
198 } else {
199 attr->sample_period = default_interval;
200 }
201 }
202
203 if (no_samples)
204 attr->sample_freq = 0;
205
206 if (inherit_stat)
207 attr->inherit_stat = 1;
208
209 if (sample_address) {
210 attr->sample_type |= PERF_SAMPLE_ADDR;
211 attr->mmap_data = track;
212 }
213
214 if (call_graph)
215 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
216
217 if (system_wide)
218 attr->sample_type |= PERF_SAMPLE_CPU;
219
220 if (sample_id_all_avail &&
221 (sample_time || system_wide || !no_inherit || cpu_list))
222 attr->sample_type |= PERF_SAMPLE_TIME;
223
224 if (raw_samples) {
225 attr->sample_type |= PERF_SAMPLE_TIME;
226 attr->sample_type |= PERF_SAMPLE_RAW;
227 attr->sample_type |= PERF_SAMPLE_CPU;
228 }
229
230 if (nodelay) {
231 attr->watermark = 0;
232 attr->wakeup_events = 1;
233 }
234
235 attr->mmap = track;
236 attr->comm = track;
237
238 if (target_pid == -1 && target_tid == -1 && !system_wide) {
239 attr->disabled = 1;
240 attr->enable_on_exec = 1;
241 }
242}
243
244static bool perf_evlist__equal(struct perf_evlist *evlist, 163static bool perf_evlist__equal(struct perf_evlist *evlist,
245 struct perf_evlist *other) 164 struct perf_evlist *other)
246{ 165{
@@ -264,11 +183,10 @@ static void open_counters(struct perf_evlist *evlist)
264{ 183{
265 struct perf_evsel *pos, *first; 184 struct perf_evsel *pos, *first;
266 185
267 if (evlist->cpus->map[0] < 0)
268 no_inherit = true;
269
270 first = list_entry(evlist->entries.next, struct perf_evsel, node); 186 first = list_entry(evlist->entries.next, struct perf_evsel, node);
271 187
188 perf_evlist__config_attrs(evlist, &record_opts);
189
272 list_for_each_entry(pos, &evlist->entries, node) { 190 list_for_each_entry(pos, &evlist->entries, node) {
273 struct perf_event_attr *attr = &pos->attr; 191 struct perf_event_attr *attr = &pos->attr;
274 struct xyarray *group_fd = NULL; 192 struct xyarray *group_fd = NULL;
@@ -288,10 +206,8 @@ static void open_counters(struct perf_evlist *evlist)
288 206
289 if (group && pos != first) 207 if (group && pos != first)
290 group_fd = first->fd; 208 group_fd = first->fd;
291
292 config_attr(pos, evlist);
293retry_sample_id: 209retry_sample_id:
294 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 210 attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
295try_again: 211try_again:
296 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 212 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
297 group_fd) < 0) { 213 group_fd) < 0) {
@@ -300,15 +216,15 @@ try_again:
300 if (err == EPERM || err == EACCES) { 216 if (err == EPERM || err == EACCES) {
301 ui__error_paranoid(); 217 ui__error_paranoid();
302 exit(EXIT_FAILURE); 218 exit(EXIT_FAILURE);
303 } else if (err == ENODEV && cpu_list) { 219 } else if (err == ENODEV && record_opts.cpu_list) {
304 die("No such device - did you specify" 220 die("No such device - did you specify"
305 " an out-of-range profile CPU?\n"); 221 " an out-of-range profile CPU?\n");
306 } else if (err == EINVAL && sample_id_all_avail) { 222 } else if (err == EINVAL && record_opts.sample_id_all_avail) {
307 /* 223 /*
308 * Old kernel, no attr->sample_id_type_all field 224 * Old kernel, no attr->sample_id_type_all field
309 */ 225 */
310 sample_id_all_avail = false; 226 record_opts.sample_id_all_avail = false;
311 if (!sample_time && !raw_samples && !time_needed) 227 if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
312 attr->sample_type &= ~PERF_SAMPLE_TIME; 228 attr->sample_type &= ~PERF_SAMPLE_TIME;
313 229
314 goto retry_sample_id; 230 goto retry_sample_id;
@@ -482,13 +398,13 @@ static int __cmd_record(int argc, const char **argv)
482 398
483 if (!output_name) { 399 if (!output_name) {
484 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 400 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
485 pipe_output = 1; 401 pipe_output = true;
486 else 402 else
487 output_name = "perf.data"; 403 output_name = "perf.data";
488 } 404 }
489 if (output_name) { 405 if (output_name) {
490 if (!strcmp(output_name, "-")) 406 if (!strcmp(output_name, "-"))
491 pipe_output = 1; 407 pipe_output = true;
492 else if (!stat(output_name, &st) && st.st_size) { 408 else if (!stat(output_name, &st) && st.st_size) {
493 if (write_mode == WRITE_FORCE) { 409 if (write_mode == WRITE_FORCE) {
494 char oldname[PATH_MAX]; 410 char oldname[PATH_MAX];
@@ -592,7 +508,7 @@ static int __cmd_record(int argc, const char **argv)
592 exit(-1); 508 exit(-1);
593 } 509 }
594 510
595 if (!system_wide && target_tid == -1 && target_pid == -1) 511 if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
596 evsel_list->threads->map[0] = child_pid; 512 evsel_list->threads->map[0] = child_pid;
597 513
598 close(child_ready_pipe[1]); 514 close(child_ready_pipe[1]);
@@ -689,7 +605,7 @@ static int __cmd_record(int argc, const char **argv)
689 perf_session__process_machines(session, 605 perf_session__process_machines(session,
690 perf_event__synthesize_guest_os); 606 perf_event__synthesize_guest_os);
691 607
692 if (!system_wide) 608 if (!record_opts.system_wide)
693 perf_event__synthesize_thread_map(evsel_list->threads, 609 perf_event__synthesize_thread_map(evsel_list->threads,
694 process_synthesized_event, 610 process_synthesized_event,
695 session); 611 session);
@@ -766,44 +682,44 @@ const struct option record_options[] = {
766 parse_events_option), 682 parse_events_option),
767 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 683 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
768 "event filter", parse_filter), 684 "event filter", parse_filter),
769 OPT_INTEGER('p', "pid", &target_pid, 685 OPT_INTEGER('p', "pid", &record_opts.target_pid,
770 "record events on existing process id"), 686 "record events on existing process id"),
771 OPT_INTEGER('t', "tid", &target_tid, 687 OPT_INTEGER('t', "tid", &record_opts.target_tid,
772 "record events on existing thread id"), 688 "record events on existing thread id"),
773 OPT_INTEGER('r', "realtime", &realtime_prio, 689 OPT_INTEGER('r', "realtime", &realtime_prio,
774 "collect data with this RT SCHED_FIFO priority"), 690 "collect data with this RT SCHED_FIFO priority"),
775 OPT_BOOLEAN('D', "no-delay", &nodelay, 691 OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
776 "collect data without buffering"), 692 "collect data without buffering"),
777 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 693 OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
778 "collect raw sample records from all opened counters"), 694 "collect raw sample records from all opened counters"),
779 OPT_BOOLEAN('a', "all-cpus", &system_wide, 695 OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
780 "system-wide collection from all CPUs"), 696 "system-wide collection from all CPUs"),
781 OPT_BOOLEAN('A', "append", &append_file, 697 OPT_BOOLEAN('A', "append", &append_file,
782 "append to the output file to do incremental profiling"), 698 "append to the output file to do incremental profiling"),
783 OPT_STRING('C', "cpu", &cpu_list, "cpu", 699 OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
784 "list of cpus to monitor"), 700 "list of cpus to monitor"),
785 OPT_BOOLEAN('f', "force", &force, 701 OPT_BOOLEAN('f', "force", &force,
786 "overwrite existing data file (deprecated)"), 702 "overwrite existing data file (deprecated)"),
787 OPT_U64('c', "count", &user_interval, "event period to sample"), 703 OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
788 OPT_STRING('o', "output", &output_name, "file", 704 OPT_STRING('o', "output", &output_name, "file",
789 "output file name"), 705 "output file name"),
790 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 706 OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
791 "child tasks do not inherit counters"), 707 "child tasks do not inherit counters"),
792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 708 OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
793 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 709 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
794 OPT_BOOLEAN(0, "group", &group, 710 OPT_BOOLEAN(0, "group", &group,
795 "put the counters into a counter group"), 711 "put the counters into a counter group"),
796 OPT_BOOLEAN('g', "call-graph", &call_graph, 712 OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
797 "do call-graph (stack chain/backtrace) recording"), 713 "do call-graph (stack chain/backtrace) recording"),
798 OPT_INCR('v', "verbose", &verbose, 714 OPT_INCR('v', "verbose", &verbose,
799 "be more verbose (show counter open errors, etc)"), 715 "be more verbose (show counter open errors, etc)"),
800 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 716 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
801 OPT_BOOLEAN('s', "stat", &inherit_stat, 717 OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
802 "per thread counts"), 718 "per thread counts"),
803 OPT_BOOLEAN('d', "data", &sample_address, 719 OPT_BOOLEAN('d', "data", &record_opts.sample_address,
804 "Sample addresses"), 720 "Sample addresses"),
805 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 721 OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
806 OPT_BOOLEAN('n', "no-samples", &no_samples, 722 OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
807 "don't sample"), 723 "don't sample"),
808 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 724 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
809 "do not update the buildid cache"), 725 "do not update the buildid cache"),
@@ -828,8 +744,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
828 744
829 argc = parse_options(argc, argv, record_options, record_usage, 745 argc = parse_options(argc, argv, record_options, record_usage,
830 PARSE_OPT_STOP_AT_NON_OPTION); 746 PARSE_OPT_STOP_AT_NON_OPTION);
831 if (!argc && target_pid == -1 && target_tid == -1 && 747 if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
832 !system_wide && !cpu_list) 748 !record_opts.system_wide && !record_opts.cpu_list)
833 usage_with_options(record_usage, record_options); 749 usage_with_options(record_usage, record_options);
834 750
835 if (force && append_file) { 751 if (force && append_file) {
@@ -842,7 +758,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
842 write_mode = WRITE_FORCE; 758 write_mode = WRITE_FORCE;
843 } 759 }
844 760
845 if (nr_cgroups && !system_wide) { 761 if (nr_cgroups && !record_opts.system_wide) {
846 fprintf(stderr, "cgroup monitoring only available in" 762 fprintf(stderr, "cgroup monitoring only available in"
847 " system-wide mode\n"); 763 " system-wide mode\n");
848 usage_with_options(record_usage, record_options); 764 usage_with_options(record_usage, record_options);
@@ -869,11 +785,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
869 goto out_symbol_exit; 785 goto out_symbol_exit;
870 } 786 }
871 787
872 if (target_pid != -1) 788 if (record_opts.target_pid != -1)
873 target_tid = target_pid; 789 record_opts.target_tid = record_opts.target_pid;
874 790
875 if (perf_evlist__create_maps(evsel_list, target_pid, 791 if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
876 target_tid, cpu_list) < 0) 792 record_opts.target_tid, record_opts.cpu_list) < 0)
877 usage_with_options(record_usage, record_options); 793 usage_with_options(record_usage, record_options);
878 794
879 list_for_each_entry(pos, &evsel_list->entries, node) { 795 list_for_each_entry(pos, &evsel_list->entries, node) {
@@ -887,18 +803,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
887 if (perf_evlist__alloc_pollfd(evsel_list) < 0) 803 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
888 goto out_free_fd; 804 goto out_free_fd;
889 805
890 if (user_interval != ULLONG_MAX) 806 if (record_opts.user_interval != ULLONG_MAX)
891 default_interval = user_interval; 807 record_opts.default_interval = record_opts.user_interval;
892 if (user_freq != UINT_MAX) 808 if (record_opts.user_freq != UINT_MAX)
893 freq = user_freq; 809 record_opts.freq = record_opts.user_freq;
894 810
895 /* 811 /*
896 * User specified count overrides default frequency. 812 * User specified count overrides default frequency.
897 */ 813 */
898 if (default_interval) 814 if (record_opts.default_interval)
899 freq = 0; 815 record_opts.freq = 0;
900 else if (freq) { 816 else if (record_opts.freq) {
901 default_interval = freq; 817 record_opts.default_interval = record_opts.freq;
902 } else { 818 } else {
903 fprintf(stderr, "frequency and count are zero, aborting\n"); 819 fprintf(stderr, "frequency and count are zero, aborting\n");
904 err = -EINVAL; 820 err = -EINVAL;