aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/powerd
diff options
context:
space:
mode:
authorRebecca Cran <brucec@FreeBSD.org>2010-08-17 09:11:38 +0000
committerRebecca Cran <brucec@FreeBSD.org>2010-08-17 09:11:38 +0000
commitcf2280aca702edef4dbccf8d1e1a8ac01c8565e7 (patch)
tree1de999c8f4363d38624c629f28cc339229e3f834 /usr.sbin/powerd
parent8fc48522522b62e7d812b07a3305535ebdfeddcc (diff)
downloadsrc-cf2280aca702edef4dbccf8d1e1a8ac01c8565e7.tar.gz
src-cf2280aca702edef4dbccf8d1e1a8ac01c8565e7.zip
Add -m and -M options to control the minimum and maximum frequency.
PR: bin/145063 Submitted by: Boris Kochergin <spawk at acm.poly.edu> Reviewed by: cperciva Approved by: rrs (mentor) MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=211415
Diffstat (limited to 'usr.sbin/powerd')
-rw-r--r--usr.sbin/powerd/powerd.86
-rw-r--r--usr.sbin/powerd/powerd.c90
2 files changed, 88 insertions, 8 deletions
diff --git a/usr.sbin/powerd/powerd.8 b/usr.sbin/powerd/powerd.8
index 2d6acffd22a6..0991bce1105a 100644
--- a/usr.sbin/powerd/powerd.8
+++ b/usr.sbin/powerd/powerd.8
@@ -35,6 +35,8 @@
.Op Fl a Ar mode
.Op Fl b Ar mode
.Op Fl i Ar percent
+.Op Fl m Ar freq
+.Op Fl M Ar freq
.Op Fl n Ar mode
.Op Fl p Ar ival
.Op Fl P Ar pidfile
@@ -79,6 +81,10 @@ to use while on battery power.
Specifies the CPU load percent level when adaptive
mode should begin to degrade performance to save power.
The default is 50% or lower.
+.It Fl m Ar freq
+Specifies the minimum frequency to throttle down to.
+.It Fl M Ar freq
+Specifies the maximum frequency to throttle up to.
.It Fl n Ar mode
Selects the
.Ar mode
diff --git a/usr.sbin/powerd/powerd.c b/usr.sbin/powerd/powerd.c
index 7192bddbbe95..a1a5126223ae 100644
--- a/usr.sbin/powerd/powerd.c
+++ b/usr.sbin/powerd/powerd.c
@@ -84,7 +84,8 @@ const char *modes[] = {
#define DEVCTL_MAXBUF 1024
static int read_usage_times(int *load);
-static int read_freqs(int *numfreqs, int **freqs, int **power);
+static int read_freqs(int *numfreqs, int **freqs, int **power,
+ int minfreq, int maxfreq);
static int set_freq(int freq);
static void acline_init(void);
static void acline_read(void);
@@ -174,10 +175,10 @@ read_usage_times(int *load)
}
static int
-read_freqs(int *numfreqs, int **freqs, int **power)
+read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq)
{
char *freqstr, *p, *q;
- int i;
+ int i, j;
size_t len = 0;
if (sysctl(levels_mib, 4, NULL, &len, NULL, 0))
@@ -201,19 +202,30 @@ read_freqs(int *numfreqs, int **freqs, int **power)
free(*freqs);
return (-1);
}
- for (i = 0, p = freqstr; i < *numfreqs; i++) {
+ for (i = 0, j = 0, p = freqstr; i < *numfreqs; i++) {
q = strchr(p, ' ');
if (q != NULL)
*q = '\0';
- if (sscanf(p, "%d/%d", &(*freqs)[i], &(*power)[i]) != 2) {
+ if (sscanf(p, "%d/%d", &(*freqs)[j], &(*power)[i]) != 2) {
free(freqstr);
free(*freqs);
free(*power);
return (-1);
}
+ if (((*freqs)[j] >= minfreq || minfreq == -1) &&
+ ((*freqs)[j] <= maxfreq || maxfreq == -1))
+ j++;
p = q + 1;
}
+ *numfreqs = j;
+ if ((*freqs = realloc(*freqs, *numfreqs * sizeof(int))) == NULL) {
+ free(freqstr);
+ free(*freqs);
+ free(*power);
+ return (-1);
+ }
+
free(freqstr);
return (0);
}
@@ -422,7 +434,7 @@ usage(void)
{
fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
exit(1);
}
@@ -435,6 +447,7 @@ main(int argc, char * argv[])
struct pidfh *pfh = NULL;
const char *pidfile = NULL;
int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
+ int minfreq = -1, maxfreq = -1;
int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
uint64_t mjoules_used;
size_t len;
@@ -452,7 +465,7 @@ main(int argc, char * argv[])
if (geteuid() != 0)
errx(1, "must be root to run");
- while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != -1)
+ while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:v")) != -1)
switch (ch) {
case 'a':
parse_mode(optarg, &mode_ac, ch);
@@ -468,6 +481,22 @@ main(int argc, char * argv[])
usage();
}
break;
+ case 'm':
+ minfreq = atoi(optarg);
+ if (minfreq < 0) {
+ warnx("%d is not a valid CPU frequency",
+ minfreq);
+ usage();
+ }
+ break;
+ case 'M':
+ maxfreq = atoi(optarg);
+ if (maxfreq < 0) {
+ warnx("%d is not a valid CPU frequency",
+ maxfreq);
+ usage();
+ }
+ break;
case 'n':
parse_mode(optarg, &mode_none, ch);
break;
@@ -515,8 +544,10 @@ main(int argc, char * argv[])
/* Check if we can read the load and supported freqs. */
if (read_usage_times(NULL))
err(1, "read_usage_times");
- if (read_freqs(&numfreqs, &freqs, &mwatts))
+ if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq))
err(1, "error reading supported CPU frequencies");
+ if (numfreqs == 0)
+ errx(1, "no CPU frequencies in user-specified range");
/* Run in the background unless in verbose mode. */
if (!vflag) {
@@ -552,6 +583,49 @@ main(int argc, char * argv[])
i = get_freq_id(curfreq, freqs, numfreqs);
if (freq < 1)
freq = 1;
+
+ /*
+ * If we are in adaptive mode and the current frequency is outside the
+ * user-defined range, adjust it to be within the user-defined range.
+ */
+ acline_read();
+ if (acline_status > SRC_UNKNOWN)
+ errx(1, "invalid AC line status %d", acline_status);
+ if ((acline_status == SRC_AC &&
+ (mode_ac == MODE_ADAPTIVE || mode_ac == MODE_HIADAPTIVE)) ||
+ (acline_status == SRC_BATTERY &&
+ (mode_battery == MODE_ADAPTIVE || mode_battery == MODE_HIADAPTIVE)) ||
+ (acline_status == SRC_UNKNOWN &&
+ (mode_none == MODE_ADAPTIVE || mode_none == MODE_HIADAPTIVE))) {
+ /* Read the current frequency. */
+ len = sizeof(curfreq);
+ if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) != 0) {
+ if (vflag)
+ warn("error reading current CPU frequency");
+ }
+ if (curfreq < freqs[numfreqs - 1]) {
+ if (vflag) {
+ printf("CPU frequency is below user-defined "
+ "minimum; changing frequency to %d "
+ "MHz\n", freqs[numfreqs - 1]);
+ }
+ if (set_freq(freqs[numfreqs - 1]) != 0) {
+ warn("error setting CPU freq %d",
+ freqs[numfreqs - 1]);
+ }
+ } else if (curfreq > freqs[0]) {
+ if (vflag) {
+ printf("CPU frequency is above user-defined "
+ "maximum; changing frequency to %d "
+ "MHz\n", freqs[0]);
+ }
+ if (set_freq(freqs[0]) != 0) {
+ warn("error setting CPU freq %d",
+ freqs[0]);
+ }
+ }
+ }
+
idle = 0;
/* Main loop. */
for (;;) {