rpms/cpuspeed/devel cpuspeed-1.2.1-multicore-support.patch, NONE, 1.1 cpuspeed-1.2.1-no-affected_cpus-fallback.patch, NONE, 1.1 cpuspeed.init, 1.39, 1.40 cpuspeed.spec, 1.68, 1.69 cpuspeed-1.2.1-multicore-workaround.patch, 1.1, NONE cpuspeed.patch, 1.1, NONE idlenice.diff, 1.2, NONE warning.diff, 1.1, NONE

Jarod Wilson jwilson at fedoraproject.org
Fri Sep 26 21:24:02 UTC 2008


Author: jwilson

Update of /cvs/pkgs/rpms/cpuspeed/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv3585

Modified Files:
	cpuspeed.init cpuspeed.spec 
Added Files:
	cpuspeed-1.2.1-multicore-support.patch 
	cpuspeed-1.2.1-no-affected_cpus-fallback.patch 
Removed Files:
	cpuspeed-1.2.1-multicore-workaround.patch cpuspeed.patch 
	idlenice.diff warning.diff 
Log Message:
* Fri Sep 26 2008 Jarod Wilson <jarod at redhat.com> 1.2.1-9
- backport proper multicore support for userspace governor
  (cpuspeed daemon) case from v1.5 cpuspeed snapshot


cpuspeed-1.2.1-multicore-support.patch:

--- NEW FILE cpuspeed-1.2.1-multicore-support.patch ---
diff -Naurp cpuspeed-1.2.1/cpuspeed.cc cpuspeed-1.2.1.mc/cpuspeed.cc
--- cpuspeed-1.2.1/cpuspeed.cc	2008-09-26 11:41:47.000000000 -0400
+++ cpuspeed-1.2.1.mc/cpuspeed.cc	2008-09-26 12:33:09.000000000 -0400
@@ -1,7 +1,7 @@
 /*
-    $Id: $
+    $Id: cpuspeed.cc 7 2007-02-06 01:20:52Z carl $
 
-    Copyright 2002 - 2005
+    Copyright 2002 - 2008
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -19,14 +19,17 @@
     This program is only for computers with Linux kernels compiled with
     CPUFreq.  You must have a CPU that supports frequency and/or voltage
     scaling via CPUFreq to use this program.  Your kernel must be compiled to
-    support the "userspace" CPUFreq governor and the "sysfs" interface on
-    Linux 2.6 or the "proc" interface on Linux 2.4.
+    support the "userspace" CPUFreq governor and the "sysfs" interface used
+    by Linux 2.6.
 
-    I use this program on my eMachines M5305 and Acer Ferrari 3200 laptops to
-    increase battery life and control performance.
+    CPUSpeed no longer supports the "proc" interface used by Linux 2.4.
+
+    I use this program on my Dell Inspiron 1420, HP Pavilion DV-9500 and
+    Toshiba laptops to increase battery life and control performance.
 */
 
-const char VERSION[] = "1.2.1";
+const char VERSION[] = "1.2.1-rh";
+const char AUTHOR[] = "Carl E. Thompson - cet [at] carlthompson.net (Copyright 2002 - 2008)";
 
 #include <unistd.h>
 #include <stdio.h>
@@ -50,6 +53,13 @@ const unsigned MAX_SPEEDS  = 15;
 // Minimum speed step supported in KHz
 const unsigned MIN_STEP = 25000;
 
+// Maximimum number of processor cores that can be controlled simultaneously
+// by one CPUSpeed process
+const unsigned MAX_TIED_CORES = 8;
+
+const char SYSFS_CPUFREQ_DIR[] =
+    "/sys/devices/system/cpu/cpu%u/cpufreq";
+
 const char SYSFS_MIN_SPEED_FILE[] =
     "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_min_freq";
 
@@ -62,33 +72,22 @@ const char SYSFS_CURRENT_SPEED_FILE[] =
 const char SYSFS_GOVERNOR_FILE[] =
      "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor";
 
+const char SYSFS_AFFECTED_CPUS_FILE[] =
+     "/sys/devices/system/cpu/cpu%u/cpufreq/affected_cpus";
+
 const char SYSFS_USERSPACE[] =
     "userspace";
 
 const char * PROC_STAT_FILE =
     "/proc/stat";
 
-#ifdef WITH_PROC
-const char PROC_MIN_SPEED_FILE[] =
-    "/proc/sys/cpu/%u/speed-min";
-
-const char PROC_MAX_SPEED_FILE[] =
-    "/proc/sys/cpu/%u/speed-max";
-
-const char PROC_CURRENT_SPEED_FILE[] =
-    "/proc/sys/cpu/%u/speed";
-
-const char PROC_GOVERNOR_FILE[] =
-    "/proc/cpufreq";
-
-const char PROC_USERSPACE[] =
-    "0%0%100%userspace";
-#endif
-
 #ifdef DEBUG
 const char * FAKE_STAT_FILE =
     "/tmp/cpuspeed/stat";
 
+const char FAKE_CPUFREQ_DIR[] =
+    "/tmp/cpuspeed/%u";
+
 const char FAKE_MIN_SPEED_FILE[] =
     "/tmp/cpuspeed/%u/speed-min";
 
@@ -101,6 +100,9 @@ const char FAKE_CURRENT_SPEED_FILE[] =
 const char FAKE_GOVERNOR_FILE[] =
     "/tmp/cpuspeed/%u/governor";
 
+const char FAKE_AFFECTED_CPUS_FILE[] =
+    "/tmp/cpuspeed/%u/affected_cores";
+
 const char FAKE_USERSPACE[] =
     "userspace";
 #endif
@@ -109,11 +111,42 @@ const char * MIN_SPEED_FILE;
 const char * MAX_SPEED_FILE;
 const char * CURRENT_SPEED_FILE;
 const char * GOVERNOR_FILE;
+const char * AFFECTED_CPUS_FILE;
 const char * USERSPACE;
 const char * STAT_FILE;
 
+// if CPU idle percentage is below this, CPU will be set to fastest speed
+unsigned clock_up_idle_fast= 10;
+
+// if CPU idle percentage is below this, CPU will be set to next higher speed
+// if CPU idle percentage is above this, CPU will be set to next lower speed
+unsigned idle_threshold = 25;
+
+// if this is set (via command line) throttle down CPU to minimum if
+// temperature is too high
+const char * temperature_filename = 0;
+unsigned max_temperature;
+
+// if this is set (via command line) throttle down CPU to minimum if
+// AC power is disconnected
+const char * ac_filename = 0;
+
+// if this is true then maximize speed when AC connected
+bool max_speed_on_ac = false;
+
+// if this is true then minimize speed when AC disconnected
+bool min_speed_on_battery = true;
+
+// if this is true then NICE time does not count as utilized time
+bool nice_counts_as_idle = true;
+
+// if this is true then IO wait time does not count as utilized time
+bool io_counts_as_idle = true;
+
+bool check_cpu = false, check_therm = false, check_ac = false;
+
 // defines what info we care about for each speed step
