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
This commit is contained in:
Rebecca Cran 2010-08-17 09:11:38 +00:00
parent 8fc4852252
commit cf2280aca7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211415
2 changed files with 88 additions and 8 deletions

View File

@ -35,6 +35,8 @@
.Op Fl a Ar mode .Op Fl a Ar mode
.Op Fl b Ar mode .Op Fl b Ar mode
.Op Fl i Ar percent .Op Fl i Ar percent
.Op Fl m Ar freq
.Op Fl M Ar freq
.Op Fl n Ar mode .Op Fl n Ar mode
.Op Fl p Ar ival .Op Fl p Ar ival
.Op Fl P Ar pidfile .Op Fl P Ar pidfile
@ -79,6 +81,10 @@ to use while on battery power.
Specifies the CPU load percent level when adaptive Specifies the CPU load percent level when adaptive
mode should begin to degrade performance to save power. mode should begin to degrade performance to save power.
The default is 50% or lower. 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 .It Fl n Ar mode
Selects the Selects the
.Ar mode .Ar mode

View File

@ -84,7 +84,8 @@ const char *modes[] = {
#define DEVCTL_MAXBUF 1024 #define DEVCTL_MAXBUF 1024
static int read_usage_times(int *load); 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 int set_freq(int freq);
static void acline_init(void); static void acline_init(void);
static void acline_read(void); static void acline_read(void);
@ -174,10 +175,10 @@ read_usage_times(int *load)
} }
static int 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; char *freqstr, *p, *q;
int i; int i, j;
size_t len = 0; size_t len = 0;
if (sysctl(levels_mib, 4, NULL, &len, NULL, 0)) if (sysctl(levels_mib, 4, NULL, &len, NULL, 0))
@ -201,19 +202,30 @@ read_freqs(int *numfreqs, int **freqs, int **power)
free(*freqs); free(*freqs);
return (-1); return (-1);
} }
for (i = 0, p = freqstr; i < *numfreqs; i++) { for (i = 0, j = 0, p = freqstr; i < *numfreqs; i++) {
q = strchr(p, ' '); q = strchr(p, ' ');
if (q != NULL) if (q != NULL)
*q = '\0'; *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(freqstr);
free(*freqs); free(*freqs);
free(*power); free(*power);
return (-1); return (-1);
} }
if (((*freqs)[j] >= minfreq || minfreq == -1) &&
((*freqs)[j] <= maxfreq || maxfreq == -1))
j++;
p = q + 1; p = q + 1;
} }
*numfreqs = j;
if ((*freqs = realloc(*freqs, *numfreqs * sizeof(int))) == NULL) {
free(freqstr);
free(*freqs);
free(*power);
return (-1);
}
free(freqstr); free(freqstr);
return (0); return (0);
} }
@ -422,7 +434,7 @@ usage(void)
{ {
fprintf(stderr, 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); exit(1);
} }
@ -435,6 +447,7 @@ main(int argc, char * argv[])
struct pidfh *pfh = NULL; struct pidfh *pfh = NULL;
const char *pidfile = NULL; const char *pidfile = NULL;
int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load; 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; int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
uint64_t mjoules_used; uint64_t mjoules_used;
size_t len; size_t len;
@ -452,7 +465,7 @@ main(int argc, char * argv[])
if (geteuid() != 0) if (geteuid() != 0)
errx(1, "must be root to run"); 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) { switch (ch) {
case 'a': case 'a':
parse_mode(optarg, &mode_ac, ch); parse_mode(optarg, &mode_ac, ch);
@ -468,6 +481,22 @@ main(int argc, char * argv[])
usage(); usage();
} }
break; 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': case 'n':
parse_mode(optarg, &mode_none, ch); parse_mode(optarg, &mode_none, ch);
break; break;
@ -515,8 +544,10 @@ main(int argc, char * argv[])
/* Check if we can read the load and supported freqs. */ /* Check if we can read the load and supported freqs. */
if (read_usage_times(NULL)) if (read_usage_times(NULL))
err(1, "read_usage_times"); 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"); 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. */ /* Run in the background unless in verbose mode. */
if (!vflag) { if (!vflag) {
@ -552,6 +583,49 @@ main(int argc, char * argv[])
i = get_freq_id(curfreq, freqs, numfreqs); i = get_freq_id(curfreq, freqs, numfreqs);
if (freq < 1) if (freq < 1)
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; idle = 0;
/* Main loop. */ /* Main loop. */
for (;;) { for (;;) {