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.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9231659754d..f3151d3c70ce 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,38 @@
31#include <sched.h> 31#include <sched.h>
32#include <sys/mman.h> 32#include <sys/mman.h>
33 33
34#ifndef HAVE_ON_EXIT
35#ifndef ATEXIT_MAX
36#define ATEXIT_MAX 32
37#endif
38static int __on_exit_count = 0;
39typedef void (*on_exit_func_t) (int, void *);
40static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
41static void *__on_exit_args[ATEXIT_MAX];
42static int __exitcode = 0;
43static void __handle_on_exit_funcs(void);
44static int on_exit(on_exit_func_t function, void *arg);
45#define exit(x) (exit)(__exitcode = (x))
46
47static int on_exit(on_exit_func_t function, void *arg)
48{
49 if (__on_exit_count == ATEXIT_MAX)
50 return -ENOMEM;
51 else if (__on_exit_count == 0)
52 atexit(__handle_on_exit_funcs);
53 __on_exit_funcs[__on_exit_count] = function;
54 __on_exit_args[__on_exit_count++] = arg;
55 return 0;
56}
57
58static void __handle_on_exit_funcs(void)
59{
60 int i;
61 for (i = 0; i < __on_exit_count; i++)
62 __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
63}
64#endif
65
34enum write_mode_t { 66enum write_mode_t {
35 WRITE_FORCE, 67 WRITE_FORCE,
36 WRITE_APPEND 68 WRITE_APPEND
@@ -198,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)
198 struct perf_record_opts *opts = &rec->opts; 230 struct perf_record_opts *opts = &rec->opts;
199 int rc = 0; 231 int rc = 0;
200 232
201 perf_evlist__config_attrs(evlist, opts); 233 /*
202 234 * Set the evsel leader links before we configure attributes,
235 * since some might depend on this info.
236 */
203 if (opts->group) 237 if (opts->group)
204 perf_evlist__set_leader(evlist); 238 perf_evlist__set_leader(evlist);
205 239
240 perf_evlist__config_attrs(evlist, opts);
241
206 list_for_each_entry(pos, &evlist->entries, node) { 242 list_for_each_entry(pos, &evlist->entries, node) {
207 struct perf_event_attr *attr = &pos->attr; 243 struct perf_event_attr *attr = &pos->attr;
208 /* 244 /*
@@ -285,6 +321,11 @@ try_again:
285 perf_evsel__name(pos)); 321 perf_evsel__name(pos));
286 rc = -err; 322 rc = -err;
287 goto out; 323 goto out;
324 } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
325 ui__error("\'precise\' request may not be supported. "
326 "Try removing 'p' modifier\n");
327 rc = -err;
328 goto out;
288 } 329 }
289 330
290 printf("\n"); 331 printf("\n");
@@ -326,7 +367,8 @@ try_again:
326 "or try again with a smaller value of -m/--mmap_pages.\n" 367 "or try again with a smaller value of -m/--mmap_pages.\n"
327 "(current value: %d)\n", opts->mmap_pages); 368 "(current value: %d)\n", opts->mmap_pages);
328 rc = -errno; 369 rc = -errno;
329 } else if (!is_power_of_2(opts->mmap_pages)) { 370 } else if (!is_power_of_2(opts->mmap_pages) &&
371 (opts->mmap_pages != UINT_MAX)) {
330 pr_err("--mmap_pages/-m value must be a power of two."); 372 pr_err("--mmap_pages/-m value must be a power of two.");
331 rc = -EINVAL; 373 rc = -EINVAL;
332 } else { 374 } else {
@@ -460,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
460 struct perf_evlist *evsel_list = rec->evlist; 502 struct perf_evlist *evsel_list = rec->evlist;
461 const char *output_name = rec->output_name; 503 const char *output_name = rec->output_name;
462 struct perf_session *session; 504 struct perf_session *session;
505 bool disabled = false;
463 506
464 rec->progname = argv[0]; 507 rec->progname = argv[0];
465 508
@@ -659,7 +702,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
659 } 702 }
660 } 703 }
661 704
662 perf_evlist__enable(evsel_list); 705 /*
706 * When perf is starting the traced process, all the events
707 * (apart from group members) have enable_on_exec=1 set,
708 * so don't spoil it by prematurely enabling them.
709 */
710 if (!perf_target__none(&opts->target))
711 perf_evlist__enable(evsel_list);
663 712
664 /* 713 /*
665 * Let the child rip 714 * Let the child rip
@@ -682,8 +731,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
682 waking++; 731 waking++;
683 } 732 }
684 733
685 if (done) 734 /*
735 * When perf is starting the traced process, at the end events
736 * die with the process and we wait for that. Thus no need to
737 * disable events in this case.
738 */
739 if (done && !disabled && !perf_target__none(&opts->target)) {
686 perf_evlist__disable(evsel_list); 740 perf_evlist__disable(evsel_list);
741 disabled = true;
742 }
687 } 743 }
688 744
689 if (quiet || signr == SIGUSR1) 745 if (quiet || signr == SIGUSR1)