-struct
+static struct
 {
     unsigned khz;
     //unsigned volts;
@@ -122,8 +155,9 @@ struct
 unsigned current_speed; // current speed step
 unsigned last_step; // lowest speed step
 
-// which CPU are we controlling
-unsigned cpu = 0;
+// which CPU cores are we controlling
+unsigned tied_cpu_cores[MAX_TIED_CORES];
+unsigned num_tied_cores = 0;
 
 // display an error message and exit the program
 void
@@ -140,7 +174,9 @@ die(bool system_error, const char *fmt, 
 
     fprintf(stderr, "\n");
     if (system_error)
+    {
         fprintf(stderr, "Error: %s\n", strerror(errno));
+    }
 
     exit(1);
 }
@@ -151,10 +187,19 @@ read_line(const char * filename, char * 
 {
     FILE * fp = fopen(filename, "r");
     if (!fp)
+    {
         die(true, "Could not open file for reading: %s", filename);
+    }
     if ( (!fgets(line, len, fp)) )
-        die(true, "Could not read from file: %s", filename);
+    {
+        die(false, "Could not read from file: %s", filename);
+    }
     fclose(fp);
+    char * p = strchr(line, '\n');
+    if (p)
+    {
+        *p = 0;
+    }
 }
 
 // write a line to a file
@@ -163,23 +208,83 @@ write_line(const char * filename, const 
 {
     FILE * fp = fopen(filename, "w+");
     if (!fp)
+    {
         die(true, "Could not open file for writing: %s", filename);
+    }
     va_list ap;
     // get variable argument list passed
     va_start(ap, fmt);
     if (vfprintf(fp, fmt, ap) < 0)
+    {
         die(true, "Could not write to file: %s", filename);
+    }
     va_end(ap);
     fclose(fp);
 }
 
+long
+get_int(const char * s)
+{
+    char * end;
+    long r = strtol(s, &end, 10);
+    if (*end != '\0')
+    {
+        die(false, "Not an integer: [%s]", s);
+    }
+    if (errno == ERANGE)
+    {
+        die(false, "Number is out of range: %s", s);
+    }
+    return r;
+}
+
 // read an integer value from a file
 unsigned
 read_value(const char * filename)
 {
     char line[256];
     read_line(filename, line, sizeof line);
-    return atoi(line);
+    return (unsigned) get_int(line);
+}
+
+// Read multiple integer values from a string. Returns them in the array
+// reference pointed to by "values" . Returns the number of values read.
+unsigned
+parse_values(const char * string, unsigned *  values, unsigned len)
+{
+    char line[256];
+    char * svalue;
+    unsigned num_found = 0;
+    strncpy(line, string, sizeof line);
+    line[sizeof line - 1] = '\0';
+    for (
+            svalue = strtok(line, " \t\n");
+            svalue;
+            svalue = strtok(NULL, " \t\n"), num_found++
+        )
+    {
+        if (num_found == len)
+        {
+            die(
+                false,
+                "More than the maximum allowed %u values found in input: [%s]",
+                len, string
+             );
+        }
+        values[num_found] = (unsigned) get_int(svalue);
+    }
+
+    return num_found;
+}
+
+// Read multiple integer values from a file. Returns them in the array
+// reference pointed to by "values" . Returns the number of values read.
+unsigned
+read_values(const char * filename, unsigned *  values, unsigned len)
+{
+    char line[256];
+    read_line(filename, line, sizeof line);
+    return parse_values(line, values, len);
 }
 
 // get the current CPU speed
@@ -192,7 +297,9 @@ unsigned get_speed()
 void set_speed(unsigned value)
 {
 #ifdef DEBUG
-    fprintf(stderr, "[cpu%u] Setting speed to: %uKHz\n", cpu, value);
+    fprintf(
+        stderr, "[core%u] Setting speed to: %uKHz\n", tied_cpu_cores[0], value
+    );
 #endif
     write_line(CURRENT_SPEED_FILE, "%u\n", value);
     // give CPU / chipset voltage time to settle down
@@ -205,19 +312,22 @@ void set_speed(unsigned value)
 void set_speed(unsigned current, unsigned target)
 {
     if (current == target)
+    {
         return;
+    }
     int delta = (current > target) ? -1 : 1;
     do
     {
         current += delta;
         set_speed(speeds[current].khz);
-    }
-    while (current != target);
+    } while (current != target);
 }
 
-
+// comparison functions
 inline unsigned MIN(unsigned a, unsigned b) { return a > b ? b : a; }
 inline unsigned MAX(unsigned a, unsigned b) { return a > b ? a : b; }
+inline int icomp(const void * a, const void * b)
+    { return *((int *)a) - *((int *)b); }
 
 // the minimum and maximum speed that we are allowed to set
 unsigned min_speed = 0, max_speed = UINT_MAX;
@@ -230,8 +340,14 @@ get_supported_speeds()
     unsigned max = read_value(MAX_SPEED_FILE);
 
 #ifdef DEBUG
-    fprintf(stderr, "[cpu%u] Mimimum speed supported: %uKHz\n", cpu, min);
-    fprintf(stderr, "[cpu%u] Maximum speed supported: %uKHz\n", cpu, max);
+    fprintf(
+        stderr, "[core%u] Mimimum speed supported: %uKHz\n",
+        tied_cpu_cores[0], min
+    );
+    fprintf(
+        stderr, "[core%u] Maximum speed supported: %uKHz\n",
+        tied_cpu_cores[0], max
+    );
 #endif
     min = MAX(min, min_speed);
     max = MIN(max, max_speed);
@@ -242,35 +358,47 @@ get_supported_speeds()
     {
         min = MAX(min, step);
         if (max <= min)
+        {
             die(false, "No speed steps could be determined!");
+        }
 
-        // Go to max speed if we are not already there
-        for (unsigned current = get_speed(); current <= max; current += step)
-                set_speed(current);
+        // go to max speed if we are not already there
+        for (unsigned current = get_speed(); current < max; current += step)
+        {
+            set_speed(MIN(current, max));
+        }
         set_speed(max);
 
         // this code is a hack to get the various speed steps supported by the
-        // CPU by looping from the maximum speed to the minimum speed and trying
-        // to set every possible speed divisible by step!
-        speeds[0].khz = max;
+        // CPU by looping from the maximum speed to the minimum speed and
+        // trying to set every possible speed divisible by step!
+
+        // speed is set to max above so returns real maximum that can be set
+        speeds[0].khz = get_speed();
         current_speed = 0;
-        for (unsigned current = max - step; current > min - step; current -= step)
+        for (unsigned current = max-step; current > min-step; current -= step)
         {
-                current = MAX(current, min);
-                set_speed(current);
-                unsigned real = get_speed();
-                if (real != speeds[current_speed].khz)
-                {
+            current = MAX(current, min);
+            set_speed(current);
+            unsigned real = get_speed();
+            if (real != speeds[current_speed].khz)
+            {
                 speeds[++current_speed].khz = real;
                 if (current_speed + 1 == MAX_SPEEDS)
-                        break;
+                {
+                    break;
                 }
+            }
         }
         if (current_speed + 1 != MAX_SPEEDS)
-                break;
+        {
+            break;
+        }
     }
     if (step > MAX_STEP)
+    {
         die(false, "Detected more speed steps than this program can handle?!");
+    }
 
     speeds[current_speed + 1].khz = 0;
 
@@ -278,41 +406,69 @@ get_supported_speeds()
     last_step = current_speed;
 
 #ifdef DEBUG
-    fprintf(stderr, "[cpu%u] Available speeds:\n", cpu);
+    fprintf(stderr, "[core%u] Available speeds:\n", tied_cpu_cores[0]);
     for (unsigned speed = 0; speeds[speed].khz; speed++)
-        fprintf(stderr, "[cpu%u]  %2u: %9uKHz\n", cpu, speed, speeds[speed].khz);
+    {
+        fprintf(
+            stderr, "[core%u]  %2u: %9uKHz\n",
+            tied_cpu_cores[0], speed, speeds[speed].khz
+        );
+    }
 #endif
 }
 
+// are we currently dynamically scaling the CPU or at min or max?
+enum Mode { SPEED_DYNAMIC, SPEED_MIN, SPEED_MAX } mode;
+
 // gets the elapsed total time and elapsed idle time since it was last called
 void
-get_times(unsigned long & total_elapsed, unsigned long & idle_elapsed)
+get_times(
+    unsigned tied_core_index, unsigned long & total_elapsed,
+    unsigned long & idle_elapsed
+)
 {
     FILE * fp = fopen(STAT_FILE, "r");
     if (!fp)
+    {
         die(true, "Could not open %s for reading!", STAT_FILE);
+    }
 
-    static char search[8];
-    static size_t searchlen = 0;
-    if (!searchlen)
+    static char search[MAX_TIED_CORES][8];
+    static size_t searchlen[MAX_TIED_CORES];
+    if (!searchlen[tied_core_index])
     {
-        snprintf(search, sizeof search, "cpu%u ", cpu);
-        searchlen = strlen(search);
+        searchlen[tied_core_index] =
+            snprintf(
+                search[tied_core_index], sizeof search[tied_core_index],
+                "cpu%u ", tied_cpu_cores[tied_core_index]
+            );
 #ifdef DEBUG
-        fprintf(stderr, "[cpu%u] Looking for CPU line starting with: \"%s\"\n", cpu, search);
+        fprintf(
+            stderr, "[core%u] Looking for CPU line starting with: \"%s\"\n",
+            tied_cpu_cores[tied_core_index], search[tied_core_index]
+        );
 #endif
     }
-    bool found;
+    bool found = false;
     char line[256];
-    while ( (found = fgets(line, sizeof line, fp)) && strncmp(line, search, searchlen) )
-    ;
+    while (fgets(line, sizeof line, fp))
+    {
+        if (!strncmp(line, search[tied_core_index], searchlen[tied_core_index]))
+        {
+            found = true;
+            break;
+        }
+    }
 
     fclose(fp);
 
     if (!found)
     {
 #ifdef DEBUG
-        fprintf(stderr, "[cpu%u] Could not find \'%s\' line in %s.\n", cpu, search, STAT_FILE);
+        fprintf(
+            stderr, "[core%u] Could not find \'%s\' line in file: %s.\n",
+            tied_cpu_cores[tied_core_index], search[tied_core_index], STAT_FILE
+        );
 #endif
         return;
     }
@@ -325,20 +481,31 @@ get_times(unsigned long & total_elapsed,
     );
 
     // count nice time as idle time
-    idle_time += nice_time;
+    if (nice_counts_as_idle)
+    {
+        idle_time += nice_time;
+    }
 
     // count IO wait time as idle time
-    idle_time += wait_time;
+    if (io_counts_as_idle)
+    {
+        idle_time += wait_time;
+    }
 
     unsigned long total_time = user_time + system_time + idle_time;
-    static unsigned long last_total_time = 0, last_idle_time = 0;
-    total_elapsed = total_time - last_total_time;
-    last_total_time = total_time;
-    idle_elapsed = idle_time - last_idle_time;
-    last_idle_time = idle_time;
+    static unsigned long last_total_time[MAX_TIED_CORES],
+        last_idle_time[MAX_TIED_CORES];
+
+    total_elapsed = total_time - last_total_time[tied_core_index];
+    last_total_time[tied_core_index] = total_time;
+    idle_elapsed = idle_time - last_idle_time[tied_core_index];
+    last_idle_time[tied_core_index] = idle_time;
 
 #ifdef DEBUG
-    fprintf(stderr, "[cpu%u] time: %lu    idle: %lu\n", cpu, total_elapsed, idle_elapsed);
+    fprintf(
+        stderr, "[core%u] time: %lu    idle: %lu\n",
+        tied_cpu_cores[tied_core_index], total_elapsed, idle_elapsed
+    );
 #endif
 }
 
@@ -346,36 +513,12 @@ get_times(unsigned long & total_elapsed,
 void reset_times()
 {
     unsigned long dummy1, dummy2;
-    get_times(dummy1, dummy2);
+    for (unsigned u = 0; u < num_tied_cores; u++)
+    {
+        get_times(u, dummy1, dummy2);
+    }
 }
 
-// are we currently dynamically scaling the CPU or at min or max?
-enum Mode { SPEED_DYNAMIC, SPEED_MIN, SPEED_MAX } mode;
-
-// if CPU idle percentage is below this, CPU will be set to fastest speed
-unsigned clock_up_idle_fast= 10;
-
-// if CPU idle percentage is below this, CPU will be set to next higher speed
-// if CPU idle percentage is above this, CPU will be set to next lower speed
-unsigned idle_threshold = 25;
-
-// if this is set (via command line) throttle down CPU to minimum if
-// temperature is too high
-const char * temperature_filename = 0;
-unsigned max_temperature;
-
-// if this is set (via command line) throttle down CPU to minimum if
-// AC power is disconnected
-const char * ac_filename = 0;
-
-// if this is true then maximize speed when AC connected
-bool max_speed_on_ac = false;
-
-// if this is true then minimize speed when AC disconnected
-bool min_speed_on_battery = true;
-
-bool check_cpu = false, check_therm = false, check_ac = false;
-
 // handles the periodic check of idle and setting CPU speed
 void
 alarm_handler(int)
@@ -399,22 +542,26 @@ alarm_handler(int)
             {
                 on_ac = false;
 #ifdef DEBUG
-                fprintf(stderr, "[cpu%u] AC is off-line\n", cpu);
+                fprintf(stderr, "[core%u] AC is off-line\n", tied_cpu_cores[0]);
 #endif
             }
             else
             {
                 on_ac = true;
 #ifdef DEBUG
-                fprintf(stderr, "[cpu%u] AC is on-line\n", cpu);
+                fprintf(stderr, "[core%u] AC is on-line\n", tied_cpu_cores[0]);
 #endif
             }
         }
 
         if (max_speed_on_ac && on_ac)
+        {
             state = SPEED_MAX;
+        }
         else if (!on_ac && min_speed_on_battery)
+        {
             state = SPEED_MIN;
+        }
 
         // check that we are not getting too hot
         if (temperature_filename && check_therm && state != SPEED_MIN)
@@ -422,12 +569,22 @@ alarm_handler(int)
             read_line(temperature_filename, line, sizeof line);
             p = strpbrk(line, "0123456789");
             if (!p)
-                die(false, "Could not find temperature in file: %s", temperature_filename);
+            {
+                die(
+                    false, "Could not find temperature in file: %s",
+                    temperature_filename
+                );
+            }
 #ifdef DEBUG
-        fprintf(stderr, "[cpu%u] temp: %ld\n", cpu, strtol(p, 0, 10));
+            fprintf(
+                stderr, "[core%u] temp: %ld\n", tied_cpu_cores[0],
+                strtol(p, 0, 10)
+            );
 #endif
             if (strtol(p, 0, 10) > (long)max_temperature)
+            {
                 state = SPEED_MIN;
+            }
         }
     }
 
@@ -438,28 +595,59 @@ alarm_handler(int)
         {
             // if it's not yet time to check CPU then don't
             if (!check_cpu)
+            {
                 break;
+            }
 
-            unsigned long elapsed_time, idle_time;
-            unsigned idle_percent;
+            unsigned wanted_speed[MAX_TIED_CORES];
+            for (unsigned i = 0; i < num_tied_cores; i++)
+            {
+                unsigned long elapsed_time, idle_time;
+                unsigned idle_percent;
 
-            // get the elapsed and idle times since we last checked
-            get_times(elapsed_time, idle_time);
+                // get the elapsed and idle times since we last checked
+                get_times(i, elapsed_time, idle_time);
 
-            if (elapsed_time > 0)
-            {
-                idle_percent = idle_time * 100 / elapsed_time;
+                wanted_speed[i] = current_speed;
+                if (elapsed_time > 0)
+                {
+                    idle_percent = idle_time * 100 / elapsed_time;
 
-                if (idle_percent <= clock_up_idle_fast)
-                    current_speed = 0;
-                else if (idle_percent < idle_threshold && current_speed > 0)
-                    current_speed--;
-                else if (idle_percent > idle_threshold && speeds[current_speed + 1].khz != 0)
-                    current_speed++;
-#ifdef DEBUG
-                fprintf(stderr, "[cpu%u] Idle percent: %.2u\n", cpu, idle_percent);
+                    if (idle_percent <= clock_up_idle_fast)
+                    {
+                        wanted_speed[i] = 0;
+                    }
+                    else if (idle_percent < idle_threshold && current_speed > 0)
+                    {
+                        wanted_speed[i] = current_speed - 1;
+                    }
+                    else if (
+                        idle_percent > idle_threshold
+                        && speeds[current_speed + 1].khz != 0
+                    )
+                    {
+                        wanted_speed[i] = current_speed + 1;
+                    }
+#ifdef DEBUG
+                    fprintf(
+                        stderr, "[core%u] idle percent: %.2u\n",
+                        tied_cpu_cores[i], idle_percent
+                    );
+                    fprintf(
+                        stderr, "[core%u] wanted speed: %u\n",
+                        tied_cpu_cores[i], wanted_speed[i]
+                    );
 #endif
+                }
             }
+            qsort(wanted_speed, num_tied_cores, sizeof(unsigned), icomp);
+            current_speed = wanted_speed[0];
+#ifdef DEBUG
+            fprintf(
+                stderr, "[core%u] winning speed: %u\n",
+                tied_cpu_cores[0], wanted_speed[0]
+            );
+#endif
             break;
         }
 
@@ -476,9 +664,10 @@ alarm_handler(int)
     if (current_speed != old_speed)
     {
 #ifdef DEBUG
+fprintf(stderr, "Current: %u\n", current_speed);
         fprintf(
-            stderr, "[cpu%u] old speed: %uKHz     new speed: %uKHz\n",
-            cpu, speeds[old_speed].khz, speeds[current_speed].khz
+            stderr, "[core%u] old speed: %uKHz     new speed: %uKHz\n",
+            tied_cpu_cores[0], speeds[old_speed].khz, speeds[current_speed].khz
         );
 #endif
         set_speed(old_speed, current_speed);
@@ -516,12 +705,11 @@ hup_handler(int)
     raise(SIGALRM);
 }
 
-unsigned num_cpus = 0; // how many CPUs are we managing? 0 = autodetect
+unsigned num_cores = 0; // how many CPU cores are we managing? 0 = autodetect
 
 // restore  initial speed on program exit
 unsigned saved_speed = 0;
 char saved_governor[32];
-pid_t * saved_pids;
 
 void
 term_handler(int which)
@@ -532,33 +720,14 @@ term_handler(int which)
         write_line(GOVERNOR_FILE, "%s\n", saved_governor);
     }
 
-    if (cpu == 0)
-    {
-        for (unsigned i = 1; i < num_cpus; i++)
-            kill(saved_pids[i], which);
-    }
-
     raise(which);
 }
 
