Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf record: Add AUX area tracing Snapshot Mode support

Add a new option and support for Instruction Tracing Snapshot Mode.
When the new option is selected, no AUX area tracing data is captured
until a signal (SIGUSR2) is received.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-10-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
2dd6d8a1 d20031bb

+149 -25
+7
tools/perf/Documentation/perf-record.txt
··· 259 259 CLOCK_MONOTONIC_RAW are supported, some events might also allow 260 260 CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI. 261 261 262 + -S:: 263 + --snapshot:: 264 + Select AUX area tracing Snapshot Mode. This option is valid only with an 265 + AUX area tracing event. Optionally the number of bytes to capture per 266 + snapshot can be specified. In Snapshot Mode, trace data is captured only when 267 + signal SIGUSR2 is received. 268 + 262 269 SEE ALSO 263 270 -------- 264 271 linkperf:perf-stat[1], linkperf:perf-list[1]
+127 -25
tools/perf/builtin-record.c
··· 112 112 return rc; 113 113 } 114 114 115 + static volatile int done; 116 + static volatile int signr = -1; 117 + static volatile int child_finished; 118 + static volatile int auxtrace_snapshot_enabled; 119 + static volatile int auxtrace_snapshot_err; 120 + static volatile int auxtrace_record__snapshot_started; 121 + 122 + static void sig_handler(int sig) 123 + { 124 + if (sig == SIGCHLD) 125 + child_finished = 1; 126 + else 127 + signr = sig; 128 + 129 + done = 1; 130 + } 131 + 132 + static void record__sig_exit(void) 133 + { 134 + if (signr == -1) 135 + return; 136 + 137 + signal(signr, SIG_DFL); 138 + raise(signr); 139 + } 140 + 115 141 #ifdef HAVE_AUXTRACE_SUPPORT 116 142 117 143 static int record__process_auxtrace(struct perf_tool *tool, ··· 193 167 return 0; 194 168 } 195 169 170 + static int record__auxtrace_mmap_read_snapshot(struct record *rec, 171 + struct auxtrace_mmap *mm) 172 + { 173 + int ret; 174 + 175 + ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 176 + record__process_auxtrace, 177 + rec->opts.auxtrace_snapshot_size); 178 + if (ret < 0) 179 + return ret; 180 + 181 + if (ret) 182 + rec->samples++; 183 + 184 + return 0; 185 + } 186 + 187 + static int record__auxtrace_read_snapshot_all(struct record *rec) 188 + { 189 + int i; 190 + int rc = 0; 191 + 192 + for (i = 0; i < rec->evlist->nr_mmaps; i++) { 193 + struct auxtrace_mmap *mm = 194 + &rec->evlist->mmap[i].auxtrace_mmap; 195 + 196 + if (!mm->base) 197 + continue; 198 + 199 + if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 200 + rc = -1; 201 + goto out; 202 + } 203 + } 204 + out: 205 + return rc; 206 + } 207 + 208 + static void record__read_auxtrace_snapshot(struct record *rec) 209 + { 210 + pr_debug("Recording AUX area tracing snapshot\n"); 211 + if (record__auxtrace_read_snapshot_all(rec) < 0) { 212 + auxtrace_snapshot_err = -1; 213 + } else { 214 + auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 215 + if (!auxtrace_snapshot_err) 216 + auxtrace_snapshot_enabled = 1; 217 + } 218 + } 219 + 196 220 #else 197 221 198 222 static inline ··· 252 176 return 0; 253 177 } 254 178 179 + static inline 180 + void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 181 + { 182 + } 183 + 184 + static inline 185 + int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 186 + { 187 + return 0; 188 + } 189 + 255 190 #endif 256 - 257 - static volatile int done = 0; 258 - static volatile int signr = -1; 259 - static volatile int child_finished = 0; 260 - 261 - static void sig_handler(int sig) 262 - { 263 - if (sig == SIGCHLD) 264 - child_finished = 1; 265 - else 266 - signr = sig; 267 - 268 - done = 1; 269 - } 270 - 271 - static void record__sig_exit(void) 272 - { 273 - if (signr == -1) 274 - return; 275 - 276 - signal(signr, SIG_DFL); 277 - raise(signr); 278 - } 279 191 280 192 static int record__open(struct record *rec) 281 193 { ··· 302 238 } 303 239 304 240 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 305 - opts->auxtrace_mmap_pages, false) < 0) { 241 + opts->auxtrace_mmap_pages, 242 + opts->auxtrace_snapshot_mode) < 0) { 306 243 if (errno == EPERM) { 307 244 pr_err("Permission error mapping pages.\n" 308 245 "Consider increasing " ··· 414 349 } 415 350 } 416 351 417 - if (mm->base && 352 + if (mm->base && !rec->opts.auxtrace_snapshot_mode && 418 353 record__auxtrace_mmap_read(rec, mm) != 0) { 419 354 rc = -1; 420 355 goto out; ··· 469 404 child_finished = 1; 470 405 } 471 406 407 + static void snapshot_sig_handler(int sig); 408 + 472 409 static int __cmd_record(struct record *rec, int argc, const char **argv) 473 410 { 474 411 int err; ··· 491 424 signal(SIGCHLD, sig_handler); 492 425 signal(SIGINT, sig_handler); 493 426 signal(SIGTERM, sig_handler); 427 + if (rec->opts.auxtrace_snapshot_mode) 428 + signal(SIGUSR2, snapshot_sig_handler); 429 + else 430 + signal(SIGUSR2, SIG_IGN); 494 431 495 432 session = perf_session__new(file, false, tool); 496 433 if (session == NULL) { ··· 634 563 perf_evlist__enable(rec->evlist); 635 564 } 636 565 566 + auxtrace_snapshot_enabled = 1; 637 567 for (;;) { 638 568 int hits = rec->samples; 639 569 640 570 if (record__mmap_read_all(rec) < 0) { 571 + auxtrace_snapshot_enabled = 0; 641 572 err = -1; 642 573 goto out_child; 574 + } 575 + 576 + if (auxtrace_record__snapshot_started) { 577 + auxtrace_record__snapshot_started = 0; 578 + if (!auxtrace_snapshot_err) 579 + record__read_auxtrace_snapshot(rec); 580 + if (auxtrace_snapshot_err) { 581 + pr_err("AUX area tracing snapshot failed\n"); 582 + err = -1; 583 + goto out_child; 584 + } 643 585 } 644 586 645 587 if (hits == rec->samples) { ··· 677 593 * disable events in this case. 678 594 */ 679 595 if (done && !disabled && !target__none(&opts->target)) { 596 + auxtrace_snapshot_enabled = 0; 680 597 perf_evlist__disable(rec->evlist); 681 598 disabled = true; 682 599 } 683 600 } 601 + auxtrace_snapshot_enabled = 0; 684 602 685 603 if (forks && workload_exec_errno) { 686 604 char msg[STRERR_BUFSIZE]; ··· 1154 1068 OPT_CALLBACK('k', "clockid", &record.opts, 1155 1069 "clockid", "clockid to use for events, see clock_gettime()", 1156 1070 parse_clockid), 1071 + OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 1072 + "opts", "AUX area tracing Snapshot Mode", ""), 1157 1073 OPT_END() 1158 1074 }; 1159 1075 ··· 1189 1101 if (err) 1190 1102 return err; 1191 1103 } 1104 + 1105 + err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 1106 + rec->opts.auxtrace_snapshot_opts); 1107 + if (err) 1108 + return err; 1192 1109 1193 1110 err = -ENOMEM; 1194 1111 ··· 1257 1164 symbol__exit(); 1258 1165 auxtrace_record__free(rec->itr); 1259 1166 return err; 1167 + } 1168 + 1169 + static void snapshot_sig_handler(int sig __maybe_unused) 1170 + { 1171 + if (!auxtrace_snapshot_enabled) 1172 + return; 1173 + auxtrace_snapshot_enabled = 0; 1174 + auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 1175 + auxtrace_record__snapshot_started = 1; 1260 1176 }
+11
tools/perf/util/auxtrace.h
··· 564 564 } 565 565 566 566 static inline 567 + int auxtrace_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused, 568 + struct record_opts *opts __maybe_unused, 569 + const char *str) 570 + { 571 + if (!str) 572 + return 0; 573 + pr_err("AUX area tracing not supported\n"); 574 + return -EINVAL; 575 + } 576 + 577 + static inline 567 578 int auxtrace__process_event(struct perf_session *session __maybe_unused, 568 579 union perf_event *event __maybe_unused, 569 580 struct perf_sample *sample __maybe_unused,
+4
tools/perf/util/parse-options.h
··· 123 123 #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 124 124 #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 125 125 #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } 126 + #define OPT_STRING_OPTARG(s, l, v, a, h, d) \ 127 + { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ 128 + .value = check_vtype(v, const char **), (a), .help = (h), \ 129 + .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } 126 130 #define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} 127 131 #define OPT_DATE(s, l, v, h) \ 128 132 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }