diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index c1f44633abed8025e6f106fa19f3fabc9b37bc73..768888b9326a7d2e4bdf9480a89f9271885f7fa0 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -635,10 +635,10 @@ endif::HAVE_LIBPFM[] --control=fd:ctl-fd[,ack-fd]:: ctl-fifo / ack-fifo are opened and used as ctl-fd / ack-fd as follows. Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, -'disable': disable events). Measurements can be started with events disabled using ---delay=-1 option. Optionally send control command completion ('ack\n') to ack-fd descriptor -to synchronize with the controlling process. Example of bash shell script to enable and -disable events during measurements: +'disable': disable events, 'snapshot': AUX area tracing snapshot). Measurements can be +started with events disabled using --delay=-1 option. Optionally send control command +completion ('ack\n') to ack-fd descriptor to synchronize with the controlling process. +Example of bash shell script to enable and disable events during measurements: #!/bin/bash diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index c83aec4940de7594656184e494a1753f30933a4d..d0f9f8107f47eaad4daca3da8e77b3d8ec675e47 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1593,6 +1593,16 @@ static int record__init_clock(struct record *rec) return 0; } +static void hit_auxtrace_snapshot_trigger(struct record *rec) +{ + if (trigger_is_ready(&auxtrace_snapshot_trigger)) { + trigger_hit(&auxtrace_snapshot_trigger); + auxtrace_record__snapshot_started = 1; + if (auxtrace_record__snapshot_start(rec->itr)) + trigger_error(&auxtrace_snapshot_trigger); + } +} + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -1937,6 +1947,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) case EVLIST_CTL_CMD_DISABLE: pr_info(EVLIST_DISABLED_MSG); break; + case EVLIST_CTL_CMD_SNAPSHOT: + hit_auxtrace_snapshot_trigger(rec); + evlist__ctlfd_ack(rec->evlist); + break; case EVLIST_CTL_CMD_ACK: case EVLIST_CTL_CMD_UNSUPPORTED: default: @@ -2589,7 +2603,8 @@ static struct option __record_options[] = { parse_libpfm_events_option), #endif OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]", - "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n" + "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events,\n" + "\t\t\t 'snapshot': AUX area tracing snapshot).\n" "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n" "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.", parse_control_option), @@ -2842,12 +2857,7 @@ static void snapshot_sig_handler(int sig __maybe_unused) { struct record *rec = &record; - if (trigger_is_ready(&auxtrace_snapshot_trigger)) { - trigger_hit(&auxtrace_snapshot_trigger); - auxtrace_record__snapshot_started = 1; - if (auxtrace_record__snapshot_start(record.itr)) - trigger_error(&auxtrace_snapshot_trigger); - } + hit_auxtrace_snapshot_trigger(rec); if (switch_output_signal(rec)) trigger_hit(&switch_output_trigger); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 14688710195cb8e77cd98086032f02b48c3188da..6562a9bdfa385460d93720a9d7854b3a2fa9575a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -578,6 +578,7 @@ static void process_evlist(struct evlist *evlist, unsigned int interval) process_interval(); pr_info(EVLIST_DISABLED_MSG); break; + case EVLIST_CTL_CMD_SNAPSHOT: case EVLIST_CTL_CMD_ACK: case EVLIST_CTL_CMD_UNSUPPORTED: default: diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 00593e5f2a9d58c32775d39d72227c9bbc82309c..e72ff7e78dec2239fd170e9fe6f9d5cfde8849e6 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1887,13 +1887,17 @@ static int evlist__ctlfd_recv(struct evlist *evlist, enum evlist_ctl_cmd *cmd, } else if (!strncmp(cmd_data, EVLIST_CTL_CMD_DISABLE_TAG, (sizeof(EVLIST_CTL_CMD_DISABLE_TAG)-1))) { *cmd = EVLIST_CTL_CMD_DISABLE; + } else if (!strncmp(cmd_data, EVLIST_CTL_CMD_SNAPSHOT_TAG, + (sizeof(EVLIST_CTL_CMD_SNAPSHOT_TAG)-1))) { + *cmd = EVLIST_CTL_CMD_SNAPSHOT; + pr_debug("is snapshot\n"); } } return bytes_read ? (int)bytes_read : err; } -static int evlist__ctlfd_ack(struct evlist *evlist) +int evlist__ctlfd_ack(struct evlist *evlist) { int err; @@ -1929,13 +1933,16 @@ int evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd) case EVLIST_CTL_CMD_DISABLE: evlist__disable(evlist); break; + case EVLIST_CTL_CMD_SNAPSHOT: + break; case EVLIST_CTL_CMD_ACK: case EVLIST_CTL_CMD_UNSUPPORTED: default: pr_debug("ctlfd: unsupported %d\n", *cmd); break; } - if (!(*cmd == EVLIST_CTL_CMD_ACK || *cmd == EVLIST_CTL_CMD_UNSUPPORTED)) + if (!(*cmd == EVLIST_CTL_CMD_ACK || *cmd == EVLIST_CTL_CMD_UNSUPPORTED || + *cmd == EVLIST_CTL_CMD_SNAPSHOT)) evlist__ctlfd_ack(evlist); } } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a5678eb5ee6012c3bff8a06dea073f140b72db94..91d1da6e1fe397793d7421ca51af816c13a34eab 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -363,6 +363,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist, #define EVLIST_CTL_CMD_ENABLE_TAG "enable" #define EVLIST_CTL_CMD_DISABLE_TAG "disable" #define EVLIST_CTL_CMD_ACK_TAG "ack\n" +#define EVLIST_CTL_CMD_SNAPSHOT_TAG "snapshot" #define EVLIST_CTL_CMD_MAX_LEN 64 @@ -370,7 +371,8 @@ enum evlist_ctl_cmd { EVLIST_CTL_CMD_UNSUPPORTED = 0, EVLIST_CTL_CMD_ENABLE, EVLIST_CTL_CMD_DISABLE, - EVLIST_CTL_CMD_ACK + EVLIST_CTL_CMD_ACK, + EVLIST_CTL_CMD_SNAPSHOT, }; int evlist__parse_control(const char *str, int *ctl_fd, int *ctl_fd_ack, bool *ctl_fd_close); @@ -378,6 +380,7 @@ int evlist__initialize_ctlfd(struct evlist *evlist, int ctl_fd, int ctl_fd_ack); int evlist__finalize_ctlfd(struct evlist *evlist); bool evlist__ctlfd_initialized(struct evlist *evlist); int evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd); +int evlist__ctlfd_ack(struct evlist *evlist); #define EVLIST_ENABLED_MSG "Events enabled\n" #define EVLIST_DISABLED_MSG "Events disabled\n"