aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoan-Sin Tan <freedom.tan@linaro.org>2014-11-27 17:10:47 +0800
committerTuukka Tikkanen <tuukka.tikkanen@linaro.org>2014-11-28 05:11:18 +0200
commitdb63259a01cb3c88b82dbecddd48a2c166c84e20 (patch)
treec86902bcdc3f2d1b5d66363e44e0561a21b97512
parent262e24b0d2136e8c3ee847bf65f6527f27973730 (diff)
add code to handle different output formats
The goals of this patch are 1) to support different report formats (e.g., text, csv, gnuplot commands), 2) to support different report modes (e.g., single run stats, histograms, comparison), and 3) without cluttering the main program code with vast amounts of conditional output code in primary processing loop. This patch implements report output via an "report operations structure" (struct output_ops) pointed to from options structure. Clutter in main source file has been reduced by moving the default report generation functions to separate report format specific source file and utils.c. Signed-off-by: Koan-Sin Tan <freedom.tan@linaro.org> Signed-off-by: Tuukka Tikkanen <tuukka.tikkanen@linaro.org>
-rw-r--r--Makefile2
-rw-r--r--default_report.c186
-rw-r--r--idlestat.c244
-rw-r--r--idlestat.h27
-rw-r--r--report_ops.h6
-rw-r--r--topology.c10
-rw-r--r--topology.h2
-rw-r--r--utils.c84
-rw-r--r--utils.h5
9 files changed, 351 insertions, 215 deletions
diff --git a/Makefile b/Makefile
index 1f8d0e9..d520918 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@
CFLAGS?=-g -Wall
CC=gcc
-OBJS = idlestat.o topology.o trace.o utils.o energy_model.o
+OBJS = idlestat.o topology.o trace.o utils.o energy_model.o default_report.o
default: idlestat
diff --git a/default_report.c b/default_report.c
new file mode 100644
index 0000000..d900dae
--- /dev/null
+++ b/default_report.c
@@ -0,0 +1,186 @@
+#include <float.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "idlestat.h"
+#include "utils.h"
+
+
+static void charrep(char c, int count)
+{
+ int i;
+ for (i = 0; i < count; i++)
+ printf("%c", c);
+}
+
+static int default_check_output(struct program_options *options, void *report_data)
+{
+ if (check_window_size() && !options->outfilename) {
+ fprintf(stderr, "The terminal must be at least "
+ "80 columns wide\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int default_open_report_file(char *path, void *report_data)
+{
+ return redirect_stdout_to_file(path);
+}
+
+static int default_close_report_file(void *report_data)
+{
+ return (fclose(stdout) == EOF) ? -1 : 0;
+}
+
+static void default_cstate_table_header(void *report_data)
+{
+ charrep('-', 80);
+ printf("\n");
+
+ printf("| C-state | min | max | avg | total | hits | over | under |\n");
+}
+
+static void default_cstate_table_footer(void *report_data)
+{
+ charrep('-', 80);
+ printf("\n\n");
+}
+
+static void default_cpu_header(const char *cpu, void *report_data, int len)
+{
+ charrep('-', len);
+ printf("\n");
+
+ if (strstr(cpu, "cluster"))
+ printf("| %-*s |\n", len - 4, cpu);
+ else if (strstr(cpu, "core"))
+ printf("| %-*s |\n", len - 9, cpu);
+ else printf("| %-*s |\n", len - 16, cpu);
+
+ charrep('-', len);
+ printf("\n");
+}
+
+static void default_cstate_cpu_header(const char *cpu, void *report_data)
+{
+ default_cpu_header(cpu, report_data, 80);
+}
+
+static void default_cstate_single_state(struct cpuidle_cstate *c, void *report_data)
+{
+ printf("| %8s | ", c->name);
+ display_factored_time(c->min_time == DBL_MAX ? 0. :
+ c->min_time, 8);
+ printf(" | ");
+ display_factored_time(c->max_time, 8);
+ printf(" | ");
+ display_factored_time(c->avg_time, 8);
+ printf(" | ");
+ display_factored_time(c->duration, 8);
+ printf(" | ");
+ printf("%5d | %5d | %5d |", c->nrdata, c->early_wakings, c->late_wakings);
+
+ printf("\n");
+}
+
+static void default_cstate_end_cpu(void *report_data)
+{
+}
+
+static void default_pstate_table_header(void *report_data)
+{
+ charrep('-', 64);
+ printf("\n");
+
+ printf("| P-state | min | max | avg | total | hits |\n");
+}
+
+static void default_pstate_table_footer(void *report_data)
+{
+ charrep('-', 64);
+ printf("\n\n");
+}
+
+static void default_pstate_cpu_header(const char *cpu, void *report_data)
+{
+ default_cpu_header(cpu, report_data, 64);
+}
+
+static void default_pstate_single_state(struct cpufreq_pstate *p, void *report_data)
+{
+
+ printf("| ");
+ display_factored_freq(p->freq, 8);
+ printf(" | ");
+ display_factored_time(p->min_time == DBL_MAX ? 0. : p->min_time, 8);
+ printf(" | ");
+ display_factored_time(p->max_time, 8);
+ printf(" | ");
+ display_factored_time(p->avg_time, 8);
+ printf(" | ");
+ display_factored_time(p->duration, 8);
+ printf(" | ");
+ printf("%5d", p->count);
+ printf(" | ");
+ printf("\n");
+}
+
+static void default_wakeup_table_header(void *report_data)
+{
+ charrep('-', 55);
+ printf("\n");
+
+ printf("| IRQ | Name | Count | early | late |\n");
+}
+
+static void default_wakeup_table_footer(void *report_data)
+{
+ charrep('-', 55);
+ printf("\n\n");
+}
+
+static void default_wakeup_cpu_header(const char *cpu, void *report_data)
+{
+ default_cpu_header(cpu, report_data, 55);
+}
+
+static void default_wakeup_single_state(struct wakeup_irq *irqinfo, void *report_data)
+{
+ if (irqinfo->id != -1) {
+ printf("| %-3d | %-15.15s | %7d | %7d | %7d |\n",
+ irqinfo->id, irqinfo->name, irqinfo->count,
+ irqinfo->early_triggers, irqinfo->late_triggers);
+ } else {
+ printf("| IPI | %-15.15s | %7d | %7d | %7d |\n",
+ irqinfo->name, irqinfo->count,
+ irqinfo->early_triggers, irqinfo->late_triggers);
+ }
+}
+
+struct report_ops default_report_ops = {
+ .check_output = default_check_output,
+
+ .open_report_file = default_open_report_file,
+ .close_report_file = default_close_report_file,
+
+ .cstate_table_header = default_cstate_table_header,
+ .cstate_table_footer = default_cstate_table_footer,
+ .cstate_cpu_header = default_cstate_cpu_header,
+ .cstate_single_state = default_cstate_single_state,
+ .cstate_end_cpu = default_cstate_end_cpu,
+
+ .pstate_table_header = default_pstate_table_header,
+ .pstate_table_footer = default_pstate_table_footer,
+ .pstate_cpu_header = default_pstate_cpu_header,
+ .pstate_single_state = default_pstate_single_state,
+ .pstate_end_cpu = default_cstate_end_cpu,
+
+ .wakeup_table_header = default_wakeup_table_header,
+ .wakeup_table_footer = default_wakeup_table_footer,
+ .wakeup_cpu_header = default_wakeup_cpu_header,
+ .wakeup_single_state = default_wakeup_single_state,
+ .wakeup_end_cpu = default_cstate_end_cpu,
+};
diff --git a/idlestat.c b/idlestat.c
index 1f9a7f3..7b6df02 100644
--- a/idlestat.c
+++ b/idlestat.c
@@ -27,17 +27,12 @@
#define _GNU_SOURCE
#include <errno.h>
#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sched.h>
#include <string.h>
#include <float.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
#include <sys/time.h>
-#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <assert.h>
@@ -48,6 +43,7 @@
#include "list.h"
#include "topology.h"
#include "energy_model.h"
+#include "report_ops.h"
#define IDLESTAT_VERSION "0.4-rc1"
#define USEC_PER_SEC 1000000
@@ -90,40 +86,6 @@ static inline void *ptrerror(const char *str)
return NULL;
}
-static void charrep(char c, int count)
-{
- int i;
- for (i = 0; i < count; i++)
- printf("%c", c);
-}
-
-static int open_report_file(const char *path)
-{
- int fd;
- int ret = 0;
-
- if (path) {
- fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH);
- if (fd < 0) {
- fprintf(stderr, "%s: failed to open '%s'\n", __func__, path);
- return -1;
- }
-
- close(STDOUT_FILENO);
-
- ret = dup2(fd, STDOUT_FILENO);
- close(fd);
-
- if (ret < 0) {
- fprintf(stderr, "%s: failed to duplicate '%s'\n", __func__, path);
- return ret;
- }
- }
-
- return 0;
-}
-
#define TRACE_TS_FORMAT "%*[^:]:%lf"
static double get_trace_ts(void)
@@ -147,67 +109,7 @@ static double get_trace_ts(void)
return ts;
}
-static void display_cpu_header(char *cpu, int length)
-{
- charrep('-', length);
- printf("\n");
-
- if (strstr(cpu, "cluster"))
- printf("| %-*s |\n", length - 4, cpu);
- else if (strstr(cpu, "core"))
- printf("| %-*s |\n", length - 9, cpu);
- else printf("| %-*s |\n", length - 16, cpu);
-}
-
-static void display_factored_time(double time, int align)
-{
- char buffer[128];
-
- if (time < 1000) {
- sprintf(buffer, "%.0lfus", time);
- printf("%*s", align, buffer);
- }
- else if (time < 1000000) {
- sprintf(buffer, "%.2lfms", time / 1000.0);
- printf("%*s", align, buffer);
- }
- else {
- sprintf(buffer, "%.2lfs", time / 1000000.0);
- printf("%*s", align, buffer);
- }
-}
-
-static void display_factored_freq(int freq, int align)
-{
- char buffer[128];
-
- if (freq < 1000) {
- sprintf(buffer, "%dHz", freq);
- printf("%*s", align, buffer);
- } else if (freq < 1000000) {
- sprintf(buffer, "%.2fMHz", (float)freq / 1000.0);
- printf("%*s", align, buffer);
- } else {
- sprintf(buffer, "%.2fGHz", (float)freq / 1000000.0);
- printf("%*s", align, buffer);
- }
-}
-
-static void display_cstates_header(void)
-{
- charrep('-', 80);
- printf("\n");
-
- printf("| C-state | min | max | avg | total | hits | over | under |\n");
-}
-
-static void display_cstates_footer(void)
-{
- charrep('-', 80);
- printf("\n\n");
-}
-
-static int display_cstates(void *arg, char *cpu)
+static int display_cstates(struct report_ops *ops, void *arg, char *cpu, void *report_data)
{
int i;
bool cpu_header = false;
@@ -221,46 +123,19 @@ static int display_cstates(void *arg, char *cpu)
continue;
if (!cpu_header) {
- display_cpu_header(cpu, 80);
+ ops->cstate_cpu_header(cpu, report_data);
cpu_header = true;
- charrep('-', 80);
- printf("\n");
}
- printf("| %8s | ", c->name);
- display_factored_time(c->min_time == DBL_MAX ? 0. :
- c->min_time, 8);
- printf(" | ");
- display_factored_time(c->max_time, 8);
- printf(" | ");
- display_factored_time(c->avg_time, 8);
- printf(" | ");
- display_factored_time(c->duration, 8);
- printf(" | ");
- printf("%5d | %5d | %5d |", c->nrdata,
- c->early_wakings, c->late_wakings);
-
- printf("\n");
+ ops->cstate_single_state(c, report_data);
}
+ if (cpu_header)
+ ops->cstate_end_cpu(report_data);
return 0;
}
-static void display_pstates_header(void)
-{
- charrep('-', 64);
- printf("\n");
-
- printf("| P-state | min | max | avg | total | hits |\n");
-}
-
-static void display_pstates_footer(void)
-{
- charrep('-', 64);
- printf("\n\n");
-}
-
-static int display_pstates(void *arg, char *cpu)
+static int display_pstates(struct report_ops *ops, void *arg, char *cpu, void *report_data)
{
int i;
bool cpu_header = false;
@@ -275,47 +150,20 @@ static int display_pstates(void *arg, char *cpu)
continue;
if (!cpu_header) {
- display_cpu_header(cpu, 64);
+ ops->pstate_cpu_header(cpu, report_data);
cpu_header = true;
- charrep('-', 64);
- printf("\n");
}
- printf("| ");
- display_factored_freq(p->freq, 8);
- printf(" | ");
- display_factored_time(p->min_time == DBL_MAX ? 0. :
- p->min_time, 8);
- printf(" | ");
- display_factored_time(p->max_time, 8);
- printf(" | ");
- display_factored_time(p->avg_time, 8);
- printf(" | ");
- display_factored_time(p->duration, 8);
- printf(" | ");
- printf("%5d", p->count);
- printf(" | ");
- printf("\n");
+ ops->pstate_single_state(p, report_data);
}
- return 0;
-}
-
-static void display_wakeup_header(void)
-{
- charrep('-', 55);
- printf("\n");
-
- printf("| IRQ | Name | Count | early | late |\n");
-}
+ if (cpu_header)
+ ops->pstate_end_cpu(report_data);
-static void display_wakeup_footer(void)
-{
- charrep('-', 55);
- printf("\n\n");
+ return 0;
}
-static int display_wakeup(void *arg, char *cpu)
+static int display_wakeup(struct report_ops *ops, void *arg, char *cpu, void *report_data)
{
int i;
bool cpu_header = false;
@@ -326,23 +174,16 @@ static int display_wakeup(void *arg, char *cpu)
for (i = 0; i < wakeinfo->nrdata; i++, irqinfo++) {
if (!cpu_header) {
- display_cpu_header(cpu, 55);
+ ops->wakeup_cpu_header(cpu, report_data);
cpu_header = true;
- charrep('-', 55);
- printf("\n");
}
- if (irqinfo->id != -1) {
- printf("| %-3d | %-15.15s | %7d | %7d | %7d |\n",
- irqinfo->id, irqinfo->name, irqinfo->count,
- irqinfo->early_triggers, irqinfo->late_triggers);
- } else {
- printf("| IPI | %-15.15s | %7d | %7d | %7d |\n",
- irqinfo->name, irqinfo->count,
- irqinfo->early_triggers, irqinfo->late_triggers);
- }
+ ops->wakeup_single_state(irqinfo, report_data);
}
+ if (cpu_header)
+ ops->wakeup_end_cpu(report_data);
+
return 0;
}
@@ -1424,6 +1265,8 @@ int getoptions(int argc, char *argv[], struct program_options *options)
options->outfilename = NULL;
options->mode = -1;
options->format = -1;
+ options->report_ops = &default_report_ops;
+
while (1) {
int optindex = 0;
@@ -1685,23 +1528,6 @@ static int execute(int argc, char *argv[], char *const envp[],
return -1;
}
-static int check_window_size(void)
-{
- struct winsize winsize;
-
- /* Output is redirected */
- if (!isatty(STDOUT_FILENO))
- return 0;
-
- /* Get terminal window size */
- ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
-
- if (winsize.ws_col >= 80)
- return 0;
-
- return -1;
-}
-
int main(int argc, char *argv[], char *const envp[])
{
struct cpuidle_datas *datas;
@@ -1709,6 +1535,7 @@ int main(int argc, char *argv[], char *const envp[])
int args;
double start_ts = 0, end_ts = 0;
struct init_pstates *initp = NULL;
+ struct report_ops *output_handler = NULL;
args = getoptions(argc, argv, &options);
if (args <= 0)
@@ -1721,11 +1548,10 @@ int main(int argc, char *argv[], char *const envp[])
return 1;
}
- if (check_window_size() && !options.outfilename) {
- fprintf(stderr, "The terminal must be at least "
- "80 columns wide\n");
+ output_handler = options.report_ops;
+
+ if (output_handler->check_output(&options, options.report_data))
return 1;
- }
if (options.energy_model_filename &&
parse_energy_model(&options) < 0) {
@@ -1815,29 +1641,31 @@ 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))
+ if (output_handler->open_report_file(options.outfilename, options.report_data))
return -1;
if (options.display & IDLE_DISPLAY) {
- display_cstates_header();
- dump_cpu_topo_info(display_cstates, 1);
- display_cstates_footer();
+ output_handler->cstate_table_header(options.report_data);
+ dump_cpu_topo_info(output_handler, options.report_data, display_cstates, 1);
+ output_handler->cstate_table_footer(options.report_data);
}
if (options.display & FREQUENCY_DISPLAY) {
- display_pstates_header();
- dump_cpu_topo_info(display_pstates, 0);
- display_pstates_footer();
+ output_handler->pstate_table_header(options.report_data);
+ dump_cpu_topo_info(output_handler, options.report_data, display_pstates, 0);
+ output_handler->pstate_table_footer(options.report_data);
}
if (options.display & WAKEUP_DISPLAY) {
- display_wakeup_header();
- dump_cpu_topo_info(display_wakeup, 1);
- display_wakeup_footer();
+ output_handler->wakeup_table_header(options.report_data);
+ dump_cpu_topo_info(output_handler, options.report_data, display_wakeup, 1);
+ output_handler->wakeup_table_footer(options.report_data);
}
if (options.energy_model_filename)
calculate_energy_consumption(&options);
+
+ output_handler->close_report_file(options.report_data);
}
release_init_pstates(initp);
diff --git a/idlestat.h b/idlestat.h
index bd1d705..c9a01a1 100644
--- a/idlestat.h
+++ b/idlestat.h
@@ -131,6 +131,8 @@ struct program_options {
char *outfilename;
int verbose;
char *energy_model_filename;
+ struct report_ops *report_ops;
+ void *report_data;
};
#define IDLE_DISPLAY 0x1
@@ -179,4 +181,29 @@ struct init_pstates {
unsigned int *freqs;
};
+struct report_ops {
+ int (*check_output)(struct program_options *, void *);
+
+ int (*open_report_file)(char *path, void *);
+ int (*close_report_file)(void *);
+
+ void (*cstate_table_header)(void *);
+ void (*cstate_table_footer)(void *);
+ void (*cstate_cpu_header)(const char *cpu, void *);
+ void (*cstate_single_state)(struct cpuidle_cstate*, void *);
+ void (*cstate_end_cpu)(void *);
+
+ void (*pstate_table_header)(void *);
+ void (*pstate_table_footer)(void *);
+ void (*pstate_cpu_header)(const char *cpu, void *);
+ void (*pstate_single_state)(struct cpufreq_pstate*, void *);
+ void (*pstate_end_cpu)(void*);
+
+ void (*wakeup_table_header)(void *);
+ void (*wakeup_table_footer)(void *);
+ void (*wakeup_cpu_header)(const char *cpu, void *);
+ void (*wakeup_single_state)(struct wakeup_irq *irqinfo, void *);
+ void (*wakeup_end_cpu)(void *);
+};
+
#endif
diff --git a/report_ops.h b/report_ops.h
new file mode 100644
index 0000000..96222ac
--- /dev/null
+++ b/report_ops.h
@@ -0,0 +1,6 @@
+#ifndef __REPORT_OPS_H
+#define __REPORT_OPS_H
+
+extern struct report_ops default_report_ops;
+
+#endif
diff --git a/topology.c b/topology.c
index 6c1097e..5cc741d 100644
--- a/topology.c
+++ b/topology.c
@@ -448,7 +448,7 @@ int establish_idledata_to_topo(struct cpuidle_datas *datas)
return 0;
}
-int dump_cpu_topo_info(int (*dump)(void *, char *), int cstate)
+int dump_cpu_topo_info(struct report_ops *ops, void *report_data, int (*dump)(struct report_ops *, void *, char *, void *), int cstate)
{
struct cpu_physical *s_phy;
struct cpu_core *s_core;
@@ -461,20 +461,20 @@ int dump_cpu_topo_info(int (*dump)(void *, char *), int cstate)
sprintf(tmp, "cluster%c", s_phy->physical_id + 'A');
if (cstate)
- dump(s_phy->cstates, tmp);
+ dump(ops, s_phy->cstates, tmp, report_data);
list_for_each_entry(s_core, &s_phy->core_head, list_core) {
if (s_core->is_ht && cstate) {
sprintf(tmp, "core%d", s_core->core_id);
- dump(s_core->cstates, tmp);
+ dump(ops, s_core->cstates, tmp, report_data);
}
list_for_each_entry(s_cpu, &s_core->cpu_head,
list_cpu) {
sprintf(tmp, "cpu%d", s_cpu->cpu_id);
- dump(cstate ?
+ dump(ops, cstate ?
(void *)s_cpu->cstates :
- (void *)s_cpu->pstates, tmp);
+ (void *)s_cpu->pstates, tmp, report_data);
}
}
}
diff --git a/topology.h b/topology.h
index d44bb45..0ddc7f1 100644
--- a/topology.h
+++ b/topology.h
@@ -66,7 +66,7 @@ extern int release_cpu_topo_info(void);
extern int output_cpu_topo_info(FILE *f);
extern int establish_idledata_to_topo(struct cpuidle_datas *datas);
extern int release_cpu_topo_cstates(void);
-extern int dump_cpu_topo_info(int (*dump)(void *, char *), int pstate);
+extern int dump_cpu_topo_info(struct report_ops *ops, void *report_data, int (*dump)(struct report_ops *, void *, char *, void *), int cstate);
extern struct cpuidle_cstates *core_cluster_data(struct cpu_core *s_core);
extern struct cpuidle_cstates *
diff --git a/utils.c b/utils.c
index ac2458c..0da877c 100644
--- a/utils.c
+++ b/utils.c
@@ -28,6 +28,12 @@
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <assert.h>
#include "utils.h"
@@ -114,3 +120,81 @@ out_free:
free(rpath);
return ret;
}
+
+int redirect_stdout_to_file(const char *path)
+{
+ int ret = 0;
+ int fd;
+
+ if (path) {
+ fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH);
+ if (fd < 0) {
+ fprintf(stderr, "%s: failed to open '%s'\n", __func__, path);
+ return -1;
+ }
+
+ fflush(stdout);
+ ret = dup2(fd, STDOUT_FILENO);
+ close(fd);
+
+ if (ret < 0) {
+ fprintf(stderr, "%s: failed to duplicate '%s'\n", __func__, path);
+ unlink(path);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void display_factored_time(double time, int align)
+{
+ char buffer[128];
+
+ if (time < 1000) {
+ sprintf(buffer, "%.0lfus", time);
+ printf("%*s", align, buffer);
+ }
+ else if (time < 1000000) {
+ sprintf(buffer, "%.2lfms", time / 1000.0);
+ printf("%*s", align, buffer);
+ }
+ else {
+ sprintf(buffer, "%.2lfs", time / 1000000.0);
+ printf("%*s", align, buffer);
+ }
+}
+
+void display_factored_freq(int freq, int align)
+{
+ char buffer[128];
+
+ if (freq < 1000) {
+ sprintf(buffer, "%dHz", freq);
+ printf("%*s", align, buffer);
+ } else if (freq < 1000000) {
+ sprintf(buffer, "%.2fMHz", (float)freq / 1000.0);
+ printf("%*s", align, buffer);
+ } else {
+ sprintf(buffer, "%.2fGHz", (float)freq / 1000000.0);
+ printf("%*s", align, buffer);
+ }
+}
+
+int check_window_size(void)
+{
+ struct winsize winsize;
+
+ /* Output is redirected */
+ if (!isatty(STDOUT_FILENO))
+ return 0;
+
+ /* Get terminal window size */
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
+
+ if (winsize.ws_col >= 80)
+ return 0;
+
+ return -1;
+}
diff --git a/utils.h b/utils.h
index d2cad5b..84aa75c 100644
--- a/utils.h
+++ b/utils.h
@@ -38,4 +38,9 @@ extern int read_int(const char *path, int *val);
extern int store_line(const char *line, void *data);
extern int file_read_value(const char *path, const char *name,
const char *format, void *value);
+extern int redirect_stdout_to_file(const char *path);
+extern void display_factored_time(double time, int align);
+extern void display_factored_freq(int freq, int align);
+extern int check_window_size(void);
+
#endif