From: Daniel Lezcano daniel.lezcano@linaro.org
Add the support to run a command line with idlestat:
./idlestat -o out.dat -- /bin/sleep 3
Without the '-t' option, idlestat will blindly use the current buffer size which may not fit with the 'command' duration and lead to a buffer overflow.
With the example, it would make sense to set the buffer size:
./idlestat -o out.dat -t 3 -- /bin/sleep 3
This is a workaround, until we find a way to set the buffer size automatically.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- idlestat.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-)
diff --git a/idlestat.c b/idlestat.c index 53ca1c7..f0c6467 100644 --- a/idlestat.c +++ b/idlestat.c @@ -36,6 +36,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/resource.h> +#include <sys/wait.h> #include <assert.h>
#include "idlestat.h" @@ -112,6 +113,7 @@ static int display_states(struct cpuidle_cstates *cstates, (c->min_time == DBL_MAX ? 0. : c->min_time), c->max_time); } + if (pstates) { for (j = 0; j < pstates->max; j++) { struct cpufreq_pstate *p = &(pstates->pstate[j]); @@ -1022,7 +1024,7 @@ int getoptions(int argc, char *argv[], struct idledebug_options *options) return -1; }
- return 0; + return optind; }
static int idlestat_file_for_each_line(const char *path, void *data, @@ -1108,14 +1110,47 @@ static int idlestat_wake_all(void) return 0; }
-int main(int argc, char *argv[]) +static int execute(int argc, char *argv[], char *const envp[], + struct idledebug_options *options) +{ + pid_t pid; + int status; + + /* Nothing to execute, just wait an amount of time */ + if (!argc) + return sleep(options->duration); + + pid = fork(); + if (pid < 0) { + perror("fork"); + return -1; + } + + if (pid == 0 && execve(argv[0], argv, envp)) { + perror("execv"); + exit(1); + } + + if (pid) { + waitpid(pid, &status, 0); + + if (WIFEXITED(status) && !WEXITSTATUS(status)) + return 0; + } + + return -1; +} + +int main(int argc, char *argv[], char *const envp[]) { struct cpuidle_datas *datas; struct cpuidle_datas *cluster; struct idledebug_options options; struct rusage rusage; + int args;
- if (getoptions(argc, argv, &options)) + args = getoptions(argc, argv, &options); + if (args <= 0) return 1;
/* We have to manipulate some files only accessible to root */ @@ -1128,7 +1163,7 @@ int main(int argc, char *argv[]) init_cpu_topo_info();
/* Acquisition time specified means we will get the traces */ - if (options.duration) { + if (options.duration || args < argc) {
/* Read cpu topology info from sysfs */ read_sysfs_cpu_topo(); @@ -1151,14 +1186,16 @@ int main(int argc, char *argv[]) /* Start the recording */ if (idlestat_trace_enable(true)) return -1; + /* We want to prevent to begin the acquisition with a cpu in * idle state because we won't be able later to close the * state and to determine which state it was. */ if (idlestat_wake_all()) return -1;
- /* Do nothing */ - sleep(options.duration); + /* Execute the command or wait a specified delay */ + if (execute(argc - args, &argv[args], envp, &options)) + return -1;
/* Wake up all cpus again to account for last idle state */ if (idlestat_wake_all())