From ab19351c394ed830184e61e8c97f6253f3f3eb21 Mon Sep 17 00:00:00 2001 From: Nate Lawson Date: Sun, 10 Apr 2005 19:02:29 +0000 Subject: [PATCH] Add support for recording the total energy used (in joules) when in verbose mode. This is useful for profiling new adaptive algorithms in performance (via time(1)) and total energy consumed for a given workload. --- usr.sbin/powerd/powerd.c | 53 +++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/usr.sbin/powerd/powerd.c b/usr.sbin/powerd/powerd.c index 18566d2ffec4..a2ecb48cfb20 100644 --- a/usr.sbin/powerd/powerd.c +++ b/usr.sbin/powerd/powerd.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -69,10 +70,11 @@ const char *modes[] = { #define APMDEV "/dev/apm" static int read_usage_times(long *idle, long *total); -static int read_freqs(int *numfreqs, int **freqs); +static int read_freqs(int *numfreqs, int **freqs, int **power); static int set_freq(int freq); static void acline_init(void); static int acline_read(void); +static void handle_sigs(int sig); static void parse_mode(char *arg, int *mode, int ch); static void usage(void); @@ -88,6 +90,7 @@ static int cpu_idle_mark; static int poll_ival; static int apm_fd; +static int exit_requested; static int read_usage_times(long *idle, long *total) @@ -116,7 +119,7 @@ read_usage_times(long *idle, long *total) } static int -read_freqs(int *numfreqs, int **freqs) +read_freqs(int *numfreqs, int **freqs, int **power) { char *freqstr, *p, *q; int i; @@ -138,13 +141,19 @@ read_freqs(int *numfreqs, int **freqs) free(freqstr); return (-1); } + if ((*power = malloc(*numfreqs * sizeof(int))) == NULL) { + free(freqstr); + free(*freqs); + return (-1); + } for (i = 0, p = freqstr; i < *numfreqs; i++) { q = strchr(p, ' '); if (q != NULL) *q = '\0'; - if (sscanf(p, "%d/%*d", &(*freqs)[i]) != 1) { + if (sscanf(p, "%d/%d", &(*freqs)[i], &(*power)[i]) != 2) { free(freqstr); free(*freqs); + free(*power); return (-1); } p = q + 1; @@ -224,6 +233,12 @@ parse_mode(char *arg, int *mode, int ch) errx(1, "bad option: -%c %s", (char)ch, optarg); } +static void +handle_sigs(int __unused sig) +{ + exit_requested = 1; +} + static void usage(void) { @@ -237,8 +252,9 @@ int main(int argc, char * argv[]) { long idle, total; - int curfreq, *freqs, i, numfreqs; + int curfreq, *freqs, i, *mwatts, numfreqs; int ch, mode_ac, mode_battery, mode_none, acline, mode, vflag; + uint64_t mjoules_used; size_t len; /* Default mode for all AC states is adaptive. */ @@ -246,6 +262,7 @@ main(int argc, char * argv[]) cpu_running_mark = DEFAULT_ACTIVE_PERCENT; cpu_idle_mark = DEFAULT_IDLE_PERCENT; poll_ival = DEFAULT_POLL_INTERVAL; + mjoules_used = 0; vflag = 0; apm_fd = -1; @@ -307,7 +324,7 @@ main(int argc, char * argv[]) /* Check if we can read the idle time and supported freqs. */ if (read_usage_times(NULL, NULL)) err(1, "read_usage_times"); - if (read_freqs(&numfreqs, &freqs)) + if (read_freqs(&numfreqs, &freqs, &mwatts)) err(1, "error reading supported CPU frequencies"); /* Decide whether to use ACPI or APM to read the AC line status. */ @@ -316,12 +333,23 @@ main(int argc, char * argv[]) /* Run in the background unless in verbose mode. */ if (!vflag) daemon(0, 0); + signal(SIGINT, handle_sigs); + signal(SIGTERM, handle_sigs); /* Main loop. */ for (;;) { /* Check status every few milliseconds. */ usleep(poll_ival); + /* If the user requested we quit, print some statistics. */ + if (exit_requested) { + if (vflag && mjoules_used != 0) + printf("total joules used: %u.%03u\n", + (u_int)(mjoules_used / 1000), + (int)mjoules_used % 1000); + break; + } + /* Read the current AC status and record the mode. */ acline = acline_read(); switch (acline) { @@ -343,6 +371,18 @@ main(int argc, char * argv[]) if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0)) err(1, "error reading current CPU frequency"); + if (vflag) { + for (i = 0; i < numfreqs; i++) { + if (freqs[i] == curfreq) + break; + } + + /* Keep a sum of all power actually used. */ + if (i < numfreqs && mwatts[i] != -1) + mjoules_used += + (mwatts[i] * (poll_ival / 1000)) / 1000; + } + /* Always switch to the lowest frequency in min mode. */ if (mode == MODE_MIN) { if (curfreq != freqs[numfreqs - 1]) { @@ -409,7 +449,8 @@ main(int argc, char * argv[]) freqs[i]); } } - /* NOTREACHED */ + free(freqs); + free(mwatts); exit(0); }