-long
-get_int(const char * s)
-{
-    char * end;
-    long r = strtol(s, &end, 10);
-    if (*end != '\0')
-        die(false, "Not an integer: %s", s);
-    if (errno == ERANGE)
-        die(false, "Number is out of range: %s", s);
-
-    return r;
-}
-
 char *
 dup_cpu_str(const char *s)
 {
     char buf[256];
-    snprintf(buf, sizeof buf, s, cpu);
+    snprintf(buf, sizeof buf, s, tied_cpu_cores[0]);
     return strdup(buf);
 }
 
@@ -579,106 +748,157 @@ main(int argc, char * argv[])
 #endif
 
     // parse argv
-    for(int i = 1; i < argc; i++)
+    for (int i = 1; i < argc; i++)
     {
-        if(!strcmp(argv[i], "-d"))
+        if (!strcmp(argv[i], "-d"))
             daemonize = true;
-        else if(!strcmp(argv[i], "-r"))
+        else if (!strcmp(argv[i], "-r"))
             save_state = true;
-        else if(!strcmp(argv[i], "-C"))
+        else if (!strcmp(argv[i], "-C"))
             max_speed_on_ac = true;
-        else if(!strcmp(argv[i], "-D"))
+        else if (!strcmp(argv[i], "-D"))
             min_speed_on_battery = false;
-        else if(!strcmp(argv[i], "-i"))
+        else if (!strcmp(argv[i], "-n"))
+            nice_counts_as_idle = false;
+        else if (!strcmp(argv[i], "-w"))
+            io_counts_as_idle = false;
+        else if (!strcmp(argv[i], "-i"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-i\' option must be followed by an interval in tenths of a second");
+            {
+                die(
+                    false, "The \'-i\' option must be followed by an interval "
+                    "in tenths of a second"
+                );
+            }
             interval = get_int(argv[++i]);
 #ifdef DEBUG
             fprintf(stderr, "CPU interval is %u\n", interval);
 #endif
         }
-        else if(!strcmp(argv[i], "-p"))
+        else if (!strcmp(argv[i], "-p"))
         {
             if (argc <= i + 2)
+            {
                 die(false, "The \'-p\' option must be followed by 2 integers");
+            }
             clock_up_idle_fast = get_int(argv[++i]);
             idle_threshold = get_int(argv[++i]);
 #ifdef DEBUG
-            fprintf(stderr, "Triggers are %u %u\n",clock_up_idle_fast, idle_threshold);
+            fprintf(
+                stderr, "Triggers are %u %u\n",
+                clock_up_idle_fast, idle_threshold
+            );
 #endif
         }
         else if (!strcmp(argv[i], "-t"))
         {
             if (argc <= i + 2)
-                die(false, "The \'-t\' option must be followed by a filename and a temperature");
+            {
+                die(
+                    false, "The \'-t\' option must be followed by a filename "
+                    "and a temperature"
+                );
+            }
             temperature_filename = argv[++i];
             max_temperature = get_int(argv[++i]);
         }
         else if (!strcmp(argv[i], "-a"))
         {
             if (argc <= i + 1)
+            {
                 die(false, "The \'-a\' option must be followed by a filename");
+            }
             ac_filename = argv[++i];
         }
-        else if(!strcmp(argv[i], "-m"))
+        else if (!strcmp(argv[i], "-m"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-m\' option must be followed by a minimum speed in KHz");
+            {
+                die(
+                    false, "The \'-m\' option must be followed by a minimum "
+                    "speed in KHz"
+                );
+            }
             min_speed = get_int(argv[++i]);
 #ifdef DEBUG
-            fprintf(stderr, "Minimum speed allowed by user: %uKHz\n", min_speed);
+            fprintf(
+                stderr, "Minimum speed allowed by user: %uKHz\n", min_speed
+            );
 #endif
         }
-        else if(!strcmp(argv[i], "-M"))
+        else if (!strcmp(argv[i], "-M"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-M\' option must be followed by a maximum speed in KHz");
+            {
+                die(
+                    false, "The \'-M\' option must be followed by a maximum "
+                    "speed in KHz"
+                );
+            }
             max_speed = get_int(argv[++i]);
 #ifdef DEBUG
-            fprintf(stderr, "Maximum speed allowed by user: %uKHz\n", max_speed);
+            fprintf(
+                stderr, "Maximum speed allowed by user: %uKHz\n", max_speed
+            );
 #endif
         }
-        else if(!strcmp(argv[i], "-T"))
+        else if (!strcmp(argv[i], "-T"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-T\' option must be followed by an interval in tenths of a second");
+            {
+                die(
+                    false, "The \'-T\' option must be followed by an interval "
+                    "in tenths of a second"
+                );
+            }
             therm_interval = get_int(argv[++i]);
 #ifdef DEBUG
             fprintf(stderr, "Thermal interval is %u\n", therm_interval);
 #endif
         }
-        else if(!strcmp(argv[i], "-A"))
+        else if (!strcmp(argv[i], "-A"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-A\' option must be followed by an interval in tenths of a second");
+            {
+                die(
+                    false, "The \'-A\' option must be followed by an interval "
+                    "in tenths of a second"
+                );
+            }
             ac_interval = get_int(argv[++i]);
 #ifdef DEBUG
             fprintf(stderr, "AC interval is %u\n", ac_interval);
 #endif
         }
-        else if(!strcmp(argv[i], "-s"))
+        else if (!strcmp(argv[i], "-S"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-s\' option must be followed by a CPU number");
-            cpu = get_int(argv[++i]);
-            num_cpus = 1;
+            {
+                die(
+                    false, "The \'-S\' option must be followed by a list of "
+                    "CPU cores"
+                );
+            }
+            num_tied_cores = parse_values(argv[++i], tied_cpu_cores, MAX_TIED_CORES);
+
 #ifdef DEBUG
-            fprintf(stderr, "Managing only CPU #%u\n", cpu);
+            fprintf(stderr, "Managing only CPU core(s): %s\n", argv[i]);
 #endif
         }
 #ifdef DEBUG
-        else if(!strcmp(argv[i], "-f"))
+        else if (!strcmp(argv[i], "-f"))
         {
             if (argc <= i + 1)
-                die(false, "The \'-f\' option must be followed by the number of fake CPUs");
-            if (fake_cpu)
-                die(false, "The \'-f\' option may only be used once");
-            if (num_cpus)
-                die(false, "The \'-f\' option must come before the \'-s\' option");
-            num_cpus = get_int(argv[++i]);
+            {
+                die(
+                    false, "The \'-f\' option must be followed by the number "
+                    "of fake CPU cores"
+                );
+            }
+            num_cores = get_int(argv[++i]);
             fake_cpu = true;
-            fprintf(stderr, "%u fake CPU(s) detected\n", num_cpus);
+            fprintf(stderr, "%u fake CPU core(s) detected\n", num_cores);
         }
 #endif
         else
@@ -688,15 +908,15 @@ main(int argc, char * argv[])
                 "%s v%s\n"
                 "\n"
                 "This program monitors the system's idle percentage and reduces or raises the\n"
-                "CPUs\' clock speeds and voltages accordingly to minimize power consumption\n"
-                "when idle and maximize performance when needed.  This is the default.\n"
+                "CPU cores\' clock speeds accordingly to minimize power usage when idle and\n"
+                "maximize performance when needed. By default the program counts time used by\n"
+                "nice()d programs and time used waiting for IO as idle time.\n"
                 "\n"
-                "The program may also optionally be configured to reduce the CPUs\' clock\n"
-                "speeds if the temperature gets too high, NOT minimize their speeds if the\n"
-                "computer's AC adapter is disconnected or maximize their speeds when the AC\n"
-                "adapter is connected.\n"
+                "The program may also optionally be configured to reduce the CPU cores\' clock\n"
+                "speeds if the temperature gets too high or minimize their speeds if the\n"
+                "computer's AC adapter is disconnected.\n"
                 "\n"
-                "By default this program will manage every CPU found in the system.\n"
+                "By default this program will manage every CPU core found in the system.\n"
                 "\n"
                 "Usage: %s [Options]\n"
                 "\n"
@@ -709,21 +929,27 @@ main(int argc, char * argv[])
                 "            changes in tenths of a second (default is 20).\n"
                 "\n"
                 "        -p <fast up> <threshold>\n"
-                "            Sets the CPU idle percentage thresholds.  <fast up> is the idle\n"
+                "            Sets the CPU core idle percentage thresholds. <fast up> is the idle\n"
                 "            percentage below which a CPU will be set to the highest possible\n"
-                "            speed.  <threshold> is the idle percentage above which a CPU's\n"
+                "            speed. <threshold> is the idle percentage above which a CPU's\n"
                 "            speed will be decreased and below which a CPU's speed will be\n"
                 "            increased (defaults are 10 and 25).\n"
                 "\n"
                 "        -m <minimum speed>\n"
-                "            Sets the minimum speed in KHz below which a CPU will not be set.\n"
+                "            Sets the minimum speed in KHz below which a CPU core won't be set.\n"
                 "\n"
                 "        -M <maximum speed>\n"
-                "            Sets the maximum speed in KHz above which a CPU will not be set.\n"
+                "            Sets the maximum speed in KHz above which a CPU core won't be set.\n"
+                "\n"
+                "        -n\n"
+                "            Do not treat niced programs as idle time.\n"
+                "\n"
+                "        -w\n"
+                "            Do not treat time waiting for IO as idle time.\n"
                 "\n"
                 "        -t <temp file> <maxtemp>\n"
-                "            Sets the ACPI temperature file and the temperature at which CPUs\n"
-                "            will be set to minimum speed.\n"
+                "            Sets the ACPI temperature file and the temperature at which CPU\n"
+                "            cores will be set to minimum speed.\n"
                 "\n"
                 "        -T <interval>\n"
                 "            Sets the interval at which the temperature will be polled in\n"
@@ -732,7 +958,7 @@ main(int argc, char * argv[])
                 "\n"
                 "        -a <AC file>\n"
                 "            Sets the ACPI AC adapter state file and tells the program to set\n"
-                "            the CPUs to minimum speed when the AC adapter is disconnected.\n"
+                "            the CPU cores to minimum speed when the AC adapter is disconnected.\n"
                 "            (This is the default but is changeable by the \'-D\' option below).\n"
                 "\n"
                 "        -A <interval>\n"
@@ -751,25 +977,32 @@ main(int argc, char * argv[])
                 "        -r\n"
                 "            Restores previous speed on program exit.\n"
                 "\n"
-                "        -s <CPU>\n"
-                "            Manage only a single CPU.  <CPU> specifies the number of the CPU\n"
-                "            to manage and is in the range 0 to (n-1) where \'n\' is the number\n"
-                "            of CPUs in the system.  Without this option the program creates\n"
-                "            copies of itself to manage every CPU in the system.\n"
+                "        -S \"<CPU core 1> [[<CPU core 2>] ...]\"\n"
+                "            Manage only a single group of CPU cores.  All of the specified\n"
+                "            cores will controlled as a single group (locked to the same speed)\n"
+                "            and are in the range 0 to n-1 where \'n\' is the total number of CPU\n"
+                "            cores in the system.  Note that when specifying multiple cores the\n"
+                "            list must be enclosed in quotes.  Without this option the program\n"
+                "            creates copies of itself to manage every core of every CPU in the\n"
+                "            system and automatically determines core groups. If you are running\n"
+                "            on an old kernel and get an error message about not being able to\n"
+                "            open an \"affected_cpus\" file then you must run this program\n"
+                "            separately for each group of cores that must be controlled together\n"
+                "            (which probably means for each physical CPU) and use this option.\n"
                 "\n"
-                "    To have a CPU stay at the highest clock speed to maximize performance send\n"
-                "    the process controlling that CPU the SIGUSR1 signal.\n"
+                "    To have a CPU core stay at the highest clock speed to maximize performance\n"
+                "    send the process controlling that CPU core the SIGUSR1 signal.\n"
                  "\n"
-                "    To have a CPU stay at the lowest clock speed to maximize battery life send\n"
-                "    the process controlling that CPU the SIGUSR2 signal.\n"
+                "    To have a CPU core stay at the lowest clock speed to maximize battery life\n"
+                "    send the process controlling that CPU core the SIGUSR2 signal.\n"
                  "\n"
-                "    To resume having a CPU\'s clock speed dynamically scaled send the process\n"
-                "    controlling that CPU the SIGHUP signal.\n"
+                "    To resume having a CPU core's clock speed dynamically scaled send the\n"
+                "    process controlling that CPU core the SIGHUP signal.\n"
                  "\n"
                 "Author:\n"
-                "    Carl Thompson - cet [at] carlthompson.net  (copyright 2002 - 2005)\n"
+                "    %s\n"
                 "\n"
-                , NAME, VERSION, NAME, NAME
+                , NAME, VERSION, NAME, AUTHOR
             );
             exit(0);
         }
@@ -784,64 +1017,122 @@ main(int argc, char * argv[])
 //     child_action.sa_handler = SIG_IGN;
 //     sigaction(SIGCHLD, &child_action, 0);
 
-    // get number of CPUs
-    if (!num_cpus)
+    // get number of CPU cores
+    if (!num_cores)
     {
-        num_cpus = get_nprocs_conf();
+        num_cores = sysconf(_SC_NPROCESSORS_CONF);
+
 #ifdef DEBUG
-        fprintf(stderr, "%u CPU(s) detected.\n", num_cpus);
+        fprintf(stderr, "%u CPU core(s) detected.\n", num_cores);
 #endif
     }
 
-    saved_pids = (pid_t *)calloc(num_cpus, sizeof(pid_t));
-
-    // run in background if requested
-    if (daemonize)
-        daemon(0, 0);
-
-    // fork() a process to handle each CPU
-    for (unsigned i = 1; i < num_cpus; i++)
+    // if cpu cores to control were not specified by the -S option then figure
+    // out what cores to control by looking at the affected_cpus file in the
+    //  cpufreq dir for each core
+    if (!num_tied_cores)
     {
-        if ( !(saved_pids[i] = fork()) )
+        // iterate through all cpu cores in main process
+        for (unsigned i = 0, forked = 0; i < num_cores && !forked; i++)
         {
-            cpu = i;
-            break;
+            // does this core do cpufreq?
+            char cpufreq_dir[256];
+            snprintf(cpufreq_dir, sizeof cpufreq_dir, SYSFS_CPUFREQ_DIR, i);
+#ifdef DEBUG
+            if (fake_cpu)
+            {
+                snprintf(cpufreq_dir, sizeof cpufreq_dir, FAKE_CPUFREQ_DIR, i);
+            }
+#endif
+            if ( access(cpufreq_dir, F_OK) != 0 )
+            {
+                // this core does not have a cpufreq dir so doesn't do cpufreq
+#ifdef DEBUG
+                fprintf(
+                    stderr, "[core%u] WARNING: Skipping core because CPUFreq "
+                    "directory (%s) not found\n", i, cpufreq_dir
+                );
+#endif
+                continue;
+            }
+
+            // get list of affected cpu cores that this core belongs to
+            char acfn[256];
+            snprintf(acfn, sizeof acfn, SYSFS_AFFECTED_CPUS_FILE, i);
+#ifdef DEBUG
+            if (fake_cpu)
+            {
+                snprintf(acfn, sizeof acfn, FAKE_AFFECTED_CPUS_FILE, i);
+            }
+#endif
+            unsigned cores[MAX_TIED_CORES];
+            int n = read_values(acfn, cores, MAX_TIED_CORES);
+
+            // if we can't figure out the affected cores
+            if (n == 0)
+            {
+                die(
+                    false, "[core%u] Could not read affected cores from: %s",
+                    i, acfn
+                );
+            }
+
+            // if this cpu core is the master of a group of tied cores then
+            // fork() a process to handle this core group
+            if (cores[0] == i)
+            {
+#ifdef DEBUG
+                fprintf(
+                    stderr, "[core%u] This core is controlled by me.\n", i
+                );
+#endif
+                // if this is not the first cpu core then fork()
+                if ((i == 0) || (forked = !fork()))
+                {
+                    memcpy(tied_cpu_cores, cores, sizeof tied_cpu_cores);
+                    num_tied_cores = n;
+                }
+            }
+            else
+            {
+#ifdef DEBUG
+                fprintf(
+                    stderr, "[core%u] This core is controlled by core #%u\n",
+                    i, cores[0]
+                );
+#endif
+            }
         }
     }
 
-    // if possible, set the proccess title to a more descriptive version
-    if (num_cpus > 1)
+
+#ifdef DEBUG
+    fprintf(
+        stderr, "[core%u] Cores controlled by this core:",
+        tied_cpu_cores[0]
+    );
+    for (unsigned i = 0; i < num_tied_cores; i++)
+    {
+        fprintf(stderr, " %u", tied_cpu_cores[i]);
+    }
+    fprintf(stderr, "\n");
+#endif
+
+    if (num_tied_cores == 0)
     {
-        char tmp[32];
-        if ((size_t)snprintf(tmp, sizeof tmp, "%s#%u", NAME, cpu) <= strlen(argv[0]))
-            strcpy(argv[0], tmp);
+        die(false, "Could not find any CPUFreq controlled CPU cores to manage");
     }
 
     STAT_FILE = PROC_STAT_FILE;
-#ifdef WITH_PROC
-    struct utsname un;
-    uname(&un);
-    if (!strncmp(un.release, "2.4", 3))
-    {
-        MIN_SPEED_FILE = dup_cpu_str(PROC_MIN_SPEED_FILE);
-        MAX_SPEED_FILE = dup_cpu_str(PROC_MAX_SPEED_FILE);
-        CURRENT_SPEED_FILE = dup_cpu_str(PROC_CURRENT_SPEED_FILE);
-        GOVERNOR_FILE = PROC_GOVERNOR_FILE;
-        USERSPACE = PROC_USERSPACE;
-    }
-    else
-#endif
-    {
-        MIN_SPEED_FILE = dup_cpu_str(SYSFS_MIN_SPEED_FILE);
-        MAX_SPEED_FILE = dup_cpu_str(SYSFS_MAX_SPEED_FILE);
-        CURRENT_SPEED_FILE = dup_cpu_str(SYSFS_CURRENT_SPEED_FILE);
-        GOVERNOR_FILE = dup_cpu_str(SYSFS_GOVERNOR_FILE);
-        USERSPACE = SYSFS_USERSPACE;
-    }
+    MIN_SPEED_FILE = dup_cpu_str(SYSFS_MIN_SPEED_FILE);
+    MAX_SPEED_FILE = dup_cpu_str(SYSFS_MAX_SPEED_FILE);
+    CURRENT_SPEED_FILE = dup_cpu_str(SYSFS_CURRENT_SPEED_FILE);
+    GOVERNOR_FILE = dup_cpu_str(SYSFS_GOVERNOR_FILE);
+    USERSPACE = SYSFS_USERSPACE;
 #ifdef DEBUG
     if (fake_cpu)
     {
-         STAT_FILE = FAKE_STAT_FILE;
+        STAT_FILE = FAKE_STAT_FILE;
         MIN_SPEED_FILE = dup_cpu_str(FAKE_MIN_SPEED_FILE);
         MAX_SPEED_FILE = dup_cpu_str(FAKE_MAX_SPEED_FILE);
         CURRENT_SPEED_FILE = dup_cpu_str(FAKE_CURRENT_SPEED_FILE);
@@ -861,7 +1152,9 @@ main(int argc, char * argv[])
     write_line(GOVERNOR_FILE, "%s\n", USERSPACE);
 
     if (access(CURRENT_SPEED_FILE, W_OK) < 0)
+    {
         die(true, "Cannot write to speed control file: %s", CURRENT_SPEED_FILE);
+    }
 
     // set up signal handling
     struct sigaction signal_action;
@@ -929,6 +1222,13 @@ main(int argc, char * argv[])
     unsigned ac_interval_timeout = 0;
     unsigned next_timeout, d;
     timespec timeout;
+
+    // run in background if requested - CET - FIXME
+    if (daemonize)
+    {
+        daemon(0, 0);
+    }
+
     // main loop
     while (1)
     {
@@ -960,13 +1260,15 @@ main(int argc, char * argv[])
         }
 
         if (check_cpu || check_ac || check_therm)
+        {
             raise(SIGALRM);
+        }
 
         d = next_timeout - counter;
         timeout.tv_sec = d / 10;
         timeout.tv_nsec = (d % 10) * 100000000LU;
         while (nanosleep(&timeout, &timeout) == -1 && errno == EINTR)
-            ;
+        {} // loop just makes sure all of timeout has passed
 
         counter = next_timeout;
     }
@@ -975,4 +1277,4 @@ main(int argc, char * argv[])
     return 0;
 }
 
-/* $Id: $ */
+/* $Id: cpuspeed.cc 7 2007-02-06 01:20:52Z carl $ */

cpuspeed-1.2.1-no-affected_cpus-fallback.patch:

--- NEW FILE cpuspeed-1.2.1-no-affected_cpus-fallback.patch ---
--- cpuspeed-1.2.1/cpuspeed.cc~	2008-09-26 17:16:19.000000000 -0400
+++ cpuspeed-1.2.1/cpuspeed.cc	2008-09-26 17:16:38.000000000 -0400
@@ -158,6 +158,8 @@ unsigned last_step; // lowest speed step
 // which CPU cores are we controlling
 unsigned tied_cpu_cores[MAX_TIED_CORES];
 unsigned num_tied_cores = 0;
+unsigned cpu = 0;
+bool no_affected_cpus_attr = false;
 
 // display an error message and exit the program
 void
@@ -484,12 +486,16 @@ get_times(
     if (nice_counts_as_idle)
     {
         idle_time += nice_time;
+    } else {
+        user_time += nice_time;
     }
 
     // count IO wait time as idle time
     if (io_counts_as_idle)
     {
         idle_time += wait_time;
+    } else {
+        user_time += wait_time;
     }
 
     unsigned long total_time = user_time + system_time + idle_time;
@@ -710,6 +716,7 @@ unsigned num_cores = 0; // how many CPU 
 // restore  initial speed on program exit
 unsigned saved_speed = 0;
 char saved_governor[32];
+pid_t * saved_pids;
 
 void
 term_handler(int which)
@@ -720,6 +727,12 @@ term_handler(int which)
         write_line(GOVERNOR_FILE, "%s\n", saved_governor);
     }
 
+    if (cpu == 0 && no_affected_cpus_attr)
+    {
+        for (unsigned i = 1; i < num_cores; i++)
+            kill(saved_pids[i], which);
+    }
+
     raise(which);
 }
 
@@ -1032,9 +1045,11 @@ main(int argc, char * argv[])
     //  cpufreq dir for each core
     if (!num_tied_cores)
     {
+        fprintf(stderr, "No cores spec'd, trying to figure it out...\n");
         // iterate through all cpu cores in main process
         for (unsigned i = 0, forked = 0; i < num_cores && !forked; i++)
         {
+	    int n;
             // does this core do cpufreq?
             char cpufreq_dir[256];
             snprintf(cpufreq_dir, sizeof cpufreq_dir, SYSFS_CPUFREQ_DIR, i);
@@ -1066,7 +1081,14 @@ main(int argc, char * argv[])
             }
 #endif
             unsigned cores[MAX_TIED_CORES];
-            int n = read_values(acfn, cores, MAX_TIED_CORES);
+            if (access(acfn, F_OK) != 0)
+            {
+                // fall back to the old 1.2.x method of forking for each core
+                no_affected_cpus_attr = true;
+                n = 1;
+            }
+            else
+                n = read_values(acfn, cores, MAX_TIED_CORES);
 
             // if we can't figure out the affected cores
             if (n == 0)
@@ -1101,8 +1123,22 @@ main(int argc, char * argv[])
                     i, cores[0]
                 );
 #endif
+            if (no_affected_cpus_attr)
+                break;
             }
         }
+
+        if (no_affected_cpus_attr)
+        {
+            saved_pids = (pid_t *)calloc(num_cores, sizeof(pid_t));
+
+            // fork() a process to handle each core
+            for (unsigned i = 1; i < num_cores; i++)
+                if ( !(saved_pids[i] = fork())) {
+                    cpu = i;
+                    break;
+                }
+        }
     }
 
 


