diff options
author | Tuukka Tikkanen <tuukka.tikkanen@linaro.org> | 2015-01-21 00:44:32 +0200 |
---|---|---|
committer | Tuukka Tikkanen <tuukka.tikkanen@linaro.org> | 2015-01-21 00:44:32 +0200 |
commit | 6efac9bed0ec6b7a2e9abc8872e03245d4918f06 (patch) | |
tree | 37455aa61d15feed236f2db5e7e12b25c0981de5 | |
parent | 7d3394ec671ee1f4a80080dcdaac31ed2247a24d (diff) |
Idlestat: Add command line options for managing trace buffer
As the kernel trace buffer is a finite resource, the default
trace buffer size idlestat sets may either be impossibly
large or insufficient to hold the data. This patch adds two
new command line options to control buffer size and whether
or not it will be polled during the trace period.
The polling functionality while tracing is not yet implemented.
Signed-off-by: Tuukka Tikkanen <tuukka.tikkanen@linaro.org>
-rw-r--r-- | idlestat.c | 27 | ||||
-rw-r--r-- | idlestat.h | 6 | ||||
-rw-r--r-- | trace.c | 52 | ||||
-rw-r--r-- | trace.h | 3 |
4 files changed, 77 insertions, 11 deletions
@@ -1000,6 +1000,8 @@ int getoptions(int argc, char *argv[], struct program_options *options) { "wakeup", no_argument, NULL, 'w' }, { "boxless-report", no_argument, NULL, 'B' }, { "csv-report", no_argument, NULL, 'C' }, + { "poll-interval", required_argument, NULL, 'I' }, + { "buffer-size", required_argument, NULL, 'S' }, { "version", no_argument, NULL, 'V' }, { 0, 0, 0, 0 } }; @@ -1014,7 +1016,7 @@ int getoptions(int argc, char *argv[], struct program_options *options) int optindex = 0; - c = getopt_long(argc, argv, ":b:ce:f:ho:pr:t:vwBCV", + c = getopt_long(argc, argv, ":b:ce:f:ho:pr:t:vwBCI:S:V", long_options, &optindex); if (c == -1) break; @@ -1079,6 +1081,12 @@ int getoptions(int argc, char *argv[], struct program_options *options) fprintf(stderr, "-B: report type already set to %s\n", options->report_type_name); return -1; + case 'I': + options->tbs.poll_interval = atoi(optarg); + break; + case 'S': + options->tbs.percpu_buffer_size = atoi(optarg); + break; case 0: /* getopt_long() set a variable, just keep going */ break; case ':': /* missing option argument */ @@ -1374,11 +1382,22 @@ int main(int argc, char *argv[], char *const envp[]) if (is_err(saved_trace_options)) return 1; + /* + * Calculate/verify buffer size and polling trace data + * interval. The interval or may may not be used to + * transfer data from kernel trace buffer to some + * storage media. It is needed for long eventful traces, + * but is not preferred. If the user does not specify + * the values, we will calculate reasonable defaults. + */ + if (calculate_buffer_parameters(options.duration, &options.tbs)) + return 1; + /* Initialize the traces for cpu_idle and increase the - * buffer size to let 'idlestat' to sleep instead of - * acquiring data, hence preventing it to pertubate the + * buffer size to let 'idlestat' to possibly sleep instead + * of acquiring data, hence preventing it to pertubate the * measurements. */ - if (idlestat_init_trace(options.duration)) + if (idlestat_init_trace(options.tbs.percpu_buffer_size)) goto err_restore_trace_options; /* Remove all the previous traces */ @@ -124,10 +124,16 @@ enum modes { IMPORT }; +struct trace_buffer_settings { + unsigned int percpu_buffer_size; + unsigned int poll_interval; +}; + struct program_options { int mode; int display; unsigned int duration; + struct trace_buffer_settings tbs; char *filename; char *baseline_filename; char *outfilename; @@ -36,6 +36,7 @@ #include <fts.h> #include "trace.h" +#include "idlestat.h" #include "utils.h" #include "list.h" @@ -163,9 +164,13 @@ cannot_get_event_options: return ptrerror(NULL); } -int idlestat_init_trace(unsigned int duration) +int calculate_buffer_parameters(unsigned int duration, + struct trace_buffer_settings *tbs) { - int bufsize; + unsigned int def_bufsize; + + if (tbs->poll_interval == 0) + tbs->poll_interval = duration; /* Assuming the worst case where we can have for cpuidle, * TRACE_IDLE_NRHITS_PER_SEC. Each state enter/exit line are @@ -175,17 +180,50 @@ int idlestat_init_trace(unsigned int duration) * Divide by 2^10 to have Kb. We add 1Kb to be sure to round up. */ - bufsize = 2 * TRACE_IDLE_LENGTH * TRACE_IDLE_NRHITS_PER_SEC; - bufsize += TRACE_CPUFREQ_LENGTH * TRACE_CPUFREQ_NRHITS_PER_SEC; - bufsize = (bufsize * duration / (1 << 10)) + 1; + if (tbs->percpu_buffer_size == 0) { + def_bufsize = 2 * TRACE_IDLE_LENGTH; + def_bufsize *= TRACE_IDLE_NRHITS_PER_SEC; + def_bufsize += TRACE_CPUFREQ_LENGTH * + TRACE_CPUFREQ_NRHITS_PER_SEC; + def_bufsize = (def_bufsize * tbs->poll_interval / (1 << 10)); + def_bufsize += 1; + + tbs->percpu_buffer_size = def_bufsize; + } + + if (tbs->poll_interval >= duration) { + verbose_printf(1, + "Polling is disabled during trace " + "(polling interval exceeds trace duration).\n"); + } else { + verbose_printf(1, "Polling interval: %u s\n", + tbs->poll_interval); + } + verbose_printf(1, "Per cpu trace buffer: %u kB\n", + tbs->percpu_buffer_size); + + return 0; +} - if (write_int(TRACE_BUFFER_SIZE_PATH, bufsize)) +int idlestat_init_trace(unsigned int percpu_bufsize) +{ + int bufsize = (int)percpu_bufsize; + + if (write_int(TRACE_BUFFER_SIZE_PATH, bufsize)) { + fprintf(stderr, + "Failed to set trace buffer to desired size. If the " + "error was caused by failure in memory allocation, " + "try to increase buffer size (-S, --buffer-size) " + "or decrease polling interval " + "(-I, --polling-interval).\n" + "Increase verbosity (-v) to see current values\n"); return -1; + } if (read_int(TRACE_BUFFER_TOTAL_PATH, &bufsize)) return -1; - printf("Total trace buffer: %d kB\n", bufsize); + verbose_printf(1, "Total trace buffer: %d kB\n", bufsize); /* Disable all the traces */ if (write_int(TRACE_EVENT_PATH, 0)) @@ -40,9 +40,12 @@ #define TRACE_CPUFREQ_LENGTH 196 struct trace_options; +struct trace_buffer_settings; extern int idlestat_trace_enable(bool enable); extern int idlestat_flush_trace(void); +extern int calculate_buffer_parameters(unsigned int duration, + struct trace_buffer_settings *tbs); extern int idlestat_init_trace(unsigned int duration); extern struct trace_options *idlestat_store_trace_options(void); extern int idlestat_restore_trace_options(struct trace_options *options); |