diff options
-rw-r--r-- | sys/kern/init_main.c | 11 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 92 |
2 files changed, 93 insertions, 10 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index b2922581365..d00ab037998 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.218 2014/10/03 18:06:46 kettenis Exp $ */ +/* $OpenBSD: init_main.c,v 1.219 2014/10/11 16:28:06 tedu Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -116,6 +116,11 @@ struct sigacts sigacts0; struct process *initprocess; struct proc *reaperproc; +#ifndef SMALL_KERNEL +extern struct timeout setperf_to; +void auto_setperf(void *); +#endif + int cmask = CMASK; extern struct user *proc0paddr; @@ -543,6 +548,10 @@ main(void *framep) start_init_exec = 1; wakeup((void *)&start_init_exec); +#ifndef SMALL_KERNEL + timeout_set(&setperf_to, auto_setperf, NULL); +#endif + /* * proc0: nothing to do, back to sleep */ diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 433f4d05098..3aadefc153a 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.264 2014/09/15 19:08:21 miod Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.265 2014/10/11 16:28:06 tedu Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -129,6 +129,10 @@ void fill_kproc(struct process *, struct kinfo_proc *, struct proc *, int); int (*cpu_cpuspeed)(int *); void (*cpu_setperf)(int); int perflevel = 100; +#ifndef SMALL_KERNEL +struct timeout setperf_to; +void auto_setperf(void *); +#endif /* * Lock to avoid too many processes vslocking a large amount of memory @@ -254,6 +258,65 @@ int securelevel = -1; int securelevel; #endif +#ifndef SMALL_KERNEL +void +auto_setperf(void *v) +{ + static uint64_t *idleticks, *totalticks; + + int i, j; + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + + int speedup; + uint64_t idle, total, allidle, alltotal; + + if (!auto_perfctl) + return; + if (!idleticks) + if (!(idleticks = malloc(sizeof(*idleticks) * ncpusfound, + M_DEVBUF, M_NOWAIT | M_ZERO))) + return; + if (!totalticks) + if (!(totalticks = malloc(sizeof(*totalticks) * ncpusfound, + M_DEVBUF, M_NOWAIT | M_ZERO))) { + free(idleticks, M_DEVBUF, 0); + return; + } + alltotal = allidle = 0; + j = 0; + speedup = 0; + CPU_INFO_FOREACH(cii, ci) { + total = 0; + for (i = 0; i < CPUSTATES; i++) { + total += ci->ci_schedstate.spc_cp_time[i]; + } + total -= totalticks[j]; + idle = ci->ci_schedstate.spc_cp_time[CP_IDLE] - idleticks[j]; + if (idle < total / 3) + speedup = 1; + alltotal += total; + allidle += idle; + idleticks[j] += idle; + totalticks[j] += total; + + j++; + } + if (allidle < alltotal / 2) + speedup = 1; + + if (speedup && perflevel != 100) { + perflevel = 100; + cpu_setperf(perflevel); + } else if (!speedup && perflevel != 0) { + perflevel = 0; + cpu_setperf(perflevel); + } + + timeout_add_msec(&setperf_to, 100); +} +#endif /* !SMALL_KERNEL */ + /* * kernel related system variables. */ @@ -608,7 +671,7 @@ hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { extern char machine[], cpu_model[]; - int err, cpuspeed; + int err, cpuspeed, newperf; /* all sysctl names at this level except sensors are terminal */ if (name[0] != HW_SENSORS && namelen != 1) @@ -664,15 +727,26 @@ hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, case HW_SETPERF: if (!cpu_setperf) return (EOPNOTSUPP); - err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel); + newperf = perflevel; + err = sysctl_int(oldp, oldlenp, newp, newlen, &newperf); if (err) return err; - if (perflevel > 100) - perflevel = 100; - if (perflevel < 0) - perflevel = 0; - if (newp) - cpu_setperf(perflevel); +#ifndef SMALL_KERNEL + if (newp) { + if (newperf == -1) { + auto_perfctl = 1; + timeout_add_msec(&setperf_to, 200); + } else { + auto_perfctl = 0; + if (newperf > 100) + newperf = 100; + if (newperf < 0) + newperf = 0; + perflevel = newperf; + cpu_setperf(newperf); + } + } +#endif /* !SMALL_KERNEL */ return (0); case HW_VENDOR: if (hw_vendor) |