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

perf stat: 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-stat.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: Alexey Budankov <alexey.budankov@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung 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/feabd5cf-0155-fb0a-4587-c71571f2d517@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Alexey Budankov and committed by
Arnaldo Carvalho de Melo
27e9769a b1aa3db2

+80 -1
+39
tools/perf/Documentation/perf-stat.txt
··· 176 176 3>results perf stat --log-fd 3 -- $cmd 177 177 3>>results perf stat --log-fd 3 --append -- $cmd 178 178 179 + --control fd:ctl-fd[,ack-fd] 180 + Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 181 + 'disable': disable events). Measurements can be started with events disabled using 182 + --delay=-1 option. Optionally send control command completion ('ack\n') to ack-fd descriptor 183 + to synchronize with the controlling process. Example of bash shell script to enable and 184 + disable events during measurements: 185 + 186 + #!/bin/bash 187 + 188 + ctl_dir=/tmp/ 189 + 190 + ctl_fifo=${ctl_dir}perf_ctl.fifo 191 + test -p ${ctl_fifo} && unlink ${ctl_fifo} 192 + mkfifo ${ctl_fifo} 193 + exec {ctl_fd}<>${ctl_fifo} 194 + 195 + ctl_ack_fifo=${ctl_dir}perf_ctl_ack.fifo 196 + test -p ${ctl_ack_fifo} && unlink ${ctl_ack_fifo} 197 + mkfifo ${ctl_ack_fifo} 198 + exec {ctl_fd_ack}<>${ctl_ack_fifo} 199 + 200 + perf stat -D -1 -e cpu-cycles -a -I 1000 \ 201 + --control fd:${ctl_fd},${ctl_fd_ack} \ 202 + -- sleep 30 & 203 + perf_pid=$! 204 + 205 + sleep 5 && echo 'enable' >&${ctl_fd} && read -u ${ctl_fd_ack} e1 && echo "enabled(${e1})" 206 + sleep 10 && echo 'disable' >&${ctl_fd} && read -u ${ctl_fd_ack} d1 && echo "disabled(${d1})" 207 + 208 + exec {ctl_fd_ack}>&- 209 + unlink ${ctl_ack_fifo} 210 + 211 + exec {ctl_fd}>&- 212 + unlink ${ctl_fifo} 213 + 214 + wait -n ${perf_pid} 215 + exit $? 216 + 217 + 179 218 --pre:: 180 219 --post:: 181 220 Pre and post measurement hooks, e.g.:
+39 -1
tools/perf/builtin-stat.c
··· 188 188 .metric_only_len = METRIC_ONLY_LEN, 189 189 .walltime_nsecs_stats = &walltime_nsecs_stats, 190 190 .big_num = true, 191 + .ctl_fd = -1, 192 + .ctl_fd_ack = -1 191 193 }; 192 194 193 195 static bool cpus_map_matched(struct evsel *a, struct evsel *b) ··· 869 867 perf_evlist__start_workload(evsel_list); 870 868 enable_counters(); 871 869 872 - if (interval || timeout) 870 + if (interval || timeout || evlist__ctlfd_initialized(evsel_list)) 873 871 status = dispatch_events(forks, timeout, interval, &times); 874 872 if (child_pid != -1) { 875 873 if (timeout) ··· 1041 1039 &stat_config.metric_events); 1042 1040 } 1043 1041 1042 + static int parse_control_option(const struct option *opt, 1043 + const char *str, 1044 + int unset __maybe_unused) 1045 + { 1046 + char *comma = NULL, *endptr = NULL; 1047 + struct perf_stat_config *config = (struct perf_stat_config *)opt->value; 1048 + 1049 + if (strncmp(str, "fd:", 3)) 1050 + return -EINVAL; 1051 + 1052 + config->ctl_fd = strtoul(&str[3], &endptr, 0); 1053 + if (endptr == &str[3]) 1054 + return -EINVAL; 1055 + 1056 + comma = strchr(str, ','); 1057 + if (comma) { 1058 + if (endptr != comma) 1059 + return -EINVAL; 1060 + 1061 + config->ctl_fd_ack = strtoul(comma + 1, &endptr, 0); 1062 + if (endptr == comma + 1 || *endptr != '\0') 1063 + return -EINVAL; 1064 + } 1065 + 1066 + return 0; 1067 + } 1068 + 1044 1069 static struct option stat_options[] = { 1045 1070 OPT_BOOLEAN('T', "transaction", &transaction_run, 1046 1071 "hardware transaction statistics"), ··· 1169 1140 "libpfm4 event selector. use 'perf list' to list available events", 1170 1141 parse_libpfm_events_option), 1171 1142 #endif 1143 + OPT_CALLBACK(0, "control", &stat_config, "fd:ctl-fd[,ack-fd]", 1144 + "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n" 1145 + "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.", 1146 + parse_control_option), 1172 1147 OPT_END() 1173 1148 }; 1174 1149 ··· 2342 2309 signal(SIGALRM, skip_signal); 2343 2310 signal(SIGABRT, skip_signal); 2344 2311 2312 + if (evlist__initialize_ctlfd(evsel_list, stat_config.ctl_fd, stat_config.ctl_fd_ack)) 2313 + goto out; 2314 + 2345 2315 status = 0; 2346 2316 for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) { 2347 2317 if (stat_config.run_count != 1 && verbose > 0) ··· 2363 2327 2364 2328 if (!forever && status != -1 && (!interval || stat_config.summary)) 2365 2329 print_counters(NULL, argc, argv); 2330 + 2331 + evlist__finalize_ctlfd(evsel_list); 2366 2332 2367 2333 if (STAT_RECORD) { 2368 2334 /*
+2
tools/perf/util/stat.h
··· 133 133 struct perf_cpu_map *cpus_aggr_map; 134 134 u64 *walltime_run; 135 135 struct rblist metric_events; 136 + int ctl_fd; 137 + int ctl_fd_ack; 136 138 }; 137 139 138 140 void perf_stat__set_big_num(int set);