aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-11-08 11:41:57 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 07:25:31 -0500
commit0f82ebc452f921590e216b28eee0b41f5e434a48 (patch)
tree96f8f0df01f362f3184e3dbc1137809e4d0aa065 /tools/perf/builtin-record.c
parenta8c9ae18d810e1ae12b6ec960907e9af63171d3a (diff)
perf evsel: Introduce config attr method
Out of the code in 'perf record', so that we can share option parsing, etc. Eventually will be used by 'perf top', but first 'trace' will use it. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-hzjqsgnte1esk90ytq0ap98v@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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;