From owner-freebsd-bugs@FreeBSD.ORG Mon Jul 20 13:17:51 2009 Return-Path: Delivered-To: freebsd-bugs@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E8115106566C; Mon, 20 Jul 2009 13:17:51 +0000 (UTC) (envelope-from cavac@magicbooks.org) Received: from magic3.magicbooks.org (cl-190.dus-01.de.sixxs.net [IPv6:2a01:198:200:bd::2]) by mx1.freebsd.org (Postfix) with ESMTP id 15F3E8FC13; Mon, 20 Jul 2009 13:17:50 +0000 (UTC) (envelope-from cavac@magicbooks.org) Received: from mail.magicbooks.org (localhost [127.0.0.1]) by magic3.magicbooks.org (8.14.3/8.14.3) with ESMTP id n6KDHlOb081647; Mon, 20 Jul 2009 15:17:49 +0200 (CEST) (envelope-from cavac@magicbooks.org) Received: from 213.150.228.38 (SquirrelMail authenticated user cavac) by mail.magicbooks.org with HTTP; Mon, 20 Jul 2009 15:17:49 +0200 (CEST) Message-ID: <30258.213.150.228.38.1248095869.squirrel@mail.magicbooks.org> In-Reply-To: <200907051610.n65GA0D0073090@freefall.freebsd.org> References: Your message of Sun, 5 Jul 2009 16:06:19 GMT <200907051606.n65G6JD4043183@www.freebsd.org> <200907051610.n65GA0D0073090@freefall.freebsd.org> Date: Mon, 20 Jul 2009 15:17:49 +0200 (CEST) From: "Rene Schickbauer" To: bug-followup@FreeBSD.org, freebsd-bugs@FreeBSD.org User-Agent: SquirrelMail/1.4.6 MIME-Version: 1.0 Content-Type: multipart/mixed;boundary="----=_20090720151749_38089" X-Priority: 3 (Normal) Importance: Normal Cc: Subject: Re: misc/136354: powerd Support for maxspeed in adaptive modes X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Jul 2009 13:17:52 -0000 ------=_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", ¬ify) == 1) + (ptr = strstr(buf, "system=ACPI")) != NULL && + (ptr = strstr(ptr, "subsystem=ACAD")) != NULL && + (ptr = strstr(ptr, "notify=")) != NULL && + sscanf(ptr, "notify=%x", ¬ify) == 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--