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 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

View File

@ -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 (;;) {