Messages in this thread Patch in this message |  | | From | Alexander Shishkin <> | Subject | [PATCH v0 59/71] perf record: Add Instruction Tracing Snapshot Mode support | Date | Wed, 11 Dec 2013 14:37:11 +0200 |
| |
From: Adrian Hunter <adrian.hunter@intel.com>
Add a new option and support for Instruction Tracing Snapshot Mode. When the new option is selected, no Instruction Tracing data is captured until a signal (SIGUSR2) is received.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- tools/perf/Documentation/perf-record.txt | 7 +++ tools/perf/builtin-record.c | 90 +++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 58bd3c1..279c808 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -216,6 +216,13 @@ if combined with -a or -C options. Enable Instruction Trace sampling. Each sample captures the specified number of bytes (default 4096) of trace. Instruction Tracing config can also be specified. +-S:: +--snapshot:: +Select Instruction Tracing Snapshot Mode. This option is valid only with an +Instruction Tracing event. Optionally the number of bytes to capture per +snapshot can be specified. In Snapshot Mode, trace data is captured only when +signal SIGUSR2 is received. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1] diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e75a15e..46c451c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -188,9 +188,29 @@ static int perf_record__itrace_mmap_read(struct perf_record *rec, return 0; } +static int perf_record__itrace_mmap_read_snapshot(struct perf_record *rec, + struct itrace_mmap *mm) +{ + int ret; + + ret = itrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, + perf_record__process_itrace, + rec->opts.itrace_snapshot_size); + if (ret < 0) + return ret; + + if (ret) + rec->samples++; + + return 0; +} + static volatile int done = 0; static volatile int signr = -1; static volatile int child_finished = 0; +static volatile int itrace_snapshot_enabled; +static volatile int itrace_snapshot_err; +static volatile int itrace_record__snapshot_started; static void sig_handler(int sig) { @@ -258,7 +278,7 @@ try_again: if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, opts->itrace_mmap_pages, - false) < 0) { + opts->itrace_snapshot_mode) < 0) { if (errno == EPERM) { pr_err("Permission error mapping pages.\n" "Consider increasing " @@ -368,7 +388,7 @@ static int perf_record__mmap_read_all(struct perf_record *rec) } } - if (mm->base && + if (mm->base && !rec->opts.itrace_snapshot_mode && perf_record__itrace_mmap_read(rec, mm) != 0) { rc = -1; goto out; @@ -405,6 +425,41 @@ static void perf_record__init_features(struct perf_record *rec) perf_header__clear_feat(&session->header, HEADER_ITRACE); } +static int perf_record__itrace_read_snapshot_all(struct perf_record *rec) +{ + int i; + int rc = 0; + + for (i = 0; i < rec->evlist->nr_mmaps; i++) { + struct itrace_mmap *mm = + &rec->evlist->mmap[i].itrace_mmap; + + if (!mm->base) + continue; + + if (perf_record__itrace_mmap_read_snapshot(rec, mm) != 0) { + rc = -1; + goto out; + } + } +out: + return rc; +} + +static void perf_record__read_itrace_snapshot(struct perf_record *rec) +{ + pr_debug("Recording instruction tracing snapshot\n"); + if (perf_record__itrace_read_snapshot_all(rec) < 0) { + itrace_snapshot_err = -1; + } else { + itrace_snapshot_err = itrace_record__snapshot_finish(rec->itr); + if (!itrace_snapshot_err) + itrace_snapshot_enabled = 1; + } +} + +static void snapshot_sig_handler(int sig); + static int __cmd_record(struct perf_record *rec, int argc, const char **argv) { int err; @@ -425,6 +480,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) signal(SIGINT, sig_handler); signal(SIGUSR1, sig_handler); signal(SIGTERM, sig_handler); + if (rec->opts.itrace_snapshot_mode) + signal(SIGUSR2, snapshot_sig_handler); + else + signal(SIGUSR2, SIG_IGN); session = perf_session__new(file, false, NULL); if (session == NULL) { @@ -574,14 +633,27 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (forks) perf_evlist__start_workload(evsel_list); + itrace_snapshot_enabled = 1; for (;;) { int hits = rec->samples; if (perf_record__mmap_read_all(rec) < 0) { + itrace_snapshot_enabled = 0; err = -1; goto out_delete_session; } + if (itrace_record__snapshot_started) { + itrace_record__snapshot_started = 0; + if (!itrace_snapshot_err) + perf_record__read_itrace_snapshot(rec); + if (itrace_snapshot_err) { + pr_err("Instruction tracing snapshot failed\n"); + err = -1; + goto out_delete_session; + } + } + if (hits == rec->samples) { if (done) break; @@ -595,10 +667,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) * disable events in this case. */ if (done && !disabled && !target__none(&opts->target)) { + itrace_snapshot_enabled = 0; perf_evlist__disable(evsel_list); disabled = true; } } + itrace_snapshot_enabled = 0; if (quiet || signr == SIGUSR1) return 0; @@ -998,6 +1072,9 @@ const struct option record_options[] = { OPT_CALLBACK_OPTARG('I', "itrace", &record.opts, &record.itr, "opts", "sample Instruction Trace", itrace_parse_sample_options), + OPT_CALLBACK_OPTARG('S', "snapshot", &record.opts, &record.itr, "opts", + "Instruction Tracing Snapshot Mode", + itrace_parse_snapshot_options), OPT_END() }; @@ -1096,3 +1173,12 @@ out_itrace_free: itrace_record__free(rec->itr); return err; } + +static void snapshot_sig_handler(int sig __maybe_unused) +{ + if (!itrace_snapshot_enabled) + return; + itrace_snapshot_enabled = 0; + itrace_snapshot_err = itrace_record__snapshot_start(record.itr); + itrace_record__snapshot_started = 1; +} -- 1.8.5.1
|  |