Intel hyperthreaded cores does not exactly behave like if it was 2 real cores.
-       Actual HW cstate is roughly minimal cstate of the 2 threads.
As most of the resources are shared, HW resources are only really powered
down when both threads are idle.
-       Interrupts always wakes up the 2 threads. i.e. terminate the 2 mwait.
So in case of an hyperthreaded core a wakeup event is affecting power only when
both the threads are asleep. A wakeup event that occurs when one of
the thread is active should not be considered as a wakeup event.

In case of hyperthreaded cores the thread ids that execute on the same core
will be reported in the 
sys/devices/system/cpu/cpu%i/topology/thread_siblings_list.
A table is initially created with this thread sibling information corresponding 
to
a cpu. When powertop gets a power_end event on a thread the thread_sibling table
is looked up to identify the siblings of the cpu and each sibling is checked it
has a wakeup pending. If any one sibling does not have a wakeup event pending
the power end event is ignored.
---
 cpu/cpu.cpp            |   28 ++++++++++++++++++++++++++++
 cpu/cpu.h              |    8 ++++++++
 process/do_process.cpp |   25 +++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/cpu/cpu.cpp b/cpu/cpu.cpp
index 39f00e7..94f4052 100644
--- a/cpu/cpu.cpp
+++ b/cpu/cpu.cpp
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ncurses.h>
+#include <sstream>
 
 #include "cpu.h"
 #include "cpudevice.h"
@@ -38,12 +39,15 @@
 #include "../display.h"
 #include "../html.h"
 
+using namespace std;
+
 static class abstract_cpu system_level;
 
 vector<class abstract_cpu *> all_cpus;
 
 static class perf_bundle * perf_events;
 
+vector < struct thread_sibling_info * > thread_sibling_table;
 
 
 class perf_power_bundle: public perf_bundle
@@ -156,6 +160,7 @@ static void handle_one_cpu(unsigned int number, char 
*vendor, int family, int mo
        unsigned int package_number = 0;
        unsigned int core_number = 0;
        class abstract_cpu *package, *core, *cpu;
+       vector <unsigned int> thread_siblings;
 
        sprintf(filename, "/sys/devices/system/cpu/cpu%i/topology/core_id", 
number);
        file.open(filename, ios::in);
@@ -171,6 +176,29 @@ static void handle_one_cpu(unsigned int number, char 
*vendor, int family, int mo
                file.close();
        }
 
+       sprintf(filename, 
"/sys/devices/system/cpu/cpu%i/topology/thread_siblings_list", number);
+       file.open(filename, ios::in);
+       if (file) {
+               string line;
+               getline(file,line);
+               istringstream linestream(line);
+               string item;
+               struct thread_sibling_info *info;
+
+               while (getline (linestream, item, '-')){
+                       thread_siblings.push_back(atoi(item.c_str()));          
+               }
+
+               if (thread_siblings.size() > 1){
+                       info = new struct thread_sibling_info;
+                       info->cpunum = number;
+                       info->thread_siblings = thread_siblings;
+                       thread_sibling_table.push_back(info);
+               }       
+               
+               file.close();
+
+       }
 
        if (system_level.children.size() <= package_number)
                system_level.children.resize(package_number + 1, NULL);
diff --git a/cpu/cpu.h b/cpu/cpu.h
index 34dcac4..398216b 100644
--- a/cpu/cpu.h
+++ b/cpu/cpu.h
@@ -39,6 +39,14 @@ class abstract_cpu;
 #define LEVEL_C0 -1
 #define LEVEL_HEADER -2
 
+
+struct thread_sibling_info {
+       unsigned int cpunum;
+       vector <unsigned int> thread_siblings;
+};
+
+extern vector < struct thread_sibling_info * > thread_sibling_table;
+
 struct idle_state {
        char linux_name[16]; /* state0 etc.. cpuidle name */
        char human_name[32];
diff --git a/process/do_process.cpp b/process/do_process.cpp
index 2ca4b10..7bd3601 100644
--- a/process/do_process.cpp
+++ b/process/do_process.cpp
@@ -44,6 +44,7 @@
 #include "../parameters/parameters.h"
 #include "../display.h"
 #include "../measurement/measurement.h"
+#include "../cpu/cpu.h"
 
 static  class perf_bundle * perf_events;
 
@@ -147,6 +148,28 @@ static void change_blame(unsigned int cpu, class 
power_consumer *consumer, int l
        cpu_level[cpu] = level;
 }
 
+static bool sibling_wakeup_pending(unsigned int cpu)
+{
+       unsigned int i,j;
+       struct thread_sibling_info *info;
+       bool wakeup_pending = TRUE;
+
+       for (i = 0; i < thread_sibling_table.size(); i++) {
+               info = thread_sibling_table[i];
+               if (cpu != info->cpunum)
+                       continue;
+
+               for (j = 0; j < info->thread_siblings.size(); j++) {
+                       if (!get_wakeup_pending(info->thread_siblings[j])){
+                               wakeup_pending = FALSE;
+                               break;
+                       }
+               }
+       }
+       
+       return wakeup_pending;
+}
+
 static void consume_blame(unsigned int cpu)
 {
        if (!get_wakeup_pending(cpu))
@@ -157,6 +180,8 @@ static void consume_blame(unsigned int cpu)
                return;
        if (!cpu_blame[cpu])
                return;
+       if (!sibling_wakeup_pending(cpu))
+               return;
 
        cpu_blame[cpu]->wake_ups++;
        cpu_blame[cpu] = NULL;
-- 
1.7.0.4

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

_______________________________________________
Power mailing list
[email protected]
https://bughost.org/mailman/listinfo/power

Reply via email to