Author: brucec
Date: Tue Aug 17 09:11:38 2010
New Revision: 211415
URL: http://svn.freebsd.org/changeset/base/211415

Log:
  Add -m and -M options to control the minimum and maximum frequency.
  
  PR:   bin/145063
  Submitted by: Boris Kochergin <spawk at acm.poly.edu>
  Reviewed by:  cperciva
  Approved by:  rrs (mentor)
  MFC after: 2 weeks

Modified:
  head/usr.sbin/powerd/powerd.8
  head/usr.sbin/powerd/powerd.c

Modified: head/usr.sbin/powerd/powerd.8
==============================================================================
--- head/usr.sbin/powerd/powerd.8       Tue Aug 17 09:08:28 2010        
(r211414)
+++ head/usr.sbin/powerd/powerd.8       Tue Aug 17 09:11:38 2010        
(r211415)
@@ -35,6 +35,8 @@
 .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
@@ -79,6 +81,10 @@ to use while on battery power.
 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

Modified: head/usr.sbin/powerd/powerd.c
==============================================================================
--- head/usr.sbin/powerd/powerd.c       Tue Aug 17 09:08:28 2010        
(r211414)
+++ head/usr.sbin/powerd/powerd.c       Tue Aug 17 09:11:38 2010        
(r211415)
@@ -84,7 +84,8 @@ const char *modes[] = {
 #define DEVCTL_MAXBUF  1024
 
 static int     read_usage_times(int *load);
-static int     read_freqs(int *numfreqs, int **freqs, int **power);
+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);
@@ -174,10 +175,10 @@ read_usage_times(int *load)
 }
 
 static int
-read_freqs(int *numfreqs, int **freqs, int **power)
+read_freqs(int *numfreqs, int **freqs, int **power, int minfreq, int maxfreq)
 {
        char *freqstr, *p, *q;
-       int i;
+       int i, j;
        size_t len = 0;
 
        if (sysctl(levels_mib, 4, NULL, &len, NULL, 0))
@@ -201,19 +202,30 @@ read_freqs(int *numfreqs, int **freqs, i
                free(*freqs);
                return (-1);
        }
-       for (i = 0, p = freqstr; i < *numfreqs; i++) {
+       for (i = 0, j = 0, p = freqstr; i < *numfreqs; i++) {
                q = strchr(p, ' ');
                if (q != NULL)
                        *q = '\0';
-               if (sscanf(p, "%d/%d", &(*freqs)[i], &(*power)[i]) != 2) {
+               if (sscanf(p, "%d/%d", &(*freqs)[j], &(*power)[i]) != 2) {
                        free(freqstr);
                        free(*freqs);
                        free(*power);
                        return (-1);
                }
+               if (((*freqs)[j] >= minfreq || minfreq == -1) &&
+                   ((*freqs)[j] <= maxfreq || maxfreq == -1))
+                       j++;
                p = q + 1;
        }
 
+       *numfreqs = j;
+       if ((*freqs = realloc(*freqs, *numfreqs * sizeof(int))) == NULL) {
+               free(freqstr);
+               free(*freqs);
+               free(*power);
+               return (-1);
+       }
+
        free(freqstr);
        return (0);
 }
@@ -422,7 +434,7 @@ usage(void)
 {
 
        fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] 
[-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] 
[-p ival] [-r %%] [-P pidfile]\n");
        exit(1);
 }
 
@@ -435,6 +447,7 @@ main(int argc, char * argv[])
        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;
@@ -452,7 +465,7 @@ main(int argc, char * argv[])
        if (geteuid() != 0)
                errx(1, "must be root to run");
 
-       while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != -1)
+       while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:v")) != -1)
                switch (ch) {
                case 'a':
                        parse_mode(optarg, &mode_ac, ch);
@@ -468,6 +481,22 @@ main(int argc, char * argv[])
                                usage();
                        }
                        break;
+               case 'm':
+                       minfreq = atoi(optarg);
+                       if (minfreq < 0) {
+                               warnx("%d is not a valid CPU frequency",
+                                   minfreq);
+                               usage();
+                       }
+                       break;
+               case 'M':
+                       maxfreq = atoi(optarg);
+                       if (maxfreq < 0) {
+                               warnx("%d is not a valid CPU frequency",
+                                   maxfreq);
+                               usage();
+                       }
+                       break;
                case 'n':
                        parse_mode(optarg, &mode_none, ch);
                        break;
@@ -515,8 +544,10 @@ main(int argc, char * argv[])
        /* Check if we can read the load and supported freqs. */
        if (read_usage_times(NULL))
                err(1, "read_usage_times");
-       if (read_freqs(&numfreqs, &freqs, &mwatts))
+       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. */
        if (!vflag) {
@@ -552,6 +583,49 @@ main(int argc, char * argv[])
        i = get_freq_id(curfreq, freqs, numfreqs);
        if (freq < 1)
                freq = 1;
+
+       /*
+        * If we are in adaptive mode and the current frequency is outside the
+        * user-defined range, adjust it to be within the user-defined range.
+        */
+       acline_read();
+       if (acline_status > SRC_UNKNOWN)
+               errx(1, "invalid AC line status %d", acline_status);
+       if ((acline_status == SRC_AC &&
+           (mode_ac == MODE_ADAPTIVE || mode_ac == MODE_HIADAPTIVE)) ||
+           (acline_status == SRC_BATTERY &&
+           (mode_battery == MODE_ADAPTIVE || mode_battery == MODE_HIADAPTIVE)) 
||
+           (acline_status == SRC_UNKNOWN &&
+           (mode_none == MODE_ADAPTIVE || mode_none == MODE_HIADAPTIVE))) {
+               /* Read the current frequency. */
+               len = sizeof(curfreq);
+               if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) != 0) {
+                       if (vflag)
+                               warn("error reading current CPU frequency");
+               }
+               if (curfreq < freqs[numfreqs - 1]) {
+                       if (vflag) {
+                               printf("CPU frequency is below user-defined "
+                                   "minimum; changing frequency to %d "
+                                   "MHz\n", freqs[numfreqs - 1]);
+                       }
+                       if (set_freq(freqs[numfreqs - 1]) != 0) {
+                               warn("error setting CPU freq %d",
+                                   freqs[numfreqs - 1]);
+                       }
+               } else if (curfreq > freqs[0]) {
+                       if (vflag) {
+                               printf("CPU frequency is above user-defined "
+                                   "maximum; changing frequency to %d "
+                                   "MHz\n", freqs[0]);
+                       }
+                       if (set_freq(freqs[0]) != 0) {
+                               warn("error setting CPU freq %d",
+                                   freqs[0]);
+                       }
+               }
+       }
+
        idle = 0;
        /* Main loop. */
        for (;;) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to