summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2009-02-26 00:29:40 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2009-02-26 00:29:40 +0000
commitfd52a3376654d450037c34c8af858ce75ab7ad9d (patch)
treedbd5c5111aae82dd0db5a3cd22a6946d5ba4a1c8
parentaa1d4eafd7065fbaf07c64c3ccd116f157bf7541 (diff)
revert 1.50 and 1.51. kettenis discovered they don't let his sparcle go slow enough
-rw-r--r--usr.sbin/apmd/apmd.c138
1 files changed, 95 insertions, 43 deletions
diff --git a/usr.sbin/apmd/apmd.c b/usr.sbin/apmd/apmd.c
index dd4608704f6..11a3b67b8ca 100644
--- a/usr.sbin/apmd/apmd.c
+++ b/usr.sbin/apmd/apmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apmd.c,v 1.51 2009/02/04 05:22:58 tedu Exp $ */
+/* $OpenBSD: apmd.c,v 1.52 2009/02/26 00:29:39 tedu Exp $ */
/*
* Copyright (c) 1995, 1996 John T. Kohl
@@ -61,15 +61,12 @@ const char sockfile[] = _PATH_APM_SOCKET;
int debug = 0;
int doperf = PERF_NONE;
-#define PERFINC 15
-#define PERFDEC 15
+#define PERFINC 50
+#define PERFDEC 20
#define PERFMIN 0
#define PERFMAX 100
#define PERFINCTHRES 10
#define PERFDECTHRES 30
-#define PERFTIMEOUTERR 999999999
-#define PERFTIMEOUTFAST 10000000
-#define PERFTIMEOUTSLOW 25000000
extern char *__progname;
@@ -77,8 +74,9 @@ void usage(void);
int power_status(int fd, int force, struct apm_power_info *pinfo);
int bind_socket(const char *sn);
enum apm_state handle_client(int sock_fd, int ctl_fd);
-int get_min_idle_mp(int ncpu);
-useconds_t perf_status(struct apm_power_info *pinfo, int ncpu);
+int get_avg_idle_mp(int ncpu);
+int get_avg_idle_up(void);
+void perf_status(struct apm_power_info *pinfo, int ncpu);
void suspend(int ctl_fd);
void stand_by(int ctl_fd);
void setperf(int new_perf);
@@ -197,12 +195,13 @@ power_status(int fd, int force, struct apm_power_info *pinfo)
/* multi- and uni-processor case */
int
-get_min_idle_mp(int ncpu)
+get_avg_idle_mp(int ncpu)
{
static int64_t **cp_time_old;
static int64_t **cp_time;
+ static int *avg_idle;
int64_t change, sum, idle;
- int i, cpu, min_idle;
+ int i, cpu, min_avg_idle;
size_t cp_time_sz = CPUSTATES * sizeof(int64_t);
if (!cp_time_old)
@@ -213,7 +212,11 @@ get_min_idle_mp(int ncpu)
if ((cp_time = calloc(sizeof(int64_t *), ncpu)) == NULL)
return -1;
- min_idle = 100;
+ if (!avg_idle)
+ if ((avg_idle = calloc(sizeof(int), ncpu)) == NULL)
+ return -1;
+
+ min_avg_idle = 0;
for (cpu = 0; cpu < ncpu; cpu++) {
int cp_time_mib[] = {CTL_KERN, KERN_CPTIME2, cpu};
@@ -227,14 +230,14 @@ get_min_idle_mp(int ncpu)
calloc(sizeof(int64_t), CPUSTATES)) == NULL)
return -1;
- if (sysctl(cp_time_mib, 3, cp_time[cpu], &cp_time_sz, NULL, 0))
+ if (sysctl(cp_time_mib, 3, cp_time[cpu], &cp_time_sz, NULL, 0)
+ < 0)
syslog(LOG_INFO, "cannot read kern.cp_time2");
sum = 0;
- idle = 100;
for (i = 0; i < CPUSTATES; i++) {
- change = cp_time[cpu][i] - cp_time_old[cpu][i];
- if (change < 0) {
+ if ((change = cp_time[cpu][i] - cp_time_old[cpu][i])
+ < 0) {
/* counter wrapped */
change = ((uint64_t)cp_time[cpu][i] -
(uint64_t)cp_time_old[cpu][i]);
@@ -246,52 +249,101 @@ get_min_idle_mp(int ncpu)
if (sum == 0)
sum = 1;
- if ((100 * idle) / sum < min_idle)
- min_idle = (100 * idle) / sum;
+ /* smooth data */
+ avg_idle[cpu] = (avg_idle[cpu] + (100 * idle) / sum) / 2;
+
+ if (cpu == 0)
+ min_avg_idle = avg_idle[cpu];
+
+ if (avg_idle[cpu] < min_avg_idle)
+ min_avg_idle = avg_idle[cpu];
memcpy(cp_time_old[cpu], cp_time[cpu], cp_time_sz);
}
- return min_idle;
+ return min_avg_idle;
+}
+
+int
+get_avg_idle_up(void)
+{
+ static long cp_time_old[CPUSTATES];
+ static int avg_idle;
+ long change, cp_time[CPUSTATES];
+ int cp_time_mib[] = {CTL_KERN, KERN_CPTIME};
+ size_t cp_time_sz = sizeof(cp_time);
+ int i, idle, sum = 0;
+
+ if (sysctl(cp_time_mib, 2, &cp_time, &cp_time_sz, NULL, 0) < 0)
+ syslog(LOG_INFO, "cannot read kern.cp_time");
+
+ for (i = 0; i < CPUSTATES; i++) {
+ if ((change = cp_time[i] - cp_time_old[i]) < 0) {
+ /* counter wrapped */
+ change = ((unsigned long)cp_time[i] -
+ (unsigned long)cp_time_old[i]);
+ }
+ sum += change;
+ if (i == CP_IDLE)
+ idle = change;
+ }
+ if (sum == 0)
+ sum = 1;
+
+ /* smooth data */
+ avg_idle = (avg_idle + (100 * idle) / sum) / 2;
+
+ memcpy(cp_time_old, cp_time, sizeof(cp_time_old));
+
+ return avg_idle;
}
-useconds_t
+void
perf_status(struct apm_power_info *pinfo, int ncpu)
{
- int avg_idle, min_idle;
+ int avg_idle;
int hw_perf_mib[] = {CTL_HW, HW_SETPERF};
int perf;
int forcehi = 0;
size_t perf_sz = sizeof(perf);
- if (avg_idle == -1)
- return PERFTIMEOUTERR;
+ if (ncpu > 1) {
+ avg_idle = get_avg_idle_mp(ncpu);
+ } else {
+ avg_idle = get_avg_idle_up();
+ }
- if (sysctl(hw_perf_mib, 2, &perf, &perf_sz, NULL, 0) < 0)
- syslog(LOG_INFO, "cannot read hw.setperf");
+ if (avg_idle == -1)
+ return;
switch (doperf) {
case PERF_AUTO:
+ /*
+ * force setperf towards the max if we are connected to AC
+ * power and have a battery life greater than 15%
+ */
if (pinfo->ac_state == APM_AC_ON && pinfo->battery_life > 15)
- forcehi = 1;
+ forcehi = 1;
+ break;
case PERF_COOL:
- min_idle = get_min_idle_mp(ncpu);
- if (forcehi || (min_idle < PERFINCTHRES && perf < PERFMAX)) {
- perf += PERFINC;
- if (perf > PERFMAX)
- perf = PERFMAX;
- setperf(perf);
- return PERFTIMEOUTFAST;
- } else if (min_idle > PERFDECTHRES && perf > PERFMIN) {
- perf -= PERFDEC;
- if (perf < PERFMIN)
- perf = PERFMIN;
- setperf(perf);
- return PERFTIMEOUTSLOW;
- } else
- return PERFTIMEOUTSLOW;
+ forcehi = 0;
+ break;
+ }
+
+ if (sysctl(hw_perf_mib, 2, &perf, &perf_sz, NULL, 0) < 0)
+ syslog(LOG_INFO, "cannot read hw.setperf");
+
+ if (forcehi || (avg_idle < PERFINCTHRES && perf < PERFMAX)) {
+ perf += PERFINC;
+ if (perf > PERFMAX)
+ perf = PERFMAX;
+ setperf(perf);
+ } else if (avg_idle > PERFDECTHRES && perf > PERFMIN) {
+ perf -= PERFDEC;
+ if (perf < PERFMIN)
+ perf = PERFMIN;
+ setperf(perf);
}
- return PERFTIMEOUTSLOW;
}
char socketname[MAXPATHLEN];
@@ -593,8 +645,8 @@ main(int argc, char *argv[])
sts = ts;
if (doperf == PERF_AUTO || doperf == PERF_COOL) {
- sts.tv_sec = 0;
- sts.tv_nsec = perf_status(&pinfo, ncpu);
+ sts.tv_sec = 1;
+ perf_status(&pinfo, ncpu);
}
apmtimeout += sts.tv_sec;