Thomas Renninger wrote:

> Go ahead.
> I like to have a look at the code, but I will search for the commit...

I'll attach it.

I commented out getCPULoad and getCPULoadConsiderNice, only
getCPULoadSMP is still there.
Since we always casted it to int, i made it int (not much use in having
cpuload percentage as double anyway :-).

This function now has two different purposes:
- call it with cpu==-2 to calculate the cpuload array for all cpus at
  once
- call it with cpu==cpunumber to retrieve the cpuload value from the
  array
- special case: cpu==-1 => overall cpu load (the "^cpu ..." line from
  /proc/stat).

The idea is, that getCPULoadSMP(-2) is called from a regular glib timer,
every 333ms or something like that.
adjustSpeeds and friends call it per core / cpu and do not have to open
/proc/stat but just "return cpuload[cpu]" which should decrease the
overhead.
The "are we idle for more tha XXX seconds?"-Code can call
getCPULoadSMP(-1) to get the overall system load to decide on
processor.idle and processor.busy events.

Maybe we should make two functions, one for calculating the load array
and one for retrieving the values, but this can be subjecto of an
additional cleanup in the future.

> Yes, code is duplicated because of historical reasons. SMP support was 
> requested 
> and I did not want to break library API and remove any functions.

I know, but some day we need to start to clean up :-)

> Maybe considering siblings (Hyperthreading/Dualcore, could be implemented 
> down 
> there and be cached in some kind of CPU core/socket static array?).

I am at least caching all the cpuload values from /proc/stat in a
per-cpu (cpu as /proc/stat sees it, regardless of ht / dualcore / smp)
static array.

> Just an idea, currently all is done in higher C++ functions, maybe this is not
> necessary.
> 
> Or can we even use some cpufreq-utils functions for that? Sorry, I didn't 
> have a 
>   look at that package for a longer time...

I looked at them and unfortunately IMO they fit not very well into our
(mostly c++) code.

