misc/136354: powerd Support for maxspeed in adaptive modes

Rene Schickbauer cavac at magicbooks.org
Mon Jul 20 13:20:08 UTC 2009


The following reply was made to PR bin/136354; it has been noted by GNATS.

From: "Rene Schickbauer" <cavac at magicbooks.org>
To: bug-followup at FreeBSD.org, freebsd-bugs at FreeBSD.org
Cc:  
Subject: Re: misc/136354: powerd Support for maxspeed in adaptive modes
Date: Mon, 20 Jul 2009 15:17:49 +0200 (CEST)

 ------=_20090720151749_38089
 Content-Type: text/plain; charset="iso-8859-1"
 Content-Transfer-Encoding: 8bit
 
 Here is an updated patch that allows setting of minimum and maximum speeds.
 Seperately for battery and AC mode, of course.
 
 I also updated the man-page.
 
 (Hope i didn't mess this follow-up up, gnats doesn't like my webmail)
 ------=_20090720151749_38089
 Content-Type: text/plain; name="powerd.txt"
 Content-Transfer-Encoding: 8bit
 Content-Disposition: attachment; filename="powerd.txt"
 
 diff -u powerd.orig2/powerd.8 powerd/powerd.8
 --- powerd.orig2/powerd.8	2009-07-20 11:43:20.000000000 +0200
 +++ powerd/powerd.8	2009-07-20 14:43:36.000000000 +0200
 @@ -24,7 +24,7 @@
  .\"
  .\" $FreeBSD: src/usr.sbin/powerd/powerd.8,v 1.13 2008/12/24 09:17:30 trhodes Exp $
  .\"
 -.Dd December 24, 2008
 +.Dd July 5, 2009
  .Dt POWERD 8
  .Os
  .Sh NAME
 @@ -34,6 +34,10 @@
  .Nm
  .Op Fl a Ar mode
  .Op Fl b Ar mode
 +.Op Fl c Ar minspeed
 +.Op Fl d Ar maxspeed
 +.Op Fl e Ar minspeed
 +.Op Fl f Ar maxspeed
  .Op Fl i Ar percent
  .Op Fl n Ar mode
  .Op Fl p Ar ival
 @@ -45,22 +49,10 @@
  .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 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.
 +It offers multiple modes (maximum, minimum, and two adaptive modes) that can be
 +individually selected while on AC power or batteries. See
 +.Ar MODES
 +below for details.
  .Pp
  The
  .Nm
 @@ -74,6 +66,22 @@
  Selects the
  .Ar mode
  to use while on battery power.
 +.It Fl c Ar mode
 +Selects the
 +.Ar minspeed
 +in Mhz for adaptive modes to use while on AC power.
 +.It Fl d Ar mode
 +Selects the
 +.Ar maxspeed
 +in Mhz for adaptive modes to use while on AC power.
 +.It Fl e Ar mode
 +Selects the
 +.Ar minspeed
 +in Mhz for adaptive modes to use while on battery power.
 +.It Fl f Ar mode
 +Selects the
 +.Ar maxspeed
 +in Mhz for adaptive modes to use while on battery power.
  .It Fl i Ar percent
  Specifies the CPU load percent level when adaptive
  mode should begin to degrade performance to save power.
 @@ -100,6 +108,48 @@
  .Nm
  will operate in the foreground.
  .El
 +.Sh MODES
 +The following
 +.Ar mode
 +flags are currently implemented:
 +.Pp
 +.Ar max
 +or
 +.Ar maximum
 +mode chooses the highest performance values.
 +.Pp
 +.Ar min
 +or
 +.Ar minimum
 +mode selects the lowest performance values to get the most power
 +savings.
 +.Pp
 +.Ar adp
 +or
 +.Ar 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 a good balance between a small performance loss for greatly
 +increased power savings.
 +.Pp
 +.Ar hadp
 +or
 +.Ar 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.
 +.Pp
 +For both adaptive modes, it is possible to set
 +.Ar maxspeed
 +to lower power consumption by limiting the dynamic range
 +.Nm
 +uses.
 +.Pp
 +The default mode is
 +.Ar adaptive
 +for battery power and
 +.Ar hiadaptive
 +for the rest.
  .Sh SEE ALSO
  .Xr acpi 4 ,
  .Xr apm 4 ,
 @@ -121,6 +171,8 @@
  then updated it for
  .Xr cpufreq 4 ,
  added features, and wrote this manual page.
 +.An Rene Schickbauer
 +added speed limiting and rewrote parts of this manual page.
  .Sh BUGS
  The
  .Nm
 diff -u powerd.orig2/powerd.c powerd/powerd.c
 --- powerd.orig2/powerd.c	2009-07-20 11:43:20.000000000 +0200
 +++ powerd/powerd.c	2009-07-20 14:53:47.000000000 +0200
 @@ -118,6 +118,11 @@
  #endif
  static int	devd_pipe = -1;
  
 +static int  minspeed_ac = 0;
 +static int  maxspeed_ac = 0;
 +static int  minspeed_battery = 0;
 +static int  maxspeed_battery = 0;
 +
  #define DEVD_RETRY_INTERVAL 60 /* seconds */
  static struct timeval tried_devd;
  
 @@ -154,13 +159,13 @@
  		for (cpu = 0; cpu < ncpus; cpu++) {
  			total = 0;
  			for (i = 0; i < CPUSTATES; i++) {
 -			    total += cp_times[cpu * CPUSTATES + i] -
 +				total += cp_times[cpu * CPUSTATES + i] -
  				cp_times_old[cpu * CPUSTATES + i];
  			}
  			if (total == 0)
  				continue;
  			*load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] - 
 -			    cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
 +				cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total;
  		}
  	}
  
 @@ -302,10 +307,10 @@
  			/* FALLTHROUGH */
  		}
  		if (rlen > 0 &&
 -		    (ptr = strstr(buf, "system=ACPI")) != NULL &&
 -		    (ptr = strstr(ptr, "subsystem=ACAD")) != NULL &&
 -		    (ptr = strstr(ptr, "notify=")) != NULL &&
 -		    sscanf(ptr, "notify=%x", &notify) == 1)
 +			(ptr = strstr(buf, "system=ACPI")) != NULL &&
 +			(ptr = strstr(ptr, "subsystem=ACAD")) != NULL &&
 +			(ptr = strstr(ptr, "notify=")) != NULL &&
 +			sscanf(ptr, "notify=%x", &notify) == 1)
  			acline_status = (notify ? SRC_AC : SRC_BATTERY);
  	}
  	if (acline_mode == ac_sysctl) {
 @@ -314,7 +319,7 @@
  
  		len = sizeof(acline);
  		if (sysctl(acline_mib, acline_mib_len, &acline, &len,
 -		    NULL, 0) == 0)
 +			NULL, 0) == 0)
  			acline_status = (acline ? SRC_AC : SRC_BATTERY);
  		else
  			acline_status = SRC_UNKNOWN;
 @@ -364,7 +369,7 @@
  	devd_addr.sun_family = PF_LOCAL;
  	strlcpy(devd_addr.sun_path, DEVDPIPE, sizeof(devd_addr.sun_path));
  	if (connect(devd_pipe, (struct sockaddr *)&devd_addr,
 -	    sizeof(devd_addr)) == -1) {
 +		sizeof(devd_addr)) == -1) {
  		if (vflag)
  			warn("%s(): connect()", __func__);
  		close(devd_pipe);
 @@ -418,7 +423,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] [-c minspeed] [-d maxspeed] [-e minspeed] [-f maxspeed] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile] \n");
  	exit(1);
  }
  
 @@ -431,13 +436,19 @@
  	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 ch, mode, mode_ac, mode_battery, mode_none, minspeed, maxspeed;
  	uint64_t mjoules_used;
  	size_t len;
  
  	/* Default mode for all AC states is adaptive. */
  	mode_ac = mode_none = MODE_HIADAPTIVE;
  	mode_battery = MODE_ADAPTIVE;
 +	minspeed_ac = 0;
 +	maxspeed_ac = 0;
 +	minspeed_battery = 0;
 +	maxspeed_battery = 0;
 +	minspeed = 0;
 +	maxspeed = 0;
  	cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
  	cpu_idle_mark = DEFAULT_IDLE_PERCENT;
  	poll_ival = DEFAULT_POLL_INTERVAL;
 @@ -448,7 +459,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:c:d:e:f:i:n:p:P:r:v")) != -1)
  		switch (ch) {
  		case 'a':
  			parse_mode(optarg, &mode_ac, ch);
 @@ -456,11 +467,43 @@
  		case 'b':
  			parse_mode(optarg, &mode_battery, ch);
  			break;
 +		case 'c':
 +			minspeed_ac = atoi(optarg);
 +			if (minspeed_ac <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					minspeed_ac);
 +				usage();
 +			}
 +			break;
 +		case 'd':
 +			maxspeed_ac = atoi(optarg);
 +			if (maxspeed_ac <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					maxspeed_ac);
 +				usage();
 +			}
 +			break;
 +		case 'e':
 +			minspeed_battery = atoi(optarg);
 +			if (minspeed_battery <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					minspeed_battery);
 +				usage();
 +			}
 +			break;
 +		case 'f':
 +			maxspeed_battery = atoi(optarg);
 +			if (maxspeed_battery <= 0) {
 +				warnx("%d is not a valid CPU speed",
 +					maxspeed_battery);
 +				usage();
 +			}
 +			break;
  		case 'i':
  			cpu_idle_mark = atoi(optarg);
  			if (cpu_idle_mark < 0 || cpu_idle_mark > 100) {
  				warnx("%d is not a valid percent",
 -				    cpu_idle_mark);
 +					cpu_idle_mark);
  				usage();
  			}
  			break;
 @@ -481,7 +524,7 @@
  			cpu_running_mark = atoi(optarg);
  			if (cpu_running_mark <= 0 || cpu_running_mark > 100) {
  				warnx("%d is not a valid percent",
 -				    cpu_running_mark);
 +					cpu_running_mark);
  				usage();
  			}
  			break;
 @@ -492,6 +535,19 @@
  			usage();
  		}
  
 +	if (minspeed_battery > 0 && maxspeed_battery > 0 &&
 +			minspeed_battery > maxspeed_battery) {
 +		warnx("Battery mode: minspeed (%d) can not be greater than maxspeed (%d)",
 +			minspeed_battery, maxspeed_battery);
 +		usage();
 +	}
 +	if (minspeed_ac > 0 && maxspeed_ac > 0 &&
 +			minspeed_ac > maxspeed_ac) {
 +		warnx("AC mode: minspeed (%d) can not be greater than maxspeed (%d)",
 +			minspeed_ac, maxspeed_ac);
 +		usage();
 +	}
 +
  	mode = mode_none;
  
  	/* Poll interval is in units of ms. */
 @@ -522,7 +578,7 @@
  		if (pfh == NULL) {
  			if (errno == EEXIST) {
  				errx(1, "powerd already running, pid: %d",
 -				    otherpid);
 +					otherpid);
  			}
  			warn("cannot open pid file");
  		}
 @@ -564,8 +620,8 @@
  		if (exit_requested) {
  			if (vflag && mjoules_used != 0)
  				printf("total joules used: %u.%03u\n",
 -				    (u_int)(mjoules_used / 1000),
 -				    (int)mjoules_used % 1000);
 +					(u_int)(mjoules_used / 1000),
 +					(int)mjoules_used % 1000);
  			break;
  		}
  
 @@ -574,12 +630,18 @@
  		switch (acline_status) {
  		case SRC_AC:
  			mode = mode_ac;
 +			minspeed = minspeed_ac;
 +			maxspeed = maxspeed_ac;
  			break;
  		case SRC_BATTERY:
  			mode = mode_battery;
 +			minspeed = minspeed_battery;
 +			maxspeed = maxspeed_battery;
  			break;
  		case SRC_UNKNOWN:
  			mode = mode_none;
 +			minspeed = 0;
 +			maxspeed = 0;
  			break;
  		default:
  			errx(1, "invalid AC line status %d", acline_status);
 @@ -595,7 +657,7 @@
  			/* Keep a sum of all power actually used. */
  			if (mwatts[i] != -1)
  				mjoules_used +=
 -				    (mwatts[i] * (poll_ival / 1000)) / 1000;
 +					(mwatts[i] * (poll_ival / 1000)) / 1000;
  		}
  
  		/* Always switch to the lowest frequency in min mode. */
 @@ -604,12 +666,12 @@
  			if (curfreq != freq) {
  				if (vflag) {
  					printf("now operating on %s power; "
 -					    "changing frequency to %d MHz\n",
 -					    modes[acline_status], freq);
 +						"changing frequency to %d MHz\n",
 +						modes[acline_status], freq);
  				}
  				if (set_freq(freq) != 0) {
  					warn("error setting CPU freq %d",
 -					    freq);
 +						freq);
  					continue;
  				}
  			}
 @@ -622,12 +684,12 @@
  			if (curfreq != freq) {
  				if (vflag) {
  					printf("now operating on %s power; "
 -					    "changing frequency to %d MHz\n",
 -					    modes[acline_status], freq);
 +						"changing frequency to %d MHz\n",
 +						modes[acline_status], freq);
  				}
  				if (set_freq(freq) != 0) {
  					warn("error setting CPU freq %d",
 -				    	    freq);
 +							freq);
  					continue;
  				}
  			}
 @@ -647,16 +709,26 @@
  					freq *= 2;
  				else
  					freq = freq * load / cpu_running_mark;
 +				
  				if (freq > freqs[0])
  					freq = freqs[0];
  			} else if (load < cpu_idle_mark &&
 -			    curfreq * load < freqs[get_freq_id(
 -			    freq * 7 / 8, freqs, numfreqs)] * 
 -			    cpu_running_mark) {
 +				curfreq * load < freqs[get_freq_id(
 +				freq * 7 / 8, freqs, numfreqs)] * 
 +				cpu_running_mark) {
  				freq = freq * 7 / 8;
  				if (freq < freqs[numfreqs - 1])
  					freq = freqs[numfreqs - 1];
  			}
 +			if(maxspeed > 0 && freq > maxspeed) {
 +				if(vflag)
 +					printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
 +				freq = maxspeed;
 +			} else if(minspeed > 0 && freq < minspeed) {
 +				if(vflag)
 +					printf("Upgrading calculated freq (%d Mhz) to %d Mhz\n", freq, minspeed);
 +				freq = minspeed;
 +			}
  		} else { /* MODE_HIADAPTIVE */
  			if (load > cpu_running_mark / 2) {
  				if (load > 95 || load > cpu_running_mark)
 @@ -666,28 +738,37 @@
  				if (freq > freqs[0] * 2)
  					freq = freqs[0] * 2;
  			} else if (load < cpu_idle_mark / 2 &&
 -			    curfreq * load < freqs[get_freq_id(
 -			    freq * 31 / 32, freqs, numfreqs)] * 
 -			    cpu_running_mark / 2) {
 +				curfreq * load < freqs[get_freq_id(
 +				freq * 31 / 32, freqs, numfreqs)] * 
 +				cpu_running_mark / 2) {
  				freq = freq * 31 / 32;
  				if (freq < freqs[numfreqs - 1])
  					freq = freqs[numfreqs - 1];
  			}
 +			if(maxspeed > 0 && freq > maxspeed) {
 +				if(vflag)
 +					printf("Limiting calculated freq (%d Mhz) to %d Mhz\n", freq, maxspeed);
 +				freq = maxspeed;
 +			} else if(minspeed > 0 && freq < minspeed) {
 +				if(vflag)
 +					printf("Upgrading calculated freq (%d Mhz) to %d Mhz\n", freq, minspeed);
 +				freq = minspeed;
 +			}
  		}
  		if (vflag) {
 -		    printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",
 +			printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",
  			load, curfreq, i, freq);
  		}
  		j = get_freq_id(freq, freqs, numfreqs);
  		if (i != j) {
  			if (vflag) {
  				printf("changing clock"
 -				    " speed from %d MHz to %d MHz\n",
 -				    freqs[i], freqs[j]);
 +					" speed from %d MHz to %d MHz\n",
 +					freqs[i], freqs[j]);
  			}
  			if (set_freq(freqs[j]))
  				warn("error setting CPU frequency %d",
 -				    freqs[j]);
 +					freqs[j]);
  		}
  	}
  	if (set_freq(initfreq))
 ------=_20090720151749_38089--
 
 


More information about the freebsd-bugs mailing list