diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2010-08-12 08:55:13 -0400 |
---|---|---|
committer | Arjan van de Ven <arjan@linux.intel.com> | 2010-08-12 08:55:13 -0400 |
commit | 9852f6c8f1ea5881abc238645e9766bb6790c00e (patch) | |
tree | 31ced7fb3d5c5ed99d10755169acfa4146661b1c /cpu | |
parent | 885d8c2f998c85c2a8a70dd12eb838b6f4d1da18 (diff) | |
download | powertop-9852f6c8f1ea5881abc238645e9766bb6790c00e.tar.gz |
do the cpu level as well
still need to do the backcounting
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/intel_cpus.cpp | 151 | ||||
-rw-r--r-- | cpu/intel_cpus.h | 9 |
2 files changed, 155 insertions, 5 deletions
diff --git a/cpu/intel_cpus.cpp b/cpu/intel_cpus.cpp index 66f6a15..2e8cee6 100644 --- a/cpu/intel_cpus.cpp +++ b/cpu/intel_cpus.cpp @@ -70,7 +70,7 @@ void nhm_core::measurement_start(void) } account_freq(0, 1); - gettimeofday(&stamp_before, NULL); +// gettimeofday(&stamp_before, NULL); } void nhm_core::measurement_end(void) @@ -198,8 +198,8 @@ void nhm_core::calculate_freq(uint64_t time) time_delta = 1; fr = current_frequency; -// if (idle) -// fr = 0; + if (idle) + fr = 0; account_freq(fr, time_delta); @@ -312,13 +312,42 @@ void nhm_package::measurement_end(void) void nhm_cpu::measurement_start(void) { + unsigned int i; + ifstream file; + char filename[4096]; + cpu_linux::measurement_start(); + last_stamp = 0; + + for (i = 0; i < children.size(); i++) + if (children[i]) + children[i]->wiggle(); + aperf_before = get_msr(number, MSR_APERF); mperf_before = get_msr(number, MSR_MPERF); tsc_before = get_msr(number, MSR_TSC); insert_cstate("active", "C0 active", 0, aperf_before, 1); + + sprintf(filename, "/sys/devices/system/cpu/cpu%i/cpufreq/stats/time_in_state", first_cpu); + + file.open(filename, ios::in); + + if (file) { + char line[1024]; + + while (file) { + uint64_t f; + file.getline(line, 1024); + f = strtoull(line, NULL, 10); + account_freq(f, 1); + } + file.close(); + } + account_freq(0, 1); + +// gettimeofday(&stamp_before, NULL); } void nhm_cpu::measurement_end(void) @@ -367,13 +396,27 @@ char * nhm_cpu::fill_pstate_name(int line_nr, char *buffer) char * nhm_cpu::fill_pstate_line(int line_nr, char *buffer) { + if (total_stamp ==0) { + unsigned int i; + for (i = 0; i < pstates.size(); i++) + total_stamp += pstates[i]->time_after; + if (total_stamp == 0) + total_stamp = 1; + } + if (line_nr == LEVEL_C0) { double F; F = 1.0 * (tsc_after - tsc_before) * (aperf_after - aperf_before) / (mperf_after - mperf_before) / time_factor * 1000; sprintf(buffer, "%s", hz_to_human(F, buffer, 1)); return buffer; } - return cpu_linux::fill_pstate_line(line_nr, buffer); + if (line_nr >= (int)pstates.size() || line_nr < 0) + return buffer; + + + sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp)); + return buffer; + } @@ -382,4 +425,102 @@ int nhm_cpu::has_pstate_level(int level) if (level == LEVEL_C0) return 1; return cpu_linux::has_pstate_level(level); -}
\ No newline at end of file +} + +void nhm_cpu::account_freq(uint64_t freq, uint64_t duration) +{ + struct frequency *state = NULL; + unsigned int i; + + for (i = 0; i < pstates.size(); i++) { + if (freq == pstates[i]->freq) { + state = pstates[i]; + break; + } + } + + if (!state) { + state = new struct frequency; + + if (!state) + return; + + memset(state, 0, sizeof(*state)); + + pstates.push_back(state); + + state->freq = freq; + sprintf(state->human_name, "%s", hz_to_human(freq, state->human_name)); + if (freq == 0) + strcpy(state->human_name, "Idle"); + state->after_count = 1; + } + + + state->time_after += duration; + +} + +void nhm_cpu::change_freq(uint64_t time, int frequency) +{ + uint64_t time_delta, fr; + + if (last_stamp) + time_delta = time - last_stamp; + else + time_delta = 1; + + fr = current_frequency; + if (idle) + fr = 0; + + account_freq(fr, time_delta); + + current_frequency = frequency; + last_stamp = time; + if (parent) + parent->calculate_freq(time); +} + +void nhm_cpu::go_idle(uint64_t time) +{ + uint64_t time_delta, fr; + + if (last_stamp) + time_delta = time - last_stamp; + else + time_delta = 1; + + fr = current_frequency; + if (idle) + fr = 0; + + account_freq(fr, time_delta); + + idle = true; + last_stamp = time; + if (parent) + parent->calculate_freq(time); +} + + +void nhm_cpu::go_unidle(uint64_t time) +{ + uint64_t time_delta, fr; + + if (last_stamp) + time_delta = time - last_stamp; + else + time_delta = 1; + + fr = current_frequency; + if (idle) + fr = 0; + + account_freq(fr, time_delta); + + idle = false; + last_stamp = time; + if (parent) + parent->calculate_freq(time); +} diff --git a/cpu/intel_cpus.h b/cpu/intel_cpus.h index f337538..c4892db 100644 --- a/cpu/intel_cpus.h +++ b/cpu/intel_cpus.h @@ -57,6 +57,11 @@ private: uint64_t mperf_before; uint64_t mperf_after; uint64_t tsc_before, tsc_after; + + uint64_t last_stamp; + uint64_t total_stamp; + + void account_freq(uint64_t frequency, uint64_t duration); public: virtual void measurement_start(void); virtual void measurement_end(void); @@ -66,6 +71,10 @@ public: virtual char * fill_pstate_line(int line_nr, char *buffer); virtual int has_pstate_level(int level); + virtual void change_freq(uint64_t time, int freq); + virtual void go_idle(uint64_t time); + virtual void go_unidle(uint64_t time); + }; class atom_package: public cpu_package |