aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2010-08-11 16:21:59 -0400
committerArjan van de Ven <arjan@linux.intel.com>2010-08-11 16:21:59 -0400
commit3b703844d9a56b3fa1054075b7de08bfc9ef1ca3 (patch)
tree5d358bcdb164fa4b28ac298463d7b59e2124098d /cpu
parent97f6c8c54b523a0ba238101dbf2935f6f70e6e77 (diff)
downloadpowertop-3b703844d9a56b3fa1054075b7de08bfc9ef1ca3.tar.gz
make sure time is passed through everything
Diffstat (limited to 'cpu')
-rw-r--r--cpu/abstract_cpu.cpp25
-rw-r--r--cpu/cpu.cpp30
-rw-r--r--cpu/cpu.h12
3 files changed, 56 insertions, 11 deletions
diff --git a/cpu/abstract_cpu.cpp b/cpu/abstract_cpu.cpp
index 8eb6d88..885fc4f 100644
--- a/cpu/abstract_cpu.cpp
+++ b/cpu/abstract_cpu.cpp
@@ -269,3 +269,28 @@ void abstract_cpu::update_pstate(uint64_t freq, const char *human_name, uint64_t
state->time_before += duration;
state->before_count += count;
}
+
+
+void abstract_cpu::calculate_freq(uint64_t time)
+{
+ uint64_t freq = 0;
+ bool is_idle = true;
+ unsigned int i;
+
+ /* calculate the maximum frequency of all children */
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ uint64_t f = 0;
+ if (!children[i]->idle) {
+ f = children[i]->current_frequency;
+ is_idle = false;
+ }
+ if (f > freq)
+ f = freq;
+ }
+
+ current_frequency = freq;
+ idle = is_idle;
+ if (parent)
+ parent->calculate_freq(time);
+} \ No newline at end of file
diff --git a/cpu/cpu.cpp b/cpu/cpu.cpp
index f3b8f67..7edd849 100644
--- a/cpu/cpu.cpp
+++ b/cpu/cpu.cpp
@@ -18,7 +18,7 @@ static class perf_bundle * perf_events;
class perf_power_bundle: public perf_bundle
{
- virtual void handle_trace_point(int type, void *trace, int cpu);
+ virtual void handle_trace_point(int type, void *trace, int cpu, uint64_t time);
};
@@ -104,6 +104,7 @@ static void handle_one_cpu(unsigned int number, char *vendor, int family, int mo
}
package = system_level.children[package_number];
+ package->parent = &system_level;
if (package->children.size() <= core_number)
package->children.resize(core_number + 1);
@@ -114,6 +115,7 @@ static void handle_one_cpu(unsigned int number, char *vendor, int family, int mo
}
core = package->children[core_number];
+ core->parent = package;
if (core->children.size() <= number)
core->children.resize(number + 1, NULL);
@@ -122,7 +124,8 @@ static void handle_one_cpu(unsigned int number, char *vendor, int family, int mo
core->childcount++;
}
- cpu = core->children[number];
+ cpu = core->children[number];
+ cpu->parent = core;
if (number >= all_cpus.size())
all_cpus.resize(number + 1, NULL);
@@ -405,25 +408,30 @@ struct power_entry {
};
-void perf_power_bundle::handle_trace_point(int type, void *trace, int cpu)
+void perf_power_bundle::handle_trace_point(int type, void *trace, int cpunr, uint64_t time)
{
const char *event_name;
+ class abstract_cpu *cpu;
if (type >= (int)event_names.size())
return;
event_name = event_names[type];
- if (strcmp(event_name, "power:power_frequency")==0) {
- struct power_entry *pe = (struct power_entry *)trace;
- printf("CPU %i new frequency is %lli\n", cpu, pe->value);
+ if (cpunr >= (int)all_cpus.size()) {
+ cout << "INVALID cpu nr in handle_trace_point\n";
+ return;
}
- if (strcmp(event_name, "power:power_start")==0) {
+
+ cpu = all_cpus[cpunr];
+
+ if (strcmp(event_name, "power:power_frequency")==0) {
struct power_entry *pe = (struct power_entry *)trace;
- printf("CPU %i new CSTATE is %lli\n", cpu, pe->value);
- }
- if (strcmp(event_name, "power:power_end")==0) {
- printf("CPU %i is no longer idle\n", cpu);
+ cpu->change_freq(time, pe->value);
}
+ if (strcmp(event_name, "power:power_start")==0)
+ cpu->go_idle(time);
+ if (strcmp(event_name, "power:power_end")==0)
+ cpu->go_unidle(time);
}
void process_cpu_data(void)
diff --git a/cpu/cpu.h b/cpu/cpu.h
index 5bc2168..8ad908a 100644
--- a/cpu/cpu.h
+++ b/cpu/cpu.h
@@ -55,10 +55,16 @@ protected:
uint64_t max_minus_one_frequency;
public:
int childcount;
+ bool idle;
+ int current_frequency;
+
vector<class abstract_cpu *> children;
vector<struct idle_state *> cstates;
vector<struct frequency *> pstates;
+ class abstract_cpu *parent;
+
+
void set_number(int number, int cpu) {this->number = number; this->first_cpu = cpu;};
virtual void measurement_start(void);
@@ -89,6 +95,12 @@ public:
virtual char * fill_pstate_name(int line_nr, char *buffer) { return buffer;};
virtual int has_pstate_level(int level);
+ /* Frequency micro accounting methods */
+ virtual void calculate_freq(uint64_t time);
+ virtual void go_idle(uint64_t time) { idle = true; if (parent) parent->calculate_freq(time);};
+ virtual void go_unidle(uint64_t time) { idle = false; if (parent) parent->calculate_freq(time);};;
+ virtual void change_freq(uint64_t time, int freq) { current_frequency = freq; if (parent) parent->calculate_freq(time);};
+
};
extern vector<class abstract_cpu *> all_cpus;