Index: cpuspeed.init
===================================================================
RCS file: /cvs/pkgs/rpms/cpuspeed/devel/cpuspeed.init,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- cpuspeed.init	13 Mar 2008 02:10:30 -0000	1.39
+++ cpuspeed.init	26 Sep 2008 21:23:31 -0000	1.40
@@ -88,7 +88,7 @@
   if [ -n "$MAX_SPEED" ]; then
     OPTS="$OPTS -M $MAX_SPEED"
   fi
-  if [ "$IGNORE_NICE" -eq 0 ]; then
+  if [ "$IGNORE_NICE" -eq 1 ]; then
     OPTS="$OPTS -n"
   fi
   daemon $prog -d $OPTS
@@ -135,14 +135,14 @@
           [ -d ${cpu0freqd} ] || /sbin/modprobe -r acpi-cpufreq 2> /dev/null
         else
           # No scaling. Just exit.
-          return 0
+          return 6
         fi
       fi
     fi
 
     # If we get this far with no driver, we must have no scaling.
     # We're doomed.
-    [ ! -f ${cpu0freqd}/scaling_driver ] && return 0
+    [ ! -f ${cpu0freqd}/scaling_driver ] && return 6
 
     # Okay, we have a driver, carry on...
     drv=`cat ${cpu0freqd}/scaling_driver`


