diff --git a/usr.sbin/powerd/powerd.8 b/usr.sbin/powerd/powerd.8 --- a/usr.sbin/powerd/powerd.8 +++ b/usr.sbin/powerd/powerd.8 @@ -43,6 +43,8 @@ .Op Fl p Ar ival .Op Fl r Ar percent .Op Fl s Ar source +.Op Fl S +.Op Fl t .Op Fl v .Sh DESCRIPTION The @@ -129,6 +131,17 @@ and .Cm apm (i386 only). +.It Fl S +Scales load to 100% no matter how many cores are present in the system. +Without this flag, powerd will keep the clock speed elevated on +systems with a high core count if a small number of cores are busy. +Note that this option will keep the CPU clock speed low on systems +with serial workloads. +.It Fl t +Forbid turbo. +Some CPUs enter "turbo" mode and allow higher clocking when a freqency +whose least significant digit is one are selected. +This flag prevents selection of "turbo" frequencies. .It Fl v Verbose mode. Messages about power changes will be printed to stdout and diff --git a/usr.sbin/powerd/powerd.c b/usr.sbin/powerd/powerd.c --- a/usr.sbin/powerd/powerd.c +++ b/usr.sbin/powerd/powerd.c @@ -86,9 +86,9 @@ #define DEVDPIPE "/var/run/devd.pipe" #define DEVCTL_MAXBUF 1024 -static int read_usage_times(int *load, int nonice); +static int read_usage_times(int *load, int nonice, int scale); static int read_freqs(int *numfreqs, int **freqs, int **power, - int minfreq, int maxfreq); + int minfreq, int maxfreq, int turbo); static int set_freq(int freq); static void acline_init(void); static void acline_read(void); @@ -140,7 +140,7 @@ * nice time will be treated as if idle. */ static int -read_usage_times(int *load, int nonice) +read_usage_times(int *load, int nonice, int scale) { static long *cp_times = NULL, *cp_times_old = NULL; static int ncpus = 0; @@ -184,6 +184,8 @@ cp_times_old[cpu * CPUSTATES + CP_NICE]; *load += 100 - excl * 100 / total; } + if (scale) + *load = *load / ncpus; } memcpy(cp_times_old, cp_times, cp_times_len); @@ -192,7 +194,8 @@ } static int -read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq) +read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, + int maxfreq, int turbo) { char *freqstr, *p, *q; int i, j; @@ -231,7 +234,10 @@ free(*power); return (-1); } - if (((*freqs)[j] >= minfreq || minfreq == -1) && + /* Turbo freq is 1st freq, and 1Mhz hihger than 2nd */ + if (!turbo && j == 1 && (*freqs)[0] == (*freqs)[1] + 1) + (*freqs)[0] = (*freqs)[1]; + else if (((*freqs)[j] >= minfreq || minfreq == -1) && ((*freqs)[j] <= maxfreq || maxfreq == -1)) j++; p = q + 1; @@ -479,7 +485,7 @@ { 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"); +"usage: powerd [-v] [-S] [-t] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-N] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n"); exit(1); } @@ -496,7 +502,7 @@ int ch, mode, mode_ac, mode_battery, mode_none, idle, to; uint64_t mjoules_used; size_t len; - int nonice; + int nonice, scale, turbo; /* Default mode for all AC states is adaptive. */ mode_ac = mode_none = MODE_HIADAPTIVE; @@ -507,12 +513,14 @@ mjoules_used = 0; vflag = 0; nonice = 0; + turbo = 1; + scale = 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) + while ((ch = getopt(argc, argv, "a:b:i:m:M:Nn:p:P:r:s:Stv")) != -1) switch (ch) { case 'a': parse_mode(optarg, &mode_ac, ch); @@ -571,6 +579,12 @@ usage(); } break; + case 'S': + scale = 1; + break; + case 't': + turbo = 0; + break; case 'v': vflag = 1; break; @@ -595,9 +609,9 @@ err(1, "lookup freq_levels"); /* Check if we can read the load and supported freqs. */ - if (read_usage_times(NULL, nonice)) + if (read_usage_times(NULL, nonice, scale)) err(1, "read_usage_times"); - if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq)) + if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq, turbo)) err(1, "error reading supported CPU frequencies"); if (numfreqs == 0) errx(1, "no CPU frequencies in user-specified range"); @@ -777,7 +791,7 @@ } /* Adaptive mode; get the current CPU usage times. */ - if (read_usage_times(&load, nonice)) { + if (read_usage_times(&load, nonice, scale)) { if (vflag) warn("read_usage_times() failed"); continue;