bin/125141: change request of /usr/sbin/powerd to adapt SMP
environment.
Yoshisato YANAGISAWA
osho at pcc-software.org
Tue Jul 1 10:50:04 UTC 2008
>Number: 125141
>Category: bin
>Synopsis: change request of /usr/sbin/powerd to adapt SMP environment.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Jul 01 10:50:03 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: Yoshisato YANAGISAWA
>Release: FreeBSD 7.0-RELEASE amd64
>Organization:
>Environment:
System: FreeBSD ai.pcc-software.org 7.0-RELEASE FreeBSD 7.0-RELEASE #3: Wed May 21 22:36:46 JST 2008 osho at ai.pcc-software.org:/usr/obj/usr/src/sys/AI amd64
>Description:
Since an idle time got by "sysctl kern.cp_time" is the average
idle time of all the CPUs, powerd will not increase frequency
when one of the CPUs is busy and the others are not.
I guess many people will recognize this problem if they uses
the system that has more than 4 CPUs because the default
value of the -r option is 65.
>How-To-Repeat:
Just run powerd on the system which has more than 4 CPUs,
and make one of the CPUs busy while the others are idle.
>Fix:
Consider the number of CPUs. I made a following patch to recognize
the number of CPUs.
Another approach to solve this problem is using idle time of
the process [idle:cpu0], [idle:cpu1], [idle:cpu2], and [idle:cpu3]
instead of sysctl kern.cp_time. However, since it requires drastic
change of code, I avoided it.
--- powerd.c.bak 2007-06-14 04:05:11.000000000 +0900
+++ powerd.c 2008-07-01 19:04:41.000000000 +0900
@@ -190,6 +190,16 @@
}
static int
+read_ncpu(int *ncpu)
+{
+ size_t len = sizeof(*ncpu);
+ if (sysctlbyname("hw.ncpu", ncpu, &len, NULL, 0))
+ return (-1);
+
+ return (0);
+}
+
+static int
set_freq(int freq)
{
@@ -366,7 +376,7 @@
{
struct timeval timeout;
fd_set fdset;
- int nfds;
+ int nfds, ncpu;
struct pidfh *pfh = NULL;
const char *pidfile = NULL;
long idle, total;
@@ -453,6 +463,9 @@
if (read_freqs(&numfreqs, &freqs, &mwatts))
err(1, "error reading supported CPU frequencies");
+ if (read_ncpu(&ncpu))
+ err(1, "error reading # of cpus");
+
/* Run in the background unless in verbose mode. */
if (!vflag) {
pid_t otherpid;
@@ -592,7 +605,8 @@
if (freqs[i] == curfreq)
break;
}
- if (idle < (total * cpu_running_mark) / 100 &&
+ if (idle < ((total - total / ncpu) +
+ (total * cpu_running_mark) / (100 * ncpu)) &&
curfreq < freqs[0]) {
i -= 2;
if (i < 0)
@@ -605,7 +619,8 @@
if (set_freq(freqs[i]))
warn("error setting CPU frequency %d",
freqs[i]);
- } else if (idle > (total * cpu_idle_mark) / 100 &&
+ } else if (idle > ((total - total / ncpu) +
+ (total * cpu_idle_mark) / (100 * ncpu)) &&
curfreq > freqs[numfreqs - 1]) {
i++;
if (vflag) {
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list