FreeBSD Bugzilla – Attachment 221997 Details for
Bug 246940
[wishlist/enhancement, patch incl.]: idle user tasks should be charged as "nice" or "idle" CPU time
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 12.1-REL powerd(8) to weight (scale) nice & user idle load
cp_time_ext.powerd.diff (text/plain), 14.07 KB, created by
Walter von Entferndt
on 2021-01-28 17:30:32 UTC
(
hide
)
Description:
Patch for 12.1-REL powerd(8) to weight (scale) nice & user idle load
Filename:
MIME Type:
Creator:
Walter von Entferndt
Created:
2021-01-28 17:30:32 UTC
Size:
14.07 KB
patch
obsolete
>--- usr.sbin/powerd/powerd.c >+++ usr.sbin/powerd/powerd.c >@@ -24,15 +24,15 @@ > * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, > * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING > * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > * POSSIBILITY OF SUCH DAMAGE. > */ > > #include <sys/cdefs.h> >-__FBSDID("$FreeBSD: releng/12.1/usr.sbin/powerd/powerd.c 342981 2019-01-13 02:19:01Z avos $"); >+__FBSDID("$FreeBSD: head/usr.sbin/powerd/powerd.c 358478 2020-02-29 22:31:23Z cperciva $"); > > #include <sys/param.h> > #include <sys/ioctl.h> > #include <sys/sysctl.h> > #include <sys/resource.h> > #include <sys/socket.h> > #include <sys/time.h> >@@ -82,28 +82,29 @@ > > #define ACPIAC "hw.acpi.acline" > #define PMUAC "dev.pmu.0.acline" > #define APMDEV "/dev/apm" > #define DEVDPIPE "/var/run/devd.pipe" > #define DEVCTL_MAXBUF 1024 > >-static int read_usage_times(int *load); >+static int read_usage_times(int *load, int nonice, int noidle); > static int read_freqs(int *numfreqs, int **freqs, int **power, > int minfreq, int maxfreq); > static int set_freq(int freq); > static void acline_init(void); > static void acline_read(void); > static int devd_init(void); > static void devd_close(void); > static void handle_sigs(int sig); > static void parse_mode(char *arg, int *mode, int ch); > static void usage(void); > > /* Sysctl data structures. */ > static int cp_times_mib[2]; >+static int cpx_times_mib[2]; > static int freq_mib[4]; > static int levels_mib[4]; > static int acline_mib[4]; > static size_t acline_mib_len; > > /* Configuration */ > static int cpu_running_mark; >@@ -131,23 +132,28 @@ > #define DEVD_RETRY_INTERVAL 60 /* seconds */ > static struct timeval tried_devd; > > /* > * This function returns summary load of all CPUs. It was made so > * intentionally to not reduce performance in scenarios when several > * threads are processing requests as a pipeline -- running one at >- * a time on different CPUs and waiting for each other. >+ * a time on different CPUs and waiting for each other. If nonice >+ * is 100, only user+sys+intr time will be counted as load; any >+ * nice time will be treated as if idle, likewise noidle. I.e. these >+ * nice and/or idle loads are weighted by nonice and noidle, resp. >+ * NOTE nonice and noidle are the "reverse" from the the command line. > */ > static int >-read_usage_times(int *load) >+read_usage_times(int *load, int nonice, int noidle) > { > static long *cp_times = NULL, *cp_times_old = NULL; >+ static long *cpx_times = NULL, *cpx_times_old = NULL; > static int ncpus = 0; >- size_t cp_times_len; >- int error, cpu, i, total; >+ size_t cp_times_len, cpx_times_len; >+ int error, cpu, i, total, excl; > > if (cp_times == NULL) { > cp_times_len = 0; > error = sysctl(cp_times_mib, 2, NULL, &cp_times_len, NULL, 0); > if (error) > return (error); > if ((cp_times = malloc(cp_times_len)) == NULL) >@@ -155,36 +161,71 @@ > if ((cp_times_old = malloc(cp_times_len)) == NULL) { > free(cp_times); > cp_times = NULL; > return (errno); > } > ncpus = cp_times_len / (sizeof(long) * CPUSTATES); > } >- > cp_times_len = sizeof(long) * CPUSTATES * ncpus; > error = sysctl(cp_times_mib, 2, cp_times, &cp_times_len, NULL, 0); > if (error) > return (error); > >+ if (noidle) { >+ if (cpx_times == NULL) { >+ cpx_times_len = 0; >+ error = sysctl(cpx_times_mib, 2, NULL, &cpx_times_len, NULL, 0); >+ if (error) >+ return (error); >+ if ((cpx_times = malloc(cpx_times_len)) == NULL) >+ return (errno); >+ if ((cpx_times_old = malloc(cpx_times_len)) == NULL) { >+ free(cpx_times); >+ cpx_times = NULL; >+ return (errno); >+ } >+ } >+ /* FIXME This could be as assert (...); */ >+ /* ncpus = cpx_times_len / (sizeof(long) * CPUSTATES_EXT); */ >+ cpx_times_len = sizeof(long) * CPUSTATES_EXT * ncpus; >+ error = sysctl(cpx_times_mib, 2, cpx_times, &cpx_times_len, NULL, 0); >+ if (error) >+ return (error); >+ } >+ > if (load) { > *load = 0; > for (cpu = 0; cpu < ncpus; cpu++) { > total = 0; > for (i = 0; i < CPUSTATES; i++) { > total += cp_times[cpu * CPUSTATES + i] - > cp_times_old[cpu * CPUSTATES + i]; > } > if (total == 0) > continue; >- *load += 100 - (cp_times[cpu * CPUSTATES + CP_IDLE] - >- cp_times_old[cpu * CPUSTATES + CP_IDLE]) * 100 / total; >+ excl = cp_times[cpu * CPUSTATES + CP_IDLE] - >+ cp_times_old[cpu * CPUSTATES + CP_IDLE]; >+ if (nonice) >+ excl += nonice*(cp_times[cpu * CPUSTATES + CP_NICE] - >+ cp_times_old[cpu * CPUSTATES + CP_NICE])/100; >+ /* These two can overlap: e.g. a command started "nice idprio 5 ..." */ >+ else if (noidle) >+ excl += noidle*(cpx_times[cpu * CPUSTATES_EXT + CPX_NICE_IDLE] - >+ cpx_times_old[cpu * CPUSTATES_EXT + CPX_NICE_IDLE])/100; >+ if (noidle) >+ excl += noidle*(cpx_times[cpu * CPUSTATES_EXT + CPX_USER_IDLE] - >+ cpx_times_old[cpu * CPUSTATES_EXT + CPX_USER_IDLE])/100; >+ >+ *load += 100 - excl * 100 / total; > } > } > > memcpy(cp_times_old, cp_times, cp_times_len); >+ if (noidle) >+ memcpy(cpx_times_old, cpx_times, cpx_times_len); > > return (0); > } > > static int > read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq) > { >@@ -192,16 +233,18 @@ > int i, j; > size_t len = 0; > > if (sysctl(levels_mib, 4, NULL, &len, NULL, 0)) > return (-1); > if ((freqstr = malloc(len)) == NULL) > return (-1); >- if (sysctl(levels_mib, 4, freqstr, &len, NULL, 0)) >+ if (sysctl(levels_mib, 4, freqstr, &len, NULL, 0)) { >+ free(freqstr); > return (-1); >+ } > > *numfreqs = 1; > for (p = freqstr; *p != '\0'; p++) > if (*p == ' ') > (*numfreqs)++; > > if ((*freqs = malloc(*numfreqs * sizeof(int))) == NULL) { >@@ -467,15 +510,15 @@ > } > > static void > usage(void) > { > > fprintf(stderr, >-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n"); >+"usage: powerd [-v] [-a mode] [-b mode] [-n mode] [-i %%] [-m freq] [-M freq] [-N %%] [-I %%] [-p ival] [-r %%] [-s source] [-P pidfile]\n"); > exit(1); > } > > int > main(int argc, char * argv[]) > { > struct timeval timeout; >@@ -484,29 +527,31 @@ > struct pidfh *pfh = NULL; > const char *pidfile = NULL; > int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load; > int minfreq = -1, maxfreq = -1; > int ch, mode, mode_ac, mode_battery, mode_none, idle, to; > uint64_t mjoules_used; > size_t len; >+ int nonice, noidle; > > /* Default mode for all AC states is adaptive. */ > mode_ac = mode_none = MODE_HIADAPTIVE; > mode_battery = MODE_ADAPTIVE; > cpu_running_mark = DEFAULT_ACTIVE_PERCENT; > cpu_idle_mark = DEFAULT_IDLE_PERCENT; > poll_ival = DEFAULT_POLL_INTERVAL; > mjoules_used = 0; > vflag = 0; >+ nonice = noidle = 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:n:p:P:r:s:v")) != -1) >+ while ((ch = getopt(argc, argv, "a:b:i:m:M:N:I:n:p:P:r:s:v")) != -1) > switch (ch) { > case 'a': > parse_mode(optarg, &mode_ac, ch); > break; > case 'b': > parse_mode(optarg, &mode_battery, ch); > break; >@@ -533,14 +578,30 @@ > maxfreq = atoi(optarg); > if (maxfreq < 0) { > warnx("%d is not a valid CPU frequency", > maxfreq); > usage(); > } > break; >+ case 'N': >+ nonice = atoi(optarg); >+ if (nonice < 0 || nonice > 100) { >+ warnx("%d is not a valid percent", nonice); >+ usage(); >+ } else >+ nonice = 100 - nonice; >+ break; >+ case 'I': >+ noidle = atoi(optarg); >+ if (noidle < 0 || noidle > 100) { >+ warnx("%d is not a valid percent", noidle); >+ usage(); >+ } else >+ noidle = 100 - noidle; >+ break; > case 'n': > parse_mode(optarg, &mode_none, ch); > break; > case 'p': > poll_ival = atoi(optarg); > if (poll_ival < 5) { > warnx("poll interval is in units of ms"); >@@ -570,23 +631,28 @@ > /* Poll interval is in units of ms. */ > poll_ival *= 1000; > > /* Look up various sysctl MIBs. */ > len = 2; > if (sysctlnametomib("kern.cp_times", cp_times_mib, &len)) > err(1, "lookup kern.cp_times"); >+ if (noidle) { >+ len = 2; >+ if (sysctlnametomib("kern.cp_times_ext", cpx_times_mib, &len)) >+ err(1, "lookup kern.cp_times_ext"); >+ } > len = 4; > if (sysctlnametomib("dev.cpu.0.freq", freq_mib, &len)) > err(EX_UNAVAILABLE, "no cpufreq(4) support -- aborting"); > len = 4; > if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len)) > err(1, "lookup freq_levels"); > > /* Check if we can read the load and supported freqs. */ >- if (read_usage_times(NULL)) >+ if (read_usage_times(NULL, nonice, noidle)) > err(1, "read_usage_times"); > if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq)) > err(1, "error reading supported CPU frequencies"); > if (numfreqs == 0) > errx(1, "no CPU frequencies in user-specified range"); > > /* Run in the background unless in verbose mode. */ >@@ -760,15 +826,15 @@ > continue; > } > } > continue; > } > > /* Adaptive mode; get the current CPU usage times. */ >- if (read_usage_times(&load)) { >+ if (read_usage_times(&load, nonice, noidle)) { > if (vflag) > warn("read_usage_times() failed"); > continue; > } > > if (mode == MODE_ADAPTIVE) { > if (load > cpu_running_mark) { >--- usr.sbin/powerd/powerd.8 >+++ usr.sbin/powerd/powerd.8 >@@ -18,128 +18,147 @@ > .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > .\" SUCH DAMAGE. > .\" >-.\" $FreeBSD: releng/12.1/usr.sbin/powerd/powerd.8 342981 2019-01-13 02:19:01Z avos $ >+.\" $FreeBSD: head/usr.sbin/powerd/powerd.8 358574 2020-03-03 13:25:08Z 0mp $ > .\" >-.Dd January 13, 2019 >+.Dd Jan 27, 2021 > .Dt POWERD 8 > .Os > .Sh NAME > .Nm powerd > .Nd "system power control utility" > .Sh SYNOPSIS > .Nm > .Op Fl a Ar mode > .Op Fl b Ar mode >-.Op Fl i Ar percent >-.Op Fl m Ar freq >-.Op Fl M Ar freq > .Op Fl n Ar mode >-.Op Fl p Ar ival >-.Op Fl P Ar pidfile >+.Op Fl M Ar freq >+.Op Fl m Ar freq >+.Op Fl N Ar percent >+.Op Fl I Ar percent >+.Op Fl i Ar percent > .Op Fl r Ar percent >+.Op Fl p Ar ival > .Op Fl s Ar source >+.Op Fl P Ar pidfile > .Op Fl v > .Sh DESCRIPTION > The > .Nm > utility monitors the system state and sets various power control options > accordingly. > It offers power-saving modes that can be > individually selected for operation on AC power or batteries. >-.Bl -tag -width ".Ar hiadaptive" >-.It Ar maximum >+.Bl -tag -width "hiadaptive" >+.It Cm maximum > Choose the highest performance values. > May be abbreviated as >-.Ar max . >-.It Ar minimum >+.Cm max . >+.It Cm minimum > Choose the lowest performance values to get the most power savings. > May be abbreviated as >-.Ar min . >-.It Ar adaptive >+.Cm min . >+.It Cm adaptive > Attempt to strike a balance by degrading performance when the system > appears idle and increasing it when the system is busy. > It offers a good balance between a small performance loss for greatly > increased power savings. > May be abbreviated as >-.Ar adp . >-.It Ar hiadaptive >+.Cm adp . >+.It Cm hiadaptive > Like >-.Ar adaptive >+.Cm adaptive > mode, but tuned for systems where performance and interactivity are > more important than power consumption. > It increases frequency faster, reduces frequency less aggressively, and > will maintain full frequency for longer. > May be abbreviated as >-.Ar hadp . >+.Cm hadp . > .El > .Pp > The default mode is >-.Ar adaptive >+.Cm adaptive > for battery power and >-.Ar hiadaptive >+.Cm hiadaptive > for the rest. > .Pp > .Nm > recognizes these runtime options: >-.Bl -tag -width ".Fl r Ar percent" >+.Bl -tag -width "-r percent" > .It Fl a Ar mode > Selects the > .Ar mode > to use while on AC power. > .It Fl b Ar mode > Selects the > .Ar mode > to use while on battery power. >-.It Fl i Ar percent >-Specifies the CPU load percent level when adaptive >-mode should begin to degrade performance to save power. >-The default is 50% or lower. >-.It Fl m Ar freq >-Specifies the minimum frequency to throttle down to. >-.It Fl M Ar freq >-Specifies the maximum frequency to throttle up to. > .It Fl n Ar mode > Selects the > .Ar mode > to use normally when the AC line state is unknown. >-.It Fl p Ar ival >-Specifies a different polling interval (in milliseconds) for AC line state >-and system idle levels. >-The default is 250 ms. >-.It Fl P Ar pidfile >-Specifies an alternative file in which the process ID should be stored. >-The default is >-.Pa /var/run/powerd.pid . >+.It Fl M Ar freq >+Specifies the maximum frequency to throttle up to. >+.It Fl m Ar freq >+Specifies the minimum frequency to throttle down to. >+.It Fl N Ar percent >+Weight "nice" CPU time by the given scale. >+.It Fl I Ar percent >+Weight "user idle" CPU time by the given scale. >+.Pp >+In both cases, 0 counts like "system idle" for the purpose of >+.Nm >+\'s internal load calculation; i.e., do not increase the CPU frequency >+if the CPU is only busy with "nice" or "user idle" processes. >+However, the system and interrupt load caused by these processes >+can not be scaled out. >+The implied default is 100, to fully count "nice" and "user idle" load. >+.It Fl i Ar percent >+Specifies the CPU load percent level when adaptive >+mode should begin to degrade performance to save power. >+The default is 50% or lower. > .It Fl r Ar percent > Specifies the CPU load percent level where adaptive > mode should consider the CPU running and increase performance. > The default is 75% or higher. >+.It Fl p Ar ival >+Specifies a different polling interval (in milliseconds) for AC line state >+and system idle levels. >+The default is 250 ms. > .It Fl s Ar source > Enforces method for AC line state refresh; by default, it is chosen > automatically. > The set of valid methods is > .Cm sysctl , devd > and > .Cm apm > (i386 only). >+.It Fl P Ar pidfile >+Specifies an alternative file in which the process ID should be stored. > .It Fl v > Verbose mode. > Messages about power changes will be printed to stdout and > .Nm > will operate in the foreground. > .El >+.Sh FILES >+.Bl -tag -width "/var/run/powerd.pid" >+.It Pa /var/run/powerd.pid >+The default PID file. >+.El > .Sh SEE ALSO > .Xr acpi 4 , > .Xr apm 4 , >-.Xr cpufreq 4 >+.Xr cpufreq 4 , >+.Xr nice 1 , >+.Xr idprio 1 . > .Sh HISTORY > The > .Nm > utility first appeared in > .Fx 6.0 . > .Sh AUTHORS > .An -nosplit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 246940
:
215172
|
215173
|
215241
|
215284
|
215285
|
221995
| 221997 |
221998
|
221999