> Date: Wed, 30 Jun 2010 14:32:26 -0400 (EDT)
> From: Ted Unangst <[email protected]>
>
> I like this one better. Slow down the poll interval just a little so it's
> not so hysterical, but also go straight to 100. If you need CPU, you need
> CPU. It still backs down slowly, but that's just to prevent getting
> caught in slow mode again. It also pays attention to per-core load, much
> better on smp machines. I'm running this now and will probably continue
> to do so for a while.
Before this goes in, I'd like to get a chance to test this on the
sparc64 laptop that I have at home, to check that the agorithm works
well on slower machines as well.
> Index: init_main.c
> ===================================================================
> RCS file: /home/tedu/cvs/src/sys/kern/init_main.c,v
> retrieving revision 1.168
> diff -u -r1.168 init_main.c
> --- init_main.c 29 Jun 2010 20:25:57 -0000 1.168
> +++ init_main.c 30 Jun 2010 18:23:22 -0000
> @@ -172,6 +172,72 @@
> EMUL_ENABLED | EMUL_NATIVE,
> };
>
> +struct timeout setperf_to;
> +
> +void auto_setperf(void *v);
> +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;
> +
> + extern int perflevel;
> +
> + if (!cpu_setperf)
> + return;
> + if (!idleticks)
> + if (!(idleticks = malloc(sizeof(*idleticks) * ncpus,
> + M_DEVBUF, M_NOWAIT | M_ZERO)))
> + return;
> + if (!totalticks)
> + if (!(totalticks = malloc(sizeof(*totalticks) * ncpus,
> + M_DEVBUF, M_NOWAIT | M_ZERO))) {
> + free(idleticks, M_DEVBUF);
> + 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 / 2)
> + speedup = 1;
> + alltotal += total;
> + allidle += idle;
> + idleticks[j] += idle;
> + totalticks[j] += total;
> +
> + j++;
> + }
> + if (allidle < alltotal * 3 / 4)
> + speedup = 1;
> +
> + if (speedup && perflevel != 100) {
> + perflevel = 100;
> + printf("going up %d\n", perflevel);
> + cpu_setperf(perflevel);
> + } else if (!speedup) {
> + perflevel -= 10;
> + if (perflevel < 0)
> + perflevel = 0;
> + else
> + printf("going down %d\n", perflevel);
> + cpu_setperf(perflevel);
> + }
> +
> + timeout_add_msec(&setperf_to, 200);
> +}
>
> /*
> * System startup; initialize the world, create process 0, mount root
> @@ -545,6 +611,9 @@
> */
> start_init_exec = 1;
> wakeup((void *)&start_init_exec);
> +
> + timeout_set(&setperf_to, auto_setperf, NULL);
> + timeout_add_msec(&setperf_to, 200);
>
> /*
> * proc0: nothing to do, back to sleep