Signed-off-by: Pi-Cheng Chen <pi-cheng.c...@linaro.org>
---
idlestat.c | 136 ++++++++++++++++++++++++++++++++++++++++---------------------
idlestat.h | 1 +
2 files changed, 90 insertions(+), 47 deletions(-)
diff --git a/idlestat.c b/idlestat.c
index bba8951..fb0ae8f 100644
--- a/idlestat.c
+++ b/idlestat.c
@@ -51,6 +51,7 @@
#define USEC_PER_SEC 1000000
static char buffer[BUFSIZE];
+static FILE *output;
static inline int error(const char *str)
{
@@ -68,19 +69,40 @@ static void charrep(char c, int count)
{
int i;
for (i = 0; i < count; i++)
- printf("%c", c);
+ fprintf(output, "%c", c);
+}
+
+static int open_report_file(const char *path)
+{
+ if (path) {
+ output = fopen(path, "w+");
+
+ if (!output) {
+ fprintf(stderr, "%s: failed to open '%s'\n", __func__,
path);
+ return -1;
+ }
+ } else
+ output = stdout;
+
+ return 0;
+}
+
+static void close_report_file(void)
+{
+ if (output != stdout)
+ fclose(output);
}
static void display_cpu_header(char *cpu, int length)
{
charrep('-', length);
- printf("\n");
+ fprintf(output, "\n");
if (strstr(cpu, "cluster"))
- printf("| %-*s |\n", length - 4, cpu);
+ fprintf(output, "| %-*s |\n", length - 4, cpu);
else if (strstr(cpu, "core"))
- printf("| %-*s |\n", length - 9, cpu);
- else printf("| %-*s |\n", length - 16, cpu);
+ fprintf(output, "| %-*s |\n", length - 9, cpu);
+ else fprintf(output, "| %-*s |\n", length - 16, cpu);
}
static void display_factored_time(double time, int align)
@@ -89,15 +111,15 @@ static void display_factored_time(double time, int align)
if (time < 1000) {
sprintf(buffer, "%.0lfus", time);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
}
else if (time < 1000000) {
sprintf(buffer, "%.2lfms", time / 1000.0);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
}
else {
sprintf(buffer, "%.2lfs", time / 1000000.0);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
}
}
@@ -107,28 +129,29 @@ static void display_factored_freq(int freq, int align)
if (freq < 1000) {
sprintf(buffer, "%dHz", freq);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
} else if (freq < 1000000) {
sprintf(buffer, "%.2fMHz", (float)freq / 1000.0);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
} else {
sprintf(buffer, "%.2fGHz", (float)freq / 1000000.0);
- printf("%*s", align, buffer);
+ fprintf(output, "%*s", align, buffer);
}
}
static void display_cstates_header(void)
{
charrep('-', 80);
- printf("\n");
+ fprintf(output, "\n");
- printf("| C-state | min | max | avg | total | hits |
over | under |\n");
+ fprintf(output, "| C-state | min | max | avg | total"
+ " | hits | over | under |\n");
}
static void display_cstates_footer(void)
{
charrep('-', 80);
- printf("\n\n");
+ fprintf(output, "\n\n");
}
static int display_cstates(void *arg, char *cpu)
@@ -148,23 +171,23 @@ static int display_cstates(void *arg, char *cpu)
display_cpu_header(cpu, 80);
cpu_header = true;
charrep('-', 80);
- printf("\n");
+ fprintf(output, "\n");
}
- printf("| %8s | ", c->name);
+ fprintf(output, "| %8s | ", c->name);
display_factored_time(c->min_time == DBL_MAX ? 0. :
c->min_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(c->max_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(c->avg_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(c->duration, 8);
- printf(" | ");
- printf("%5d | %5d | %5d |", c->nrdata,
+ fprintf(output, " | ");
+ fprintf(output, "%5d | %5d | %5d |", c->nrdata,
c->premature_wakeup, c->could_sleep_more);
- printf("\n");
+ fprintf(output, "\n");
}
return 0;
@@ -173,15 +196,16 @@ static int display_cstates(void *arg, char *cpu)
static void display_pstates_header(void)
{
charrep('-', 64);
- printf("\n");
+ fprintf(output, "\n");
- printf("| P-state | min | max | avg | total | hits
|\n");
+ fprintf(output, "| P-state | min | max | avg | total"
+ " | hits |\n");
}
static void display_pstates_footer(void)
{
charrep('-', 64);
- printf("\n\n");
+ fprintf(output, "\n\n");
}
static int display_pstates(void *arg, char *cpu)
@@ -202,24 +226,24 @@ static int display_pstates(void *arg, char *cpu)
display_cpu_header(cpu, 64);
cpu_header = true;
charrep('-', 64);
- printf("\n");
+ fprintf(output, "\n");
}
- printf("| ");
+ fprintf(output, "| ");
display_factored_freq(p->freq, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(p->min_time == DBL_MAX ? 0. :
p->min_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(p->max_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(p->avg_time, 8);
- printf(" | ");
+ fprintf(output, " | ");
display_factored_time(p->duration, 8);
- printf(" | ");
- printf("%5d", p->count);
- printf(" | ");
- printf("\n");
+ fprintf(output, " | ");
+ fprintf(output, "%5d", p->count);
+ fprintf(output, " | ");
+ fprintf(output, "\n");
}
return 0;
@@ -228,15 +252,15 @@ static int display_pstates(void *arg, char *cpu)
static void display_wakeup_header(void)
{
charrep('-', 44);
- printf("\n");
+ fprintf(output, "\n");
- printf("| Wakeup | # | Name | Count |\n");
+ fprintf(output, "| Wakeup | # | Name | Count |\n");
}
static void display_wakeup_footer(void)
{
charrep('-', 44);
- printf("\n\n");
+ fprintf(output, "\n\n");
}
static int display_wakeup(void *arg, char *cpu)
@@ -253,16 +277,16 @@ static int display_wakeup(void *arg, char *cpu)
display_cpu_header(cpu, 44);
cpu_header = true;
charrep('-', 44);
- printf("\n");
+ fprintf(output, "\n");
}
if (irqinfo->irq_type == HARD_IRQ)
- printf("| %-6s | %-3d | %15.15s | %7d |\n",
+ fprintf(output, "| %-6s | %-3d | %15.15s | %7d |\n",
"irq", irqinfo->id, irqinfo->name,
irqinfo->count);
if (irqinfo->irq_type == IPI_IRQ)
- printf("| %-6s | --- | %15.15s | %7d |\n",
+ fprintf(output, "| %-6s | --- | %15.15s | %7d |\n",
"ipi", irqinfo->name, irqinfo->count);
}
@@ -1111,11 +1135,11 @@ static void help(const char *cmd)
{
fprintf(stderr,
"\nUsage:\nTrace mode:\n\t%s --trace -f|--trace-file <filename>"
- " -t|--duration <seconds> -c|--idle -p|--frequency -w|--wakeup",
- basename(cmd));
+ " -o|--output-file <filename> -t|--duration <seconds>"
+ " -c|--idle -p|--frequency -w|--wakeup", basename(cmd));
fprintf(stderr,
- "\nReporting mode:\n\t%s --import -f|--trace-file <filename>",
- basename(cmd));
+ "\nReporting mode:\n\t%s --import -f|--trace-file <filename>"
+ " -o|--output-file <filename>", basename(cmd));
fprintf(stderr,
"\n\nExamples:\n1. Run a trace, post-process the results"
" (default is to show only C-state statistics):\n\tsudo "
@@ -1131,6 +1155,15 @@ static void help(const char *cmd)
fprintf(stderr,
"\n4. Post-process a trace captured earlier:\n\tsudo ./%s"
" --import -f /tmp/mytrace\n", basename(cmd));
+ fprintf(stderr,
+ "\n5. Run a trace, post-process the results and print all"
+ " statistics into a file:\n\tsudo ./%s --trace -f /tmp/mytrace -t 10
-p -c -w"
+ " -o /tmp/myreport\n", basename(cmd));
+ fprintf(stderr,
+ "\n6. Post-process a trace captured earlier and print all"
+ " statistics into a file:\n\tsudo ./%s --import -f /tmp/mytrace -p
-c -w"
+ " -o /tmp/myreport\n",
+ basename(cmd));
}
static void version(const char *cmd)
@@ -1144,6 +1177,7 @@ int getoptions(int argc, char *argv[], struct
program_options *options)
{ "trace", no_argument, &options->mode, TRACE },
{ "import", no_argument, &options->mode, IMPORT },
{ "trace-file", required_argument, NULL, 'f' },
+ { "output-file", required_argument, NULL, 'o' },
{ "help", no_argument, NULL, 'h' },
{ "duration", required_argument, NULL, 't' },
{ "version", no_argument, NULL, 'V' },
@@ -1157,13 +1191,14 @@ int getoptions(int argc, char *argv[], struct
program_options *options)
memset(options, 0, sizeof(*options));
options->filename = NULL;
+ options->outfilename = NULL;
options->mode = -1;
options->format = -1;
while (1) {
int optindex = 0;
- c = getopt_long(argc, argv, ":df:ht:cpwVv",
+ c = getopt_long(argc, argv, ":df:o:ht:cpwVv",
long_options, &optindex);
if (c == -1)
break;
@@ -1172,6 +1207,9 @@ int getoptions(int argc, char *argv[], struct
program_options *options)
case 'f':
options->filename = optarg;
break;
+ case 'o':
+ options->outfilename = optarg;
+ break;
case 'h':
help(argv[0]);
exit(0);
@@ -1427,7 +1465,7 @@ int main(int argc, char *argv[], char *const envp[])
return -1;
}
- if (check_window_size()) {
+ if (check_window_size() && !options.outfilename) {
fprintf(stderr, "The terminal must be at least "
"80 columns wide\n");
return -1;
@@ -1501,6 +1539,8 @@ int main(int argc, char *argv[], char *const envp[])
* the same cluster
*/
if (0 == establish_idledata_to_topo(datas)) {
+ if (open_report_file(options.outfilename))
+ return -1;
if (options.display & IDLE_DISPLAY) {
display_cstates_header();
@@ -1519,6 +1559,8 @@ int main(int argc, char *argv[], char *const envp[])
dump_cpu_topo_info(display_wakeup, 1);
display_wakeup_footer();
}
+
+ close_report_file();
}
release_cpu_topo_cstates();
diff --git a/idlestat.h b/idlestat.h
index 1d5f961..735f0fe 100644
--- a/idlestat.h
+++ b/idlestat.h
@@ -132,6 +132,7 @@ struct program_options {
int display;
unsigned int duration;
char *filename;
+ char *outfilename;
int verbose;
};