summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/apmd/apmd.817
-rw-r--r--usr.sbin/apmd/apmd.c226
2 files changed, 38 insertions, 205 deletions
diff --git a/usr.sbin/apmd/apmd.8 b/usr.sbin/apmd/apmd.8
index e283ff0c482..bf795e0797a 100644
--- a/usr.sbin/apmd/apmd.8
+++ b/usr.sbin/apmd/apmd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: apmd.8,v 1.44 2014/07/24 01:04:58 tedu Exp $
+.\" $OpenBSD: apmd.8,v 1.45 2014/10/17 01:55:00 tedu Exp $
.\"
.\" Copyright (c) 1995 John T. Kohl
.\" All rights reserved.
@@ -26,7 +26,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: July 24 2014 $
+.Dd $Mdocdate: October 17 2014 $
.Dt APMD 8
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Nd Advanced Power Management daemon
.Sh SYNOPSIS
.Nm apmd
-.Op Fl AaCdHLs
+.Op Fl AadHLs
.Op Fl f Ar devname
.Op Fl S Ar sockname
.Op Fl t Ar seconds
@@ -69,21 +69,10 @@ The options are as follows:
Start
.Nm
in automatic performance adjustment mode.
-Optimize for performance, but lower
-.Va hw.setperf
-when running on battery power or when AC is connected but the battery charge
-level is low.
.It Fl a
BIOS-initiated suspend or standby requests are
ignored if the system is connected to line current and not running from
batteries (user requests are still honored).
-.It Fl C
-Start
-.Nm
-in cool running performance adjustment mode.
-Optimize for low power use by keeping
-.Va hw.setperf
-low, except when CPU idle time drops and more performance is required.
.It Fl d
.Nm
enters debug mode, logging to facility
diff --git a/usr.sbin/apmd/apmd.c b/usr.sbin/apmd/apmd.c
index 6954f44af63..6aaebab58fc 100644
--- a/usr.sbin/apmd/apmd.c
+++ b/usr.sbin/apmd/apmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apmd.c,v 1.69 2014/09/26 10:39:28 dcoppa Exp $ */
+/* $OpenBSD: apmd.c,v 1.70 2014/10/17 01:55:00 tedu Exp $ */
/*
* Copyright (c) 1995, 1996 John T. Kohl
@@ -79,7 +79,7 @@ void perf_status(struct apm_power_info *pinfo, int ncpu);
void suspend(int ctl_fd);
void stand_by(int ctl_fd);
void hibernate(int ctl_fd);
-void setperf(int new_perf);
+void setperfpolicy(char *policy);
void sigexit(int signo);
void do_etc_file(const char *file);
void sockunlink(void);
@@ -195,159 +195,6 @@ power_status(int fd, int force, struct apm_power_info *pinfo)
return acon;
}
-/* multi- and uni-processor case */
-int
-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_avg_idle;
- size_t cp_time_sz = CPUSTATES * sizeof(int64_t);
-
- if (!cp_time_old)
- if ((cp_time_old = calloc(sizeof(int64_t *), ncpu)) == NULL)
- return -1;
-
- if (!cp_time)
- if ((cp_time = calloc(sizeof(int64_t *), ncpu)) == NULL)
- return -1;
-
- 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};
-
- if (!cp_time_old[cpu])
- if ((cp_time_old[cpu] =
- calloc(sizeof(int64_t), CPUSTATES)) == NULL)
- return -1;
-
- if (!cp_time[cpu])
- if ((cp_time[cpu] =
- calloc(sizeof(int64_t), CPUSTATES)) == NULL)
- return -1;
-
- 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;
- for (i = 0; i < CPUSTATES; i++) {
- 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]);
- }
- sum += change;
- if (i == CP_IDLE)
- idle = change;
- }
- if (sum == 0)
- sum = 1;
-
- /* 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_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;
-}
-
-void
-perf_status(struct apm_power_info *pinfo, int ncpu)
-{
- int avg_idle;
- int hw_perf_mib[] = {CTL_HW, HW_SETPERF};
- int perf;
- int forcehi = 0;
- size_t perf_sz = sizeof(perf);
-
- if (ncpu > 1) {
- avg_idle = get_avg_idle_mp(ncpu);
- } else {
- avg_idle = get_avg_idle_up();
- }
-
- 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%, or if
- * the battery is absent
- */
- if ((pinfo->ac_state == APM_AC_ON && pinfo->battery_life > 15) ||
- pinfo->battery_state == APM_BATTERY_ABSENT)
- forcehi = 1;
- break;
- case PERF_COOL:
- 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 = PERFMAX;
- setperf(perf);
- } else if (avg_idle > PERFDECTHRES && perf > PERFMIN) {
- perf -= PERFDEC;
- if (perf < PERFMIN)
- perf = PERFMIN;
- setperf(perf);
- }
-}
-
char socketname[MAXPATHLEN];
void
@@ -435,24 +282,21 @@ handle_client(int sock_fd, int ctl_fd)
case SETPERF_LOW:
doperf = PERF_MANUAL;
reply.newstate = NORMAL;
- syslog(LOG_NOTICE, "setting hw.setperf to %d", PERFMIN);
- setperf(PERFMIN);
+ syslog(LOG_NOTICE, "setting hw.perfpolicy to manual");
+ setperfpolicy("low");
break;
case SETPERF_HIGH:
doperf = PERF_MANUAL;
reply.newstate = NORMAL;
- syslog(LOG_NOTICE, "setting hw.setperf to %d", PERFMAX);
- setperf(PERFMAX);
+ syslog(LOG_NOTICE, "setting hw.perfpolicy to high");
+ setperfpolicy("high");
break;
case SETPERF_AUTO:
- doperf = PERF_AUTO;
- reply.newstate = NORMAL;
- syslog(LOG_NOTICE, "setting hw.setperf automatically");
- break;
case SETPERF_COOL:
- doperf = PERF_COOL;
+ doperf = PERF_AUTO;
reply.newstate = NORMAL;
- syslog(LOG_NOTICE, "setting hw.setperf for cool running");
+ syslog(LOG_NOTICE, "setting hw.perfpolicy to auto");
+ setperfpolicy("auto");
break;
default:
reply.newstate = NORMAL;
@@ -545,26 +389,23 @@ main(int argc, char *argv[])
statonly = 1;
break;
case 'A':
- if (doperf != PERF_NONE)
- usage();
- doperf = PERF_AUTO;
- break;
case 'C':
if (doperf != PERF_NONE)
usage();
- doperf = PERF_COOL;
+ doperf = PERF_AUTO;
+ setperfpolicy("auto");
break;
case 'L':
if (doperf != PERF_NONE)
usage();
doperf = PERF_MANUAL;
- setperf(PERFMIN);
+ setperfpolicy("low");
break;
case 'H':
if (doperf != PERF_NONE)
usage();
doperf = PERF_MANUAL;
- setperf(PERFMAX);
+ setperfpolicy("high");
break;
case '?':
default:
@@ -629,24 +470,12 @@ main(int argc, char *argv[])
if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_sz, NULL, 0) < 0)
error("cannot read hw.ncpu", NULL);
- if (doperf == PERF_AUTO || doperf == PERF_COOL) {
- setperf(0);
- setperf(100);
- }
for (;;) {
int rv;
sts = ts;
- if (doperf == PERF_AUTO || doperf == PERF_COOL) {
- sts.tv_sec = 0;
- sts.tv_nsec = 200000000;
- perf_status(&pinfo, ncpu);
- apmtimeout += 1;
- } else {
- apmtimeout += sts.tv_sec;
- }
-
+ apmtimeout += 1;
if ((rv = kevent(kq, NULL, 0, ev, 1, &sts)) < 0)
break;
@@ -749,14 +578,29 @@ main(int argc, char *argv[])
}
void
-setperf(int new_perf)
+setperfpolicy(char *policy)
{
- int hw_perf_mib[] = {CTL_HW, HW_SETPERF};
- int perf;
- size_t perf_sz = sizeof(perf);
+ int hw_perfpol_mib[] = { CTL_HW, HW_PERFPOLICY };
+ char oldpolicy[32];
+ size_t oldsz = sizeof(oldpolicy);
+ int setlo = 0;
+
+ if (strcmp(policy, "low") == 0) {
+ policy = "manual";
+ setlo = 1;
+ }
+
+ if (sysctl(hw_perfpol_mib, 2, oldpolicy, &oldsz, policy, strlen(policy) + 1) < 0)
+ syslog(LOG_INFO, "cannot set hw.perfpolicy");
- if (sysctl(hw_perf_mib, 2, &perf, &perf_sz, &new_perf, perf_sz) < 0)
- syslog(LOG_INFO, "cannot set hw.setperf");
+ if (setlo == 1) {
+ int hw_perf_mib[] = {CTL_HW, HW_SETPERF};
+ int perf;
+ int new_perf = 0;
+ size_t perf_sz = sizeof(perf);
+ if (sysctl(hw_perf_mib, 2, &perf, &perf_sz, &new_perf, perf_sz) < 0)
+ syslog(LOG_INFO, "cannot set hw.setperf");
+ }
}
void