Index: cpuspeed.spec
===================================================================
RCS file: /cvs/pkgs/rpms/cpuspeed/devel/cpuspeed.spec,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -r1.68 -r1.69
--- cpuspeed.spec	15 Jul 2008 19:03:36 -0000	1.68
+++ cpuspeed.spec	26 Sep 2008 21:23:31 -0000	1.69
@@ -1,7 +1,7 @@
 Summary:        CPU frequency adjusting daemon
 Name:           cpuspeed
 Version:        1.2.1
-Release:        8%{?dist}
+Release:        9%{?dist}
 Epoch:          1
 Group:          System Environment/Base
 License:        GPLv2+
@@ -17,14 +17,13 @@
 Requires(preun): /sbin/service
 
 BuildRequires:  automake util-linux groff gettext
-ExclusiveArch:	i386 x86_64 ppc ppc64 ia64 sparcv9 sparc64 
+ExclusiveArch:	i386 x86_64 ppc ppc64 ia64 sparcv9 sparc64
 Obsoletes:	kernel-utils
 
-Patch1:         warning.diff
-Patch2:         idlenice.diff
-Patch3:         cpuspeed-1.2.1-make.patch
-Patch4:         cpuspeed-1.2.1-make-gcc43-happy.patch
-Patch5:         cpuspeed-1.2.1-multicore-workaround.patch
+Patch1:         cpuspeed-1.2.1-make.patch
+Patch2:         cpuspeed-1.2.1-make-gcc43-happy.patch
+Patch3:         cpuspeed-1.2.1-multicore-support.patch
+Patch4:         cpuspeed-1.2.1-no-affected_cpus-fallback.patch
 
 %description
 cpuspeed is a daemon that dynamically changes the speed
