Commit 1d078ccb authored by Alexey Budankov's avatar Alexey Budankov Committed by Arnaldo Carvalho de Melo
Browse files

perf record: Introduce --control fd:ctl-fd[,ack-fd] options



Introduce --control fd:ctl-fd[,ack-fd] options to pass open file
descriptors numbers from command line.

Extend perf-record.txt file with --control fd:ctl-fd[,ack-fd] options
description.

Document possible usage model introduced by --control fd:ctl-fd[,ack-fd]
options by providing example bash shell script.

Signed-off-by: default avatarAlexey Budankov <alexey.budankov@linux.intel.com>
Acked-by: default avatarJiri Olsa <jolsa@redhat.com>
Acked-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/8dc01e1a-3a80-3f67-5385-4bc7112b0dd3@linux.intel.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent acce0223
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -627,6 +627,45 @@ option. The -e option and this one can be mixed and matched. Events
can be grouped using the {} notation.
endif::HAVE_LIBPFM[]

--control fd:ctl-fd[,ack-fd]
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:

#!/bin/bash

ctl_dir=/tmp/

ctl_fifo=${ctl_dir}perf_ctl.fifo
test -p ${ctl_fifo} && unlink ${ctl_fifo}
mkfifo ${ctl_fifo}
exec {ctl_fd}<>${ctl_fifo}

ctl_ack_fifo=${ctl_dir}perf_ctl_ack.fifo
test -p ${ctl_ack_fifo} && unlink ${ctl_ack_fifo}
mkfifo ${ctl_ack_fifo}
exec {ctl_fd_ack}<>${ctl_ack_fifo}

perf record -D -1 -e cpu-cycles -a               \
            --control fd:${ctl_fd},${ctl_fd_ack} \
            -- sleep 30 &
perf_pid=$!

sleep 5  && echo 'enable' >&${ctl_fd} && read -u ${ctl_fd_ack} e1 && echo "enabled(${e1})"
sleep 10 && echo 'disable' >&${ctl_fd} && read -u ${ctl_fd_ack} d1 && echo "disabled(${d1})"

exec {ctl_fd_ack}>&-
unlink ${ctl_ack_fifo}

exec {ctl_fd}>&-
unlink ${ctl_fifo}

wait -n ${perf_pid}
exit $?


SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1]
+37 −0
Original line number Diff line number Diff line
@@ -1786,6 +1786,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		perf_evlist__start_workload(rec->evlist);
	}

	if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack))
		goto out_child;

	if (opts->initial_delay) {
		pr_info(EVLIST_DISABLED_MSG);
		if (opts->initial_delay > 0) {
@@ -1932,6 +1935,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		record__synthesize_workload(rec, true);

out_child:
	evlist__finalize_ctlfd(rec->evlist);
	record__mmap_read_all(rec, true);
	record__aio_mmap_read_sync(rec);

@@ -2281,6 +2285,33 @@ static int record__parse_mmap_pages(const struct option *opt,
	return ret;
}

static int parse_control_option(const struct option *opt,
				const char *str,
				int unset __maybe_unused)
{
	char *comma = NULL, *endptr = NULL;
	struct record_opts *config = (struct record_opts *)opt->value;

	if (strncmp(str, "fd:", 3))
		return -EINVAL;

	config->ctl_fd = strtoul(&str[3], &endptr, 0);
	if (endptr == &str[3])
		return -EINVAL;

	comma = strchr(str, ',');
	if (comma) {
		if (endptr != comma)
			return -EINVAL;

		config->ctl_fd_ack = strtoul(comma + 1, &endptr, 0);
		if (endptr == comma + 1 || *endptr != '\0')
			return -EINVAL;
	}

	return 0;
}

static void switch_output_size_warn(struct record *rec)
{
	u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages);
@@ -2417,6 +2448,8 @@ static struct record record = {
		},
		.mmap_flush          = MMAP_FLUSH_DEFAULT,
		.nr_threads_synthesize = 1,
		.ctl_fd              = -1,
		.ctl_fd_ack          = -1,
	},
	.tool = {
		.sample		= process_sample_event,
@@ -2618,6 +2651,10 @@ static struct option __record_options[] = {
		"libpfm4 event selector. use 'perf list' to list available events",
		parse_libpfm_events_option),
#endif
	OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd]",
		     "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n"
		     "\t\t\t  Optionally send control command completion ('ack\\n') to ack-fd descriptor.",
		      parse_control_option),
	OPT_END()
};

+2 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ struct record_opts {
	int	      mmap_flush;
	unsigned int  comp_level;
	unsigned int  nr_threads_synthesize;
	int	      ctl_fd;
	int	      ctl_fd_ack;
};

extern const char * const *record_usage;