freebsd-dev/usr.sbin/powerd/powerd.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

846 lines
20 KiB
C
Raw Normal View History

/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004 Colin Percival
* Copyright (c) 2005 Nate Lawson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#ifdef __i386__
#define USE_APM
#endif
#ifdef USE_APM
#include <machine/apm_bios.h>
#endif
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
#define DEFAULT_ACTIVE_PERCENT 75
#define DEFAULT_IDLE_PERCENT 50
#define DEFAULT_POLL_INTERVAL 250 /* Poll interval in milliseconds */
typedef enum {
MODE_MIN,
MODE_ADAPTIVE,
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
MODE_HIADAPTIVE,
MODE_MAX,
} modes_t;
typedef enum {
SRC_AC,
SRC_BATTERY,
SRC_UNKNOWN,
} power_src_t;
static const char *modes[] = {
"AC",
"battery",
"unknown"
};
#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, int nonice);
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);
static int devd_init(void);
static void devd_close(void);
static void handle_sigs(int sig);
static void parse_mode(char *arg, int *mode, int ch);
static void usage(void);
/* Sysctl data structures. */
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
static int cp_times_mib[2];
static int freq_mib[4];
static int levels_mib[4];
static int acline_mib[4];
static size_t acline_mib_len;
/* Configuration */
static int cpu_running_mark;
static int cpu_idle_mark;
static int poll_ival;
static int vflag;
static volatile sig_atomic_t exit_requested;
static power_src_t acline_status;
typedef enum {
ac_none,
ac_sysctl,
ac_acpi_devd,
#ifdef USE_APM
ac_apm,
#endif
} acline_mode_t;
static acline_mode_t acline_mode;
static acline_mode_t acline_mode_user = ac_none;
#ifdef USE_APM
static int apm_fd = -1;
#endif
static int devd_pipe = -1;
#define DEVD_RETRY_INTERVAL 60 /* seconds */
static struct timeval tried_devd;
/*
* This function returns summary load of all CPUs. It was made so
* intentionally to not reduce performance in scenarios when several
* threads are processing requests as a pipeline -- running one at
* a time on different CPUs and waiting for each other. If nonice
* is nonzero, only user+sys+intr time will be counted as load; any
* nice time will be treated as if idle.
*/
static int
read_usage_times(int *load, int nonice)
{
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
static long *cp_times = NULL, *cp_times_old = NULL;
static int ncpus = 0;
size_t cp_times_len;
int error, cpu, i, total, excl;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (cp_times == NULL) {
cp_times_len = 0;
error = sysctl(cp_times_mib, 2, NULL, &cp_times_len, NULL, 0);
if (error)
return (error);
if ((cp_times = malloc(cp_times_len)) == NULL)
return (errno);
if ((cp_times_old = malloc(cp_times_len)) == NULL) {
free(cp_times);
cp_times = NULL;
return (errno);
}
ncpus = cp_times_len / (sizeof(long) * CPUSTATES);
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
cp_times_len = sizeof(long) * CPUSTATES * ncpus;
error = sysctl(cp_times_mib, 2, cp_times, &cp_times_len, NULL, 0);
if (error)
return (error);
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (load) {
*load = 0;
for (cpu = 0; cpu < ncpus; cpu++) {
total = 0;
for (i = 0; i < CPUSTATES; i++) {
total += cp_times[cpu * CPUSTATES + i] -
cp_times_old[cpu * CPUSTATES + i];
}
if (total == 0)
continue;
excl = cp_times[cpu * CPUSTATES + CP_IDLE] -
cp_times_old[cpu * CPUSTATES + CP_IDLE];
if (nonice)
excl += cp_times[cpu * CPUSTATES + CP_NICE] -
cp_times_old[cpu * CPUSTATES + CP_NICE];
*load += 100 - excl * 100 / total;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
}
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
memcpy(cp_times_old, cp_times, cp_times_len);
return (0);
}
static int
read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq)
{
char *freqstr, *p, *q;
int i, j;
size_t len = 0;
if (sysctl(levels_mib, 4, NULL, &len, NULL, 0))
return (-1);
if ((freqstr = malloc(len)) == NULL)
return (-1);
if (sysctl(levels_mib, 4, freqstr, &len, NULL, 0)) {
free(freqstr);
return (-1);
}
*numfreqs = 1;
for (p = freqstr; *p != '\0'; p++)
if (*p == ' ')
(*numfreqs)++;
if ((*freqs = malloc(*numfreqs * sizeof(int))) == NULL) {
free(freqstr);
return (-1);
}
if ((*power = malloc(*numfreqs * sizeof(int))) == NULL) {
free(freqstr);
free(*freqs);
return (-1);
}
for (i = 0, j = 0, p = freqstr; i < *numfreqs; i++) {
q = strchr(p, ' ');
if (q != NULL)
*q = '\0';
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);
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
static int
get_freq(void)
{
size_t len;
int curfreq;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
len = sizeof(curfreq);
if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) != 0) {
if (vflag)
warn("error reading current CPU frequency");
curfreq = 0;
}
return (curfreq);
}
static int
set_freq(int freq)
{
if (sysctl(freq_mib, 4, NULL, NULL, &freq, sizeof(freq))) {
if (errno != EPERM)
return (-1);
}
return (0);
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
static int
get_freq_id(int freq, int *freqs, int numfreqs)
{
int i = 1;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
while (i < numfreqs) {
if (freqs[i] < freq)
break;
i++;
}
return (i - 1);
}
/*
* Try to use ACPI to find the AC line status. If this fails, fall back
* to APM. If nothing succeeds, we'll just run in default mode.
*/
static void
acline_init(void)
{
int skip_source_check;
acline_mib_len = 4;
acline_status = SRC_UNKNOWN;
skip_source_check = (acline_mode_user == ac_none ||
acline_mode_user == ac_acpi_devd);
if ((skip_source_check || acline_mode_user == ac_sysctl) &&
sysctlnametomib(ACPIAC, acline_mib, &acline_mib_len) == 0) {
acline_mode = ac_sysctl;
if (vflag)
warnx("using sysctl for AC line status");
#ifdef __powerpc__
} else if ((skip_source_check || acline_mode_user == ac_sysctl) &&
sysctlnametomib(PMUAC, acline_mib, &acline_mib_len) == 0) {
acline_mode = ac_sysctl;
if (vflag)
warnx("using sysctl for AC line status");
#endif
#ifdef USE_APM
} else if ((skip_source_check || acline_mode_user == ac_apm) &&
(apm_fd = open(APMDEV, O_RDONLY)) >= 0) {
if (vflag)
warnx("using APM for AC line status");
acline_mode = ac_apm;
#endif
} else {
warnx("unable to determine AC line status");
acline_mode = ac_none;
}
}
static void
acline_read(void)
{
if (acline_mode == ac_acpi_devd) {
char buf[DEVCTL_MAXBUF], *ptr;
ssize_t rlen;
int notify;
rlen = read(devd_pipe, buf, sizeof(buf));
if (rlen == 0 || (rlen < 0 && errno != EWOULDBLOCK)) {
if (vflag)
warnx("lost devd connection, switching to sysctl");
devd_close();
acline_mode = ac_sysctl;
/* 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)
acline_status = (notify ? SRC_AC : SRC_BATTERY);
}
if (acline_mode == ac_sysctl) {
int acline;
size_t len;
len = sizeof(acline);
if (sysctl(acline_mib, acline_mib_len, &acline, &len,
NULL, 0) == 0)
acline_status = (acline ? SRC_AC : SRC_BATTERY);
else
acline_status = SRC_UNKNOWN;
}
#ifdef USE_APM
if (acline_mode == ac_apm) {
struct apm_info info;
if (ioctl(apm_fd, APMIO_GETINFO, &info) == 0) {
acline_status = (info.ai_acline ? SRC_AC : SRC_BATTERY);
} else {
close(apm_fd);
apm_fd = -1;
acline_mode = ac_none;
acline_status = SRC_UNKNOWN;
}
}
#endif
/* try to (re)connect to devd */
#ifdef USE_APM
if ((acline_mode == ac_sysctl &&
(acline_mode_user == ac_none ||
acline_mode_user == ac_acpi_devd)) ||
(acline_mode == ac_apm &&
acline_mode_user == ac_acpi_devd)) {
#else
if (acline_mode == ac_sysctl &&
(acline_mode_user == ac_none ||
acline_mode_user == ac_acpi_devd)) {
#endif
struct timeval now;
gettimeofday(&now, NULL);
if (now.tv_sec > tried_devd.tv_sec + DEVD_RETRY_INTERVAL) {
if (devd_init() >= 0) {
if (vflag)
warnx("using devd for AC line status");
acline_mode = ac_acpi_devd;
}
tried_devd = now;
}
}
}
static int
devd_init(void)
{
struct sockaddr_un devd_addr;
bzero(&devd_addr, sizeof(devd_addr));
if ((devd_pipe = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0) {
if (vflag)
warn("%s(): socket()", __func__);
return (-1);
}
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) {
if (vflag)
warn("%s(): connect()", __func__);
close(devd_pipe);
devd_pipe = -1;
return (-1);
}
return (devd_pipe);
}
static void
devd_close(void)
{
close(devd_pipe);
devd_pipe = -1;
}
static void
parse_mode(char *arg, int *mode, int ch)
{
if (strcmp(arg, "minimum") == 0 || strcmp(arg, "min") == 0)
*mode = MODE_MIN;
else if (strcmp(arg, "maximum") == 0 || strcmp(arg, "max") == 0)
*mode = MODE_MAX;
else if (strcmp(arg, "adaptive") == 0 || strcmp(arg, "adp") == 0)
*mode = MODE_ADAPTIVE;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
else if (strcmp(arg, "hiadaptive") == 0 || strcmp(arg, "hadp") == 0)
*mode = MODE_HIADAPTIVE;
else
errx(1, "bad option: -%c %s", (char)ch, optarg);
}
static void
parse_acline_mode(char *arg, int ch)
{
if (strcmp(arg, "sysctl") == 0)
acline_mode_user = ac_sysctl;
else if (strcmp(arg, "devd") == 0)
acline_mode_user = ac_acpi_devd;
#ifdef USE_APM
else if (strcmp(arg, "apm") == 0)
acline_mode_user = ac_apm;
#endif
else
errx(1, "bad option: -%c %s", (char)ch, optarg);
}
static void
handle_sigs(int __unused sig)
{
exit_requested = 1;
}
static void
usage(void)
{
fprintf(stderr,
"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-N] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n");
exit(1);
}
int
main(int argc, char * argv[])
{
struct timeval timeout;
fd_set fdset;
int nfds;
struct pidfh *pfh = NULL;
const char *pidfile = NULL;
int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
int minfreq = -1, maxfreq = -1;
int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
uint64_t mjoules_used;
size_t len;
int nonice;
/* Default mode for all AC states is adaptive. */
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
mode_ac = mode_none = MODE_HIADAPTIVE;
mode_battery = MODE_ADAPTIVE;
cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
cpu_idle_mark = DEFAULT_IDLE_PERCENT;
poll_ival = DEFAULT_POLL_INTERVAL;
mjoules_used = 0;
vflag = 0;
nonice = 0;
/* User must be root to control frequencies. */
if (geteuid() != 0)
errx(1, "must be root to run");
while ((ch = getopt(argc, argv, "a:b:i:m:M:Nn:p:P:r:s:v")) != -1)
switch (ch) {
case 'a':
parse_mode(optarg, &mode_ac, ch);
break;
case 'b':
parse_mode(optarg, &mode_battery, ch);
break;
case 's':
parse_acline_mode(optarg, ch);
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);
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':
nonice = 1;
break;
case 'n':
parse_mode(optarg, &mode_none, ch);
break;
case 'p':
poll_ival = atoi(optarg);
if (poll_ival < 5) {
warnx("poll interval is in units of ms");
usage();
}
break;
case 'P':
pidfile = optarg;
break;
case 'r':
cpu_running_mark = atoi(optarg);
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (cpu_running_mark <= 0 || cpu_running_mark > 100) {
warnx("%d is not a valid percent",
cpu_running_mark);
usage();
}
break;
case 'v':
vflag = 1;
break;
default:
usage();
}
mode = mode_none;
/* Poll interval is in units of ms. */
poll_ival *= 1000;
/* Look up various sysctl MIBs. */
len = 2;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (sysctlnametomib("kern.cp_times", cp_times_mib, &len))
err(1, "lookup kern.cp_times");
len = 4;
if (sysctlnametomib("dev.cpu.0.freq", freq_mib, &len))
err(EX_UNAVAILABLE, "no cpufreq(4) support -- aborting");
len = 4;
if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len))
err(1, "lookup freq_levels");
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
/* Check if we can read the load and supported freqs. */
if (read_usage_times(NULL, nonice))
err(1, "read_usage_times");
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) {
pid_t otherpid;
pfh = pidfile_open(pidfile, 0600, &otherpid);
if (pfh == NULL) {
if (errno == EEXIST) {
errx(1, "powerd already running, pid: %d",
otherpid);
}
warn("cannot open pid file");
}
if (daemon(0, 0) != 0) {
warn("cannot enter daemon mode, exiting");
pidfile_remove(pfh);
exit(EXIT_FAILURE);
}
pidfile_write(pfh);
}
/* Decide whether to use ACPI or APM to read the AC line status. */
acline_init();
/*
* Exit cleanly on signals.
*/
signal(SIGINT, handle_sigs);
signal(SIGTERM, handle_sigs);
freq = initfreq = curfreq = get_freq();
i = get_freq_id(curfreq, freqs, numfreqs);
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
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);
if (devd_pipe >= 0) {
FD_SET(devd_pipe, &fdset);
nfds = devd_pipe + 1;
} else {
nfds = 0;
}
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. */
if (exit_requested) {
if (vflag && mjoules_used != 0)
printf("total joules used: %u.%03u\n",
(u_int)(mjoules_used / 1000),
(int)mjoules_used % 1000);
break;
}
/* Read the current AC status and record the mode. */
acline_read();
switch (acline_status) {
case SRC_AC:
mode = mode_ac;
break;
case SRC_BATTERY:
mode = mode_battery;
break;
case SRC_UNKNOWN:
mode = mode_none;
break;
default:
errx(1, "invalid AC line status %d", acline_status);
}
/* Read the current frequency. */
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. */
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (mwatts[i] != -1)
mjoules_used +=
(mwatts[i] * (poll_ival / 1000)) / 1000;
}
/* Always switch to the lowest frequency in min mode. */
if (mode == MODE_MIN) {
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
freq = freqs[numfreqs - 1];
if (curfreq != freq) {
if (vflag) {
printf("now operating on %s power; "
"changing frequency to %d MHz\n",
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
modes[acline_status], freq);
}
idle = 0;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (set_freq(freq) != 0) {
warn("error setting CPU freq %d",
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
freq);
continue;
}
}
continue;
}
/* Always switch to the highest frequency in max mode. */
if (mode == MODE_MAX) {
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
freq = freqs[0];
if (curfreq != freq) {
if (vflag) {
printf("now operating on %s power; "
"changing frequency to %d MHz\n",
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
modes[acline_status], freq);
}
idle = 0;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (set_freq(freq) != 0) {
warn("error setting CPU freq %d",
freq);
continue;
}
}
continue;
}
/* Adaptive mode; get the current CPU usage times. */
if (read_usage_times(&load, nonice)) {
if (vflag)
warn("read_usage_times() failed");
continue;
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (mode == MODE_ADAPTIVE) {
if (load > cpu_running_mark) {
if (load > 95 || load > cpu_running_mark * 2)
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)] *
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
cpu_running_mark) {
freq = freq * 7 / 8;
if (freq < freqs[numfreqs - 1])
freq = freqs[numfreqs - 1];
}
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
} else { /* MODE_HIADAPTIVE */
if (load > cpu_running_mark / 2) {
if (load > 95 || load > cpu_running_mark)
freq *= 4;
else
freq = freq * load * 2 / cpu_running_mark;
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)] *
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
cpu_running_mark / 2) {
freq = freq * 31 / 32;
if (freq < freqs[numfreqs - 1])
freq = freqs[numfreqs - 1];
}
}
if (vflag) {
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) {
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
printf("changing clock"
" speed from %d MHz to %d MHz\n",
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
freqs[i], freqs[j]);
}
idle = 0;
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
if (set_freq(freqs[j]))
warn("error setting CPU frequency %d",
Set of powerd enchancements: 1. Make it more SMP polite. Previous version uses average CPU load that often leads to load underestimation. It make powerd with default configuration unusable on systems with more then 2 CPUs. I propose to use summary load instead of average one. IMO this is the best we can do without specially tuned scheduler. Also as soon as measuring total load on SMP systems is more useful then total idle, I have switched to it. 2. Make powerd's operation independent from number and size of frequency levels. I have added internal frequency counter which translated into real frequencies only on a last stage and only as good as gone. Some systems may have only several power levels, while others - many of them, so adaptation time with previous approach was completely different. 3. As part of previous I have changed adaptive mode to rise frequency on demand up to 2 times and fall on 1/8 per time internal. 4. For desktop (AC-powered) systems I have added one more mode - "hiadaptive". It rises frequency twice faster, drops it 4 times slower, prefers twice lower CPU load and has additional delay before leaving the highest frequency after the period of maximum load. This mode was specially made to improve interactivity of the systems where operation capabilities are more significant then power consumption, but keeping maximum frequency all the time is not needed. 5. I have reduced default polling interval from 1/2 to 1/4 of second. It is not so important for algorithm math now, but gives better system interactivity. Discussed on: mobile@
2008-11-18 13:24:38 +00:00
freqs[j]);
}
}
if (set_freq(initfreq))
warn("error setting CPU frequency %d", initfreq);
free(freqs);
free(mwatts);
devd_close();
if (!vflag)
pidfile_remove(pfh);
exit(0);
}