>From kernel version 2.6.41 the power_start, power_end and power_frequency power traces will be replaced with cpu_idle and cpu_frequency power traces. Refer kernel documentation events-power.txt for details. This patch enables the use of new power traces and will fall back to old traces if new traces are not avaialable
Signed-off-by: John Mathew <john.mat...@intel.com> --- cpu/cpu.cpp | 24 ++++++++++++++++++++---- perf/perf_bundle.cpp | 5 ++++- perf/perf_bundle.h | 2 +- process/do_process.cpp | 13 +++++++++++-- process/process.h | 4 ++++ 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/cpu/cpu.cpp b/cpu/cpu.cpp index 563aa30..13d3cc2 100644 --- a/cpu/cpu.cpp +++ b/cpu/cpu.cpp @@ -32,6 +32,7 @@ #include "cpu.h" #include "cpudevice.h" #include "../parameters/parameters.h" +#include "../process/process.h" #include "../perf/perf_bundle.h" #include "../lib.h" @@ -277,10 +278,13 @@ void enumerate_cpus(void) perf_events = new perf_power_bundle(); - perf_events->add_event("power:power_frequency"); - perf_events->add_event("power:power_start"); - perf_events->add_event("power:power_end"); - + if (!perf_events->add_event("power:cpu_idle")){ + perf_events->add_event("power:power_start"); + perf_events->add_event("power:power_end"); + } + if (!perf_events->add_event("power:cpu_frequency")) + perf_events->add_event("power:power_frequency"); + } void start_cpu_measurement(void) @@ -955,6 +959,18 @@ void perf_power_bundle::handle_trace_point(int type, void *trace, int cpunr, uin system_level.children[i]->validate(); #endif + + if (strcmp(event_name, "power:cpu_frequency")==0) { + struct cpuidle_entry *pe = (struct cpuidle_entry *)trace; + cpu->change_freq(time, pe->state); + } + if (strcmp(event_name, "power:cpu_idle")==0) { + struct cpuidle_entry *ce = (struct cpuidle_entry *)trace; + if (ce->state == 4294967295) + cpu->go_unidle(time); + else + cpu->go_idle(time); + } if (strcmp(event_name, "power:power_frequency")==0) { struct power_entry *pe = (struct power_entry *)trace; cpu->change_freq(time, pe->value); diff --git a/perf/perf_bundle.cpp b/perf/perf_bundle.cpp index 2276c3a..5c9a49d 100644 --- a/perf/perf_bundle.cpp +++ b/perf/perf_bundle.cpp @@ -85,9 +85,10 @@ void perf_bundle::release(void) } -void perf_bundle::add_event(const char *event_name) +bool perf_bundle::add_event(const char *event_name) { unsigned int i; + int event_added = false; class perf_event *ev; for (i = 0; i < all_cpus.size(); i++) { @@ -105,10 +106,12 @@ void perf_bundle::add_event(const char *event_name) event_names[ev->trace_type] = strdup(event_name); events.push_back(ev); + event_added = true; } else { delete ev; } } + return event_added; } void perf_bundle::start(void) diff --git a/perf/perf_bundle.h b/perf/perf_bundle.h index 9e46cb2..021d112 100644 --- a/perf/perf_bundle.h +++ b/perf/perf_bundle.h @@ -44,7 +44,7 @@ public: virtual ~perf_bundle() {}; virtual void release(void); - void add_event(const char *event_name); + bool add_event(const char *event_name); void start(void); void stop(void); diff --git a/process/do_process.cpp b/process/do_process.cpp index f97b7e7..ae9ec05 100644 --- a/process/do_process.cpp +++ b/process/do_process.cpp @@ -447,6 +447,13 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin t = work->done(time, (uint64_t)wq->work); consumer_child_time(cpu, t); } + if (strcmp(event_name, "power:cpu_idle")==0) { + struct cpuidle_entry *ce = (struct cpuidle_entry *)trace; + if (ce->state == 4294967295) + consume_blame(cpu); + else + set_wakeup_pending(cpu); + } if (strcmp(event_name, "power:power_start") == 0) { set_wakeup_pending(cpu); } @@ -515,8 +522,10 @@ void start_process_measurement(void) perf_events->add_event("timer:timer_expire_exit"); perf_events->add_event("timer:hrtimer_expire_entry"); perf_events->add_event("timer:hrtimer_expire_exit"); - perf_events->add_event("power:power_start"); - perf_events->add_event("power:power_end"); + if (!perf_events->add_event("power:cpu_idle")){ + perf_events->add_event("power:power_start"); + perf_events->add_event("power:power_end"); + } perf_events->add_event("workqueue:workqueue_execute_start"); perf_events->add_event("workqueue:workqueue_execute_end"); perf_events->add_event("i915:i915_gem_ring_dispatch"); diff --git a/process/process.h b/process/process.h index a8fa91e..7d3f7cf 100644 --- a/process/process.h +++ b/process/process.h @@ -177,6 +177,10 @@ struct workqueue_end { #endif void *work; } __attribute__((packed)); +struct cpuidle_entry { + uint32_t state; + uint32_t cpu_id; +} __attribute__((packed)); struct dirty_inode { uint32_t dev; -- 1.7.4.1 --------------------------------------------------------------------- Intel Finland Oy Registered Address: PL 281, 00181 Helsinki Business Identity Code: 0357606 - 4 Domiciled in Helsinki 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 Power@bughost.org https://bughost.org/mailman/listinfo/power