[Midnightbsd-cvs] src [6525] trunk/usr.sbin/powerd: add new min / max frequency flags
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun Dec 22 16:43:29 EST 2013
Revision: 6525
http://svnweb.midnightbsd.org/src/?rev=6525
Author: laffer1
Date: 2013-12-22 16:43:29 -0500 (Sun, 22 Dec 2013)
Log Message:
-----------
add new min / max frequency flags
Obtained from: FreeBSD
Modified Paths:
--------------
trunk/usr.sbin/powerd/Makefile
trunk/usr.sbin/powerd/powerd.8
trunk/usr.sbin/powerd/powerd.c
Modified: trunk/usr.sbin/powerd/Makefile
===================================================================
--- trunk/usr.sbin/powerd/Makefile 2013-12-22 21:37:59 UTC (rev 6524)
+++ trunk/usr.sbin/powerd/Makefile 2013-12-22 21:43:29 UTC (rev 6525)
@@ -3,13 +3,8 @@
PROG= powerd
MAN= powerd.8
-WARNS?= 6
DPADD= ${LIBUTIL}
LDADD= -lutil
-.if ${MACHINE_ARCH} == "i386"
-CFLAGS+=-DUSE_APM
-.endif
-
.include <bsd.prog.mk>
Modified: trunk/usr.sbin/powerd/powerd.8
===================================================================
--- trunk/usr.sbin/powerd/powerd.8 2013-12-22 21:37:59 UTC (rev 6524)
+++ trunk/usr.sbin/powerd/powerd.8 2013-12-22 21:43:29 UTC (rev 6525)
@@ -25,7 +25,7 @@
.\" $FreeBSD: src/usr.sbin/powerd/powerd.8,v 1.10.2.2 2009/01/09 22:10:07 mav Exp $
.\" $MidnightBSD: src/usr.sbin/powerd/powerd.8,v 1.3 2010/01/17 14:42:44 laffer1 Exp $
.\"
-.Dd January 17, 2009
+.Dd July 4, 2013
.Dt POWERD 8
.Os
.Sh NAME
@@ -36,6 +36,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
@@ -46,26 +48,43 @@
.Nm
utility monitors the system state and sets various power control options
accordingly.
-It offers three modes (maximum, minimum, and adaptive) that can be
-individually selected while on AC power or batteries.
-The modes maximum, minimum, adaptive and hiadaptive may be abbreviated
-max, min, adp, hadp.
-.Pp
-Maximum mode chooses the highest performance values.
-Minimum mode selects the lowest performance values to get the most power
-savings.
-Adaptive mode attempts to strike a balance by degrading performance when
-the system appears idle and increasing it when the system is busy.
+It offers power-saving modes that can be
+individually selected for operation on AC power or batteries.
+.Bl -tag -width ".Ar hiadaptive"
+.It Ar maximum
+Choose the highest performance values.
+May be abbreviated as
+.Ar max .
+.It Ar minimum
+Choose the lowest performance values to get the most power savings.
+May be abbreviated as
+.Ar min .
+.It Ar adaptive
+Attempt to strike a balance by degrading performance when the system
+appears idle and increasing it when the system is busy.
It offers a good balance between a small performance loss for greatly
increased power savings.
-Hiadaptive mode is alike adaptive mode, but tuned for systems where
-performance and interactivity are more important then power consumption.
-It rises frequency faster, drops slower and keeps twice lower CPU load.
-The default mode is adaptive for battery power and hiadaptive for the rest.
+May be abbreviated as
+.Ar adp .
+.It Ar hiadaptive
+Like
+.Ar adaptive
+mode, but tuned for systems where performance and interactivity are
+more important than power consumption.
+It increases frequency faster, reduces frequency less aggressively, and
+will maintain full frequency for longer.
+May be abbreviated as
+.Ar hadp .
+.El
.Pp
-The
+The default mode is
+.Ar adaptive
+for battery power and
+.Ar hiadaptive
+for the rest.
+.Pp
.Nm
-utility recognizes the following runtime options:
+recognizes these runtime options:
.Bl -tag -width ".Fl r Ar percent"
.It Fl a Ar mode
Selects the
@@ -79,6 +98,10 @@
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
Modified: trunk/usr.sbin/powerd/powerd.c
===================================================================
--- trunk/usr.sbin/powerd/powerd.c 2013-12-22 21:37:59 UTC (rev 6524)
+++ trunk/usr.sbin/powerd/powerd.c 2013-12-22 21:43:29 UTC (rev 6525)
@@ -1,4 +1,4 @@
-/* $MidnightBSD: src/usr.sbin/powerd/powerd.c,v 1.3 2010/01/17 14:42:44 laffer1 Exp $ */
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2004 Colin Percival
* Copyright (c) 2005 Nate Lawson
@@ -47,6 +47,10 @@
#include <string.h>
#include <unistd.h>
+#ifdef __i386__
+#define USE_APM
+#endif
+
#ifdef USE_APM
#include <machine/apm_bios.h>
#endif
@@ -75,12 +79,14 @@
};
#define ACPIAC "hw.acpi.acline"
+#define PMUAC "dev.pmu.0.acline"
#define APMDEV "/dev/apm"
#define DEVDPIPE "/var/run/devd.pipe"
#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);
@@ -94,7 +100,8 @@
static int cp_times_mib[2];
static int freq_mib[4];
static int levels_mib[4];
-static int acline_mib[3];
+static int acline_mib[4];
+static size_t acline_mib_len;
/* Configuration */
static int cpu_running_mark;
@@ -106,7 +113,7 @@
static power_src_t acline_status;
static enum {
ac_none,
- ac_acpi_sysctl,
+ ac_sysctl,
ac_acpi_devd,
#ifdef USE_APM
ac_apm,
@@ -147,7 +154,7 @@
error = sysctl(cp_times_mib, 2, cp_times, &cp_times_len, NULL, 0);
if (error)
return (error);
-
+
if (load) {
*load = 0;
for (cpu = 0; cpu < ncpus; cpu++) {
@@ -158,7 +165,7 @@
}
if (total == 0)
continue;
- *load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] -
+ *load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] -
cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
}
}
@@ -169,10 +176,10 @@
}
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))
@@ -196,19 +203,30 @@
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);
}
@@ -218,7 +236,7 @@
{
size_t len;
int curfreq;
-
+
len = sizeof(curfreq);
if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) != 0) {
if (vflag)
@@ -244,7 +262,7 @@
get_freq_id(int freq, int *freqs, int numfreqs)
{
int i = 1;
-
+
while (i < numfreqs) {
if (freqs[i] < freq)
break;
@@ -260,11 +278,10 @@
static void
acline_init(void)
{
- size_t len;
+ acline_mib_len = 4;
- len = 3;
- if (sysctlnametomib(ACPIAC, acline_mib, &len) == 0) {
- acline_mode = ac_acpi_sysctl;
+ if (sysctlnametomib(ACPIAC, acline_mib, &acline_mib_len) == 0) {
+ acline_mode = ac_sysctl;
if (vflag)
warnx("using sysctl for AC line status");
#ifdef USE_APM
@@ -292,7 +309,7 @@
if (vflag)
warnx("lost devd connection, switching to sysctl");
devd_close();
- acline_mode = ac_acpi_sysctl;
+ acline_mode = ac_sysctl;
/* FALLTHROUGH */
}
if (rlen > 0 &&
@@ -302,12 +319,13 @@
sscanf(ptr, "notify=%x", ¬ify) == 1)
acline_status = (notify ? SRC_AC : SRC_BATTERY);
}
- if (acline_mode == ac_acpi_sysctl) {
+ if (acline_mode == ac_sysctl) {
int acline;
size_t len;
len = sizeof(acline);
- if (sysctl(acline_mib, 3, &acline, &len, NULL, 0) == 0)
+ if (sysctl(acline_mib, acline_mib_len, &acline, &len,
+ NULL, 0) == 0)
acline_status = (acline ? SRC_AC : SRC_BATTERY);
else
acline_status = SRC_UNKNOWN;
@@ -327,7 +345,7 @@
}
#endif
/* try to (re)connect to devd */
- if (acline_mode == ac_acpi_sysctl) {
+ if (acline_mode == ac_sysctl) {
struct timeval now;
gettimeofday(&now, NULL);
@@ -411,7 +429,7 @@
{
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);
}
@@ -424,7 +442,8 @@
struct pidfh *pfh = NULL;
const char *pidfile = NULL;
int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
- int ch, mode, mode_ac, mode_battery, mode_none;
+ int minfreq = -1, maxfreq = -1;
+ int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
uint64_t mjoules_used;
size_t len;
@@ -441,7 +460,7 @@
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);
@@ -457,6 +476,22 @@
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;
@@ -504,8 +539,10 @@
/* 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) {
@@ -537,9 +574,54 @@
signal(SIGINT, handle_sigs);
signal(SIGTERM, handle_sigs);
- freq = initfreq = get_freq();
+ freq = initfreq = curfreq = get_freq();
+ 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 (;;) {
FD_ZERO(&fdset);
@@ -549,8 +631,14 @@
} else {
nfds = 0;
}
- timeout.tv_sec = poll_ival / 1000000;
- timeout.tv_usec = poll_ival % 1000000;
+ if (mode == MODE_HIADAPTIVE || idle < 120)
+ to = poll_ival;
+ else if (idle < 360)
+ to = poll_ival * 2;
+ else
+ to = poll_ival * 4;
+ timeout.tv_sec = to / 1000000;
+ timeout.tv_usec = to % 1000000;
select(nfds, &fdset, NULL, &fdset, &timeout);
/* If the user requested we quit, print some statistics. */
@@ -579,11 +667,12 @@
}
/* Read the current frequency. */
- if ((curfreq = get_freq()) == 0)
- continue;
-
- i = get_freq_id(curfreq, freqs, numfreqs);
-
+ if (idle % 32 == 0) {
+ if ((curfreq = get_freq()) == 0)
+ continue;
+ i = get_freq_id(curfreq, freqs, numfreqs);
+ }
+ idle++;
if (vflag) {
/* Keep a sum of all power actually used. */
if (mwatts[i] != -1)
@@ -600,6 +689,7 @@
"changing frequency to %d MHz\n",
modes[acline_status], freq);
}
+ idle = 0;
if (set_freq(freq) != 0) {
warn("error setting CPU freq %d",
freq);
@@ -618,9 +708,10 @@
"changing frequency to %d MHz\n",
modes[acline_status], freq);
}
+ idle = 0;
if (set_freq(freq) != 0) {
warn("error setting CPU freq %d",
- freq);
+ freq);
continue;
}
}
@@ -633,7 +724,7 @@
warn("read_usage_times() failed");
continue;
}
-
+
if (mode == MODE_ADAPTIVE) {
if (load > cpu_running_mark) {
if (load > 95 || load > cpu_running_mark * 2)
@@ -644,7 +735,7 @@
freq = freqs[0];
} else if (load < cpu_idle_mark &&
curfreq * load < freqs[get_freq_id(
- freq * 7 / 8, freqs, numfreqs)] *
+ freq * 7 / 8, freqs, numfreqs)] *
cpu_running_mark) {
freq = freq * 7 / 8;
if (freq < freqs[numfreqs - 1])
@@ -660,7 +751,7 @@
freq = freqs[0] * 2;
} else if (load < cpu_idle_mark / 2 &&
curfreq * load < freqs[get_freq_id(
- freq * 31 / 32, freqs, numfreqs)] *
+ freq * 31 / 32, freqs, numfreqs)] *
cpu_running_mark / 2) {
freq = freq * 31 / 32;
if (freq < freqs[numfreqs - 1])
@@ -678,6 +769,7 @@
" speed from %d MHz to %d MHz\n",
freqs[i], freqs[j]);
}
+ idle = 0;
if (set_freq(freqs[j]))
warn("error setting CPU frequency %d",
freqs[j]);
More information about the Midnightbsd-cvs
mailing list