Note that there is at least one bug in my code, sometimes my machine
"hangs" at full speed until i switch it back down manually, so there is
still something to clean out :-)
-- 
Stefan Seyfried                  \ "I didn't want to write for pay. I
QA / R&D Team Mobile Devices      \ wanted to be paid for what I write."
SUSE LINUX Products GmbH, Nürnberg \                    -- Leonard Cohen
Index: daemon/pm_interface.cpp
===================================================================
RCS file: /cvsroot/powersave/powersave/daemon/pm_interface.cpp,v
retrieving revision 1.9
diff -u -p -r1.9 pm_interface.cpp
--- daemon/pm_interface.cpp     28 Sep 2005 20:05:35 -0000      1.9
+++ daemon/pm_interface.cpp     2 Oct 2005 21:19:29 -0000
@@ -385,14 +385,20 @@ int PM_Interface::updateBatteryState()
 
 int PM_Interface::updateCPUState()
 {
+printf("%s\n",__FUNCTION__);
        int cpu_load;
        // get CPU load, just cast it, accuracy not important
-       cpu_load = 
(int)getCPULoadConsiderNice(_config->current_scheme->CONSIDER_NICE);
+       // use only cpu0, this is not correct, but the same as we always did.
+       cpu_load = (int)getCPULoadSMP(_config->current_scheme->CONSIDER_NICE, 
-2);
+       cpu_load = (int)getCPULoadSMP(_config->current_scheme->CONSIDER_NICE, 
-1);
        if (cpu_load == -1) {
                pDebug(DBG_ERR, "Could not evalute cpu load (-1)");
                return -1;
        } else if (cpu_load == -2) {
                pDebug(DBG_DIAG, "/proc/stat not updated yet, CPU load could 
not be evaluated");
+               return -1;
+       } else if (cpu_load < 0) {
+               pDebug(DBG_DIAG, "strange error from getCPULoadSMP: %d", 
cpu_load);
                return -1;
        }
 
Index: daemon/pm_interface.h
===================================================================
RCS file: /cvsroot/powersave/powersave/daemon/pm_interface.h,v
retrieving revision 1.3
diff -u -p -r1.3 pm_interface.h
--- daemon/pm_interface.h       27 Sep 2005 12:01:36 -0000      1.3
+++ daemon/pm_interface.h       2 Oct 2005 21:19:30 -0000
@@ -336,6 +336,9 @@ protected:
        /** @brief defines whether sleep was triggered before */
        static bool _sleep_triggered;
 
+       /** @brief stores the overall CPU load */
+       static double _cpu_load;
+
 private:
        /** @brief handles a message on the manager interface
         * @param msg the dbus message received
Index: libpower/powerlib.h
===================================================================
RCS file: /cvsroot/powersave/powersave/libpower/powerlib.h,v
retrieving revision 1.20
diff -u -p -r1.20 powerlib.h
--- libpower/powerlib.h 15 Sep 2005 11:34:08 -0000      1.20
+++ libpower/powerlib.h 2 Oct 2005 21:19:31 -0000
@@ -333,9 +333,11 @@ extern "C" {
        /* of the first time you invoke this function, because */
        /* it will be the total idleness of cpu since the machine */
        /* has been powered on */
-       double getCPULoad(void);
-       double getCPULoadConsiderNice(const int nice);
-       double getCPULoadSMP(const int consider_nice, const int cpu);
+       /* call with cpu=-2 to calculate the array of CPU loads */
+       /* call with cpu=-1 to get the overall CPU load of a SMP machine */
+//     double getCPULoad(void);
+//     double getCPULoadConsiderNice(const int nice);
+       int getCPULoadSMP(const int consider_nice, const int cpu);
        void freeCPULoadSMPCalls(void);
        int getCPUCount(void);
        /******************************************************************/
Index: libpower/processor.c
===================================================================
RCS file: /cvsroot/powersave/powersave/libpower/processor.c,v
retrieving revision 1.13
diff -u -p -r1.13 processor.c
--- libpower/processor.c        28 Sep 2005 17:08:26 -0000      1.13
+++ libpower/processor.c        2 Oct 2005 21:19:31 -0000
@@ -23,6 +23,7 @@
    -1 general error
 */
 static unsigned long *ps_last_total_time = NULL, *ps_last_working_time = NULL;
+static int *ps_cpuload = NULL;
 static int cpuCount = -1;
 
 int getThrottlingInfo(int *states, int *current)
@@ -290,6 +291,10 @@ float getRealProcessorSpeed()
 #endif
 }
 
+/***************************************************************************/
+/************************************* commented out ***********************/
+/***************************************************************************/
+#if 0
 /* This function exists for compatibility */
 double getCPULoad()
 {
@@ -378,8 +383,12 @@ double getCPULoadConsiderNice(int consid
        else
                return -1;
 }
+#endif
+/***************************************************************************/
+/************************************* commented out ***********************/
+/***************************************************************************/
 
-double getCPULoadSMP(const int consider_nice, const int cpu)
+int getCPULoadSMP(const int consider_nice, const int cpu)
 {
 
        unsigned long total_elapsed, working_elapsed;
@@ -390,9 +399,9 @@ double getCPULoadSMP(const int consider_
        char cpuString[7];
        FILE *fp;
 
-       if (cpu < 0 || cpu > MAX_SUPPORTED_CPUS) {
+       if (cpu < -2 || cpu > MAX_SUPPORTED_CPUS) {
                errno = EINVAL;
-               return -10.0;
+               return -10;
        }
 
        if (cpuCount == -1) {
@@ -401,8 +410,9 @@ double getCPULoadSMP(const int consider_
                        errno = ENODEV;
                        return -20;
                }
-               ps_last_total_time = (unsigned long *)calloc(cpuCount, 
sizeof(unsigned long));
-               ps_last_working_time = (unsigned long *)calloc(cpuCount, 
sizeof(unsigned long));
+               ps_last_total_time = (unsigned long *)calloc(cpuCount + 1, 
sizeof(unsigned long));
+               ps_last_working_time = (unsigned long *)calloc(cpuCount + 1, 
sizeof(unsigned long));
+               ps_cpuload = (int *)calloc(cpuCount + 1, sizeof(int));
                /*              for (x=0; x < cpuCount; x++){
                   ps_last_total_time[x] = (unsigned long*) 
malloc(sizeof(unsigned long));
                   ps_last_working_time[x] = (unsigned long*) 
malloc(sizeof(unsigned long));
@@ -412,77 +422,83 @@ double getCPULoadSMP(const int consider_
                 */
        }
 
-       /* just to be sure we get no segfault. Should I check array as well? 
-          Do I need a check at all? */
-       if (ps_last_total_time == NULL || ps_last_working_time == NULL) {
-               errno = EFAULT;
-               return -40;
-       }
-
-       if (cpu > cpuCount) {
-               errno = ENODEV;
-               return -30;
-       }
-
-       sprintf(cpuString, "cpu%d", cpu);
+       if (cpu >= -1){
+               /* just to be sure we get no segfault. Should I check array as 
well? 
+                  Do I need a check at all? */
+               if (ps_last_total_time == NULL || ps_last_working_time == NULL 
||
+                   ps_cpuload == NULL) {
+                       errno = EFAULT;
+                       return -40;
+               }
 
-       /*      pDebug(DBG_INFO, "Before calculation: last_total_time: %d, 
last_idle_time: %d\n", */
-       /*      last_total_time, last_working_time); */
+               if (cpu >= cpuCount) {
+                       errno = ENODEV;
+                       return -30;
+               }
 
-       if ((fp = fopen(PROC_STAT_FILE, "r")) == NULL) {
-               /* let errno be set for higher applications... */
-               pDebug(DBG_DIAG, "Could not open %s: %s", PROC_STAT_FILE, 
strerror(errno));
-               return -1;
+               return ps_cpuload[cpu + 1];
        }
+       else
+       {       // cpu==-2, since everything else is already checked out.
+               if ((fp = fopen(PROC_STAT_FILE, "r")) == NULL) {
+                       /* let errno be set for higher applications... */
+                       pDebug(DBG_DIAG, "Could not open %s: %s", 
PROC_STAT_FILE, strerror(errno));
+                       return -1;
+               }
 
-       /* search for cpu line ... */
-       /* is the "cpu " string always at the beginning? -> Expect yes, but had 
*/
-       /* no look in the kernel */
+               sprintf(cpuString, "cpu ");
+               // if cpuCount == 1, we do not need to evaluate "overall" and 
"per-cpu" load
+               for (int i=0; i <= cpuCount - (cpuCount == 1); i++) {
+                       if (fgets(line,255,fp) == NULL) {
+                               pDebug(DBG_DIAG, "%s too short (%s)", 
PROC_STAT_FILE, cpuString);
+                               fclose(fp);
+                               return -1;
+                       }
+                       if (memcmp(line, cpuString, 4)) {
+                               pDebug(DBG_DIAG, "no '%s' string in %s line 
%d", cpuString, PROC_STAT_FILE, i);
+                               fclose(fp);
+                               return -1;
+                       }
+                       iowait_time = 0;        /* initialized, since it is 
simply not there in 2.4 */
+                       scan_ret = sscanf(line, "%s %lu %lu %lu %lu %lu", what, 
&user_time, &nice_time,
+                                 &system_time, &idle_time, &iowait_time);
+                       if (scan_ret < 5) {
+                               pDebug(DBG_DIAG, "only %d values in %s. Please 
report.", scan_ret, PROC_STAT_FILE);
+                               fclose(fp);
+                               return -1;
+                       }
+       
+                       unsigned long working_time;
+                       if (consider_nice) {
+                               working_time = user_time + system_time + 
nice_time;
+                               idle_time += iowait_time;
+                       } else {
+                               working_time = user_time + system_time;
+                               idle_time += (nice_time + iowait_time);
+                       }
+                       total_time = working_time + idle_time;
+                       total_elapsed = total_time - ps_last_total_time[i];
+                       working_elapsed = working_time - 
ps_last_working_time[i];
+                       ps_last_working_time[i] = working_time;
+                       ps_last_total_time[i] = total_time;
+                       
+                       if (!total_elapsed) {
+                               if (!i) { // not once per CPU, only once per 
check.
+                                       pDebug(DBG_DIAG, "%s not updated yet, 
poll slower.", PROC_STAT_FILE);
+                               }
+                       } else {
+                               // if (working_elapsed*100) gets too big for a 
long, we are in trouble anyway.
+                               ps_cpuload[i] = working_elapsed * 100 / 
total_elapsed;
+                       }
+                       sprintf(cpuString, "cpu%d", i);
+               }
+               if (cpuCount == 1) // shortcut for UP systems.
+                       ps_cpuload[1] = ps_cpuload[0];
 
-       /* what about multi processor systems? -> not supported at the moment */
-       while (fgets(line, 255, fp) != NULL) {
-               if (!memcmp(line, cpuString, 4))
-                       break;
-       }
-       if (memcmp(line, cpuString, 4)) {
-               pDebug(DBG_DIAG, "no '%s' string in %s", cpuString, 
PROC_STAT_FILE);
                fclose(fp);
-               return -1;
        }
-       iowait_time = 0;        /* initialized, since it is simply not there in 
2.4 */
-       scan_ret = sscanf(line, "%s %lu %lu %lu %lu %lu", what, &user_time, 
&nice_time,
-                         &system_time, &idle_time, &iowait_time);
-       fclose(fp);
-       if (scan_ret < 5) {
-               pDebug(DBG_DIAG, "only %d values in %s. Please report.", 
scan_ret, PROC_STAT_FILE);
-               return -1;
-       }
-
-       if (consider_nice) {
-               idle_time += iowait_time;
-               total_time = nice_time + user_time + system_time + idle_time;
-       } else {
-               idle_time += (nice_time + iowait_time);
-               total_time = user_time + system_time + idle_time;
-       }
-       total_elapsed = total_time - ps_last_total_time[cpu];
-       ps_last_total_time[cpu] = total_time;
-       if (consider_nice) {
-               working_elapsed = (user_time + system_time + nice_time) - 
ps_last_working_time[cpu];
-               ps_last_working_time[cpu] = user_time + system_time + nice_time;
-       } else {
-               working_elapsed = (user_time + system_time) - 
ps_last_working_time[cpu];
-               ps_last_working_time[cpu] = user_time + system_time;
-       }
-       if (!total_elapsed) {
-               pDebug(DBG_DIAG, "%s not updated yet, poll slower.", 
PROC_STAT_FILE);
-               return -2;
-       }
-
-       if (total_time > 0)
-               return (double)working_elapsed / (double)total_elapsed *100.0;
-       else
-               return -1;
+               
+       return 0;
 }
 
 int getCPUCount()
@@ -521,5 +537,6 @@ void freeCPULoadSMPCalls()
        if (cpuCount != -1) {
                free(ps_last_working_time);
                free(ps_last_total_time);
+               free(ps_cpuload);
        }
 }
_______________________________________________
powersave-devel mailing list
[email protected]
http://forge.novell.com/mailman/listinfo/powersave-devel

Reply via email to