diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 144 |
1 files changed, 123 insertions, 21 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dbb2c02cd706..5dfe91395617 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -112,6 +112,32 @@ out: return rc; } +static volatile int done; +static volatile int signr = -1; +static volatile int child_finished; +static volatile int auxtrace_snapshot_enabled; +static volatile int auxtrace_snapshot_err; +static volatile int auxtrace_record__snapshot_started; + +static void sig_handler(int sig) +{ + if (sig == SIGCHLD) + child_finished = 1; + else + signr = sig; + + done = 1; +} + +static void record__sig_exit(void) +{ + if (signr == -1) + return; + + signal(signr, SIG_DFL); + raise(signr); +} + #ifdef HAVE_AUXTRACE_SUPPORT static int record__process_auxtrace(struct perf_tool *tool, @@ -167,6 +193,56 @@ static int record__auxtrace_mmap_read(struct record *rec, return 0; } +static int record__auxtrace_mmap_read_snapshot(struct record *rec, + struct auxtrace_mmap *mm) +{ + int ret; + + ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, + record__process_auxtrace, + rec->opts.auxtrace_snapshot_size); + if (ret < 0) + return ret; + + if (ret) + rec->samples++; + + return 0; +} + +static int record__auxtrace_read_snapshot_all(struct record *rec) +{ + int i; + int rc = 0; + + for (i = 0; i < rec->evlist->nr_mmaps; i++) { + struct auxtrace_mmap *mm = + &rec->evlist->mmap[i].auxtrace_mmap; + + if (!mm->base) + continue; + + if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { + rc = -1; + goto out; + } + } +out: + return rc; +} + +static void record__read_auxtrace_snapshot(struct record *rec) +{ + pr_debug("Recording AUX area tracing snapshot\n"); + if (record__auxtrace_read_snapshot_all(rec) < 0) { + auxtrace_snapshot_err = -1; + } else { + auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); + if (!auxtrace_snapshot_err) + auxtrace_snapshot_enabled = 1; + } +} + #else static inline @@ -176,31 +252,19 @@ int record__auxtrace_mmap_read(struct record *rec __maybe_unused, return 0; } -#endif - -static volatile int done = 0; -static volatile int signr = -1; -static volatile int child_finished = 0; - -static void sig_handler(int sig) +static inline +void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) { - if (sig == SIGCHLD) - child_finished = 1; - else - signr = sig; - - done = 1; } -static void record__sig_exit(void) +static inline +int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) { - if (signr == -1) - return; - - signal(signr, SIG_DFL); - raise(signr); + return 0; } +#endif + static int record__open(struct record *rec) { char msg[512]; @@ -238,7 +302,8 @@ try_again: } if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, - opts->auxtrace_mmap_pages, false) < 0) { + opts->auxtrace_mmap_pages, + opts->auxtrace_snapshot_mode) < 0) { if (errno == EPERM) { pr_err("Permission error mapping pages.\n" "Consider increasing " @@ -349,7 +414,7 @@ static int record__mmap_read_all(struct record *rec) } } - if (mm->base && + if (mm->base && !rec->opts.auxtrace_snapshot_mode && record__auxtrace_mmap_read(rec, mm) != 0) { rc = -1; goto out; @@ -404,6 +469,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused, child_finished = 1; } +static void snapshot_sig_handler(int sig); + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -424,6 +491,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); + if (rec->opts.auxtrace_snapshot_mode) + signal(SIGUSR2, snapshot_sig_handler); + else + signal(SIGUSR2, SIG_IGN); session = perf_session__new(file, false, tool); if (session == NULL) { @@ -563,14 +634,27 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) perf_evlist__enable(rec->evlist); } + auxtrace_snapshot_enabled = 1; for (;;) { int hits = rec->samples; if (record__mmap_read_all(rec) < 0) { + auxtrace_snapshot_enabled = 0; err = -1; goto out_child; } + if (auxtrace_record__snapshot_started) { + auxtrace_record__snapshot_started = 0; + if (!auxtrace_snapshot_err) + record__read_auxtrace_snapshot(rec); + if (auxtrace_snapshot_err) { + pr_err("AUX area tracing snapshot failed\n"); + err = -1; + goto out_child; + } + } + if (hits == rec->samples) { if (done || draining) break; @@ -593,10 +677,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * disable events in this case. */ if (done && !disabled && !target__none(&opts->target)) { + auxtrace_snapshot_enabled = 0; perf_evlist__disable(rec->evlist); disabled = true; } } + auxtrace_snapshot_enabled = 0; if (forks && workload_exec_errno) { char msg[STRERR_BUFSIZE]; @@ -1068,6 +1154,8 @@ struct option __record_options[] = { OPT_CALLBACK('k', "clockid", &record.opts, "clockid", "clockid to use for events, see clock_gettime()", parse_clockid), + OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, + "opts", "AUX area tracing Snapshot Mode", ""), OPT_END() }; @@ -1102,6 +1190,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) return err; } + err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, + rec->opts.auxtrace_snapshot_opts); + if (err) + return err; + err = -ENOMEM; symbol__init(NULL); @@ -1165,3 +1258,12 @@ out_symbol_exit: auxtrace_record__free(rec->itr); return err; } + +static void snapshot_sig_handler(int sig __maybe_unused) +{ + if (!auxtrace_snapshot_enabled) + return; + auxtrace_snapshot_enabled = 0; + auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); + auxtrace_record__snapshot_started = 1; +} |