@@ -38,14 +37,11 @@
 
 %prep
 %setup -q
-
 cp %{SOURCE1} .
-
-%patch1 -p1 -b .warn
-%patch2 -p1 -b .idle
-%patch3 -p1 -b .make
-%patch4 -p1 -b .gcc43
-%patch5 -p1 -b .multicore
+%patch1 -p1 -b .make
+%patch2 -p1 -b .gcc43
+%patch3 -p1 -b .mc
+%patch4 -p1 -b .ac
 
 %build
 rm -rf $RPM_BUILD_ROOT
@@ -89,6 +85,10 @@
 exit 0
 
 %changelog
+* Fri Sep 26 2008 Jarod Wilson <jarod at redhat.com> 1.2.1-9
+- backport proper multicore support for userspace governor
+  (cpuspeed daemon) case from v1.5 cpuspeed snapshot
+
 * Tue Jul 15 2008 Tom "spot" Callaway <tcallawa at redhat.com> 1.2.1-8
 - fix license tag
 
@@ -108,7 +108,7 @@
 * Wed Aug 29 2007 Jarod Wilson <jwilson at redhat.com> 1.2.1-3
 - Bump and rebuild, due to busted ppc32
 
-* Sat Jul 07 2007 Jarod Wilson <jwilson at redhat.com>
+* Sat Jul 07 2007 Jarod Wilson <jwilson at redhat.com> 1.2.1-2
 - Account for the cpuidle feature in rawhide kernels,
   slated for release in kernel 2.6.23 (#247352)
 
@@ -176,8 +176,8 @@
 - Don't start on xen kernels (freq scaling not supported)
 
 * Thu Dec 14 2006 Jarod Wilson <jwilson at redhat.com>
-- Set lock file for centrino/powernow-k8 so status 
-  indicates we do have scaling working 
+- Set lock file for centrino/powernow-k8 so status
+  indicates we do have scaling working
 - Fix up centrino/powernow-k8 stop function (#213999)
 
 * Wed Nov 29 2006 Jarod Wilson <jwilson at redhat.com>


--- cpuspeed-1.2.1-multicore-workaround.patch DELETED ---


--- cpuspeed.patch DELETED ---


--- idlenice.diff DELETED ---


--- warning.diff DELETED ---




More information about the fedora-extras-commits mailing list