[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", &notify) == 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