Hello,

Patch introduces support for new trace API. Below is part 1 --
support new trace API. I suspect, that in part 2 we'll have to change 
add_event signature to return status code, since that compiled with both 
CONFIG_EVENT_POWER_TRACING_DEPRECATED and new API kernel will produce
double events (didn't test it, just a guess).


----8<-----8<------

Introduce support for new trace API : cpu_frequency, cpu_idle events.

For event_type 71 -- cpu_frequency -- header is as follows:

header:
        type  is 71 / 47 
09 00 00 00 01 00 30 00 e7 bb f1 76 78 6e 00 00 01 00 00 00 00 00 00 00
14 00 00 00 47 00 00 01 67 1e 00 00 ff ff ff ff 98 4b 12 00 01 00 00 00 


where according to include/trace/events/power.h

DEFINE_EVENT(cpu, cpu_frequency,
                TP_PROTO(unsigned int frequency, unsigned int cpu_id),
                TP_ARGS(frequency, cpu_id)
);

To address freq and cpu_id, struct power_cpu_idle_entry was introduced:
struct power_cpu_idle_entry {
int     state;
int     cpu_id;
};



For event_type 72 -- cpu_idle -- header is:
header:
        type  is 72 / 48 
09 00 00 00 01 00 30 00 ba 5b 68 52 78 6e 00 00 03 00 00 00 00 00 00 00
14 00 00 00 48 00 04 02 00 00 00 00 ff ff ff ff ff ff ff ff 03 00 00 00 

where 
DEFINE_EVENT(cpu, cpu_idle,
                TP_PROTO(unsigned int state, unsigned int cpu_id),
                TP_ARGS(state, cpu_id)
);

To address frequency and cpu_id, struct power_cpu_freqency_entry was 
introduced:
struct power_cpu_freqency_entry {
unsigned int    frequency;
unsigned int    cpu_id;
};



---

 cpu/cpu.cpp            |   18 +++++++++++++++++-
 perf/perf.cpp          |    4 +++-
 perf/perf.h            |   23 ++++++++++++++++++++++-
 process/do_process.cpp |   11 +++++++++++
 4 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/cpu/cpu.cpp b/cpu/cpu.cpp
index 39f00e7..6afedf3 100644
--- a/cpu/cpu.cpp
+++ b/cpu/cpu.cpp
@@ -271,6 +271,8 @@ void enumerate_cpus(void)
        perf_events = new perf_power_bundle();
 
        perf_events->add_event("power:power_frequency");
+       perf_events->add_event("power:cpu_frequency");
+       perf_events->add_event("power:cpu_idle");
        perf_events->add_event("power:power_start");
        perf_events->add_event("power:power_end");
 
@@ -773,10 +775,24 @@ 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:power_frequency")==0) {
+       if (strcmp(event_name, "power:power_frequency") == 0) {
                struct power_entry *pe = (struct power_entry *)trace;
                cpu->change_freq(time, pe->value);
        }
+
+       if (strcmp(event_name, "power:cpu_frequency") == 0) {
+               struct power_cpu_freqency_entry *pfe = (struct 
power_cpu_freqency_entry *)trace;
+               cpu->change_freq(time, pfe->frequency);
+       }
+
+       if (strcmp(event_name, "power:cpu_idle") == 0) {
+               struct power_cpu_idle_entry *ppe = (struct power_cpu_idle_entry 
*)trace;
+               if (ppe->state != PWR_EVENT_EXIT)
+                       cpu->go_idle(time);
+               else
+                       cpu->go_unidle(time);
+       }
+
        if (strcmp(event_name, "power:power_start")==0)
                cpu->go_idle(time);
        if (strcmp(event_name, "power:power_end")==0)
diff --git a/perf/perf.cpp b/perf/perf.cpp
index 73682aa..7354391 100644
--- a/perf/perf.cpp
+++ b/perf/perf.cpp
@@ -53,8 +53,10 @@ static int get_trace_type(const char *eventname)
 
 
        str = read_sysfs_string("/sys/kernel/debug/tracing/events/%s/id", 
eventname);
-       if (str.length() < 1)
+       if (str.length() < 1) {
+               fprintf(stderr, "Error: can't find event: %s\n", eventname);
                return -1;
+       }
        this_trace = strtoull(str.c_str(), NULL, 10);
        return this_trace;
 }
diff --git a/perf/perf.h b/perf/perf.h
index faeb6b3..569c5ed 100644
--- a/perf/perf.h
+++ b/perf/perf.h
@@ -26,9 +26,30 @@
 #define _INCLUDE_GUARD_PERF_H_
 
 #include <iostream>
+#include <stdint.h>
 
 using namespace std;
 
+#define __u32 uint32_t
+#define PWR_EVENT_EXIT -1
+
+/*
+ * DEFINE_EVENT cpu_idle
+ * TP_ARGS(state, cpu_id)
+ */
+struct power_cpu_idle_entry {
+       int             state;
+       int             cpu_id;
+};
+
+/* DEFINE_EVENT cpu_frequency
+ * TP_ARGS(frequency, cpu_id)
+ */
+struct power_cpu_freqency_entry {
+       unsigned int    frequency;
+       unsigned int    cpu_id;
+};
+
 class  perf_event {
 protected:
        int perf_fd;
@@ -65,4 +86,4 @@ public:
 };
 
 
-#endif
\ No newline at end of file
+#endif
diff --git a/process/do_process.cpp b/process/do_process.cpp
index 2ca4b10..f87a873 100644
--- a/process/do_process.cpp
+++ b/process/do_process.cpp
@@ -39,6 +39,7 @@
 #include <string.h>
 #include <ncurses.h>
 
+#include "../perf/perf.h"
 #include "../perf/perf_bundle.h"
 #include "../perf/perf_event.h"
 #include "../parameters/parameters.h"
@@ -438,6 +439,15 @@ 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 power_cpu_idle_entry *ppe = (struct 
power_cpu_idle_entry *)trace;
+                       if (ppe->state != PWR_EVENT_EXIT)
+                               set_wakeup_pending(cpu);
+                       else
+                               consume_blame(cpu);
+       }
+
        if (strcmp(event_name, "power:power_start") == 0) {
                set_wakeup_pending(cpu);
        }
@@ -503,6 +513,7 @@ 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:cpu_idle");
                perf_events->add_event("power:power_start");
                perf_events->add_event("power:power_end");
                perf_events->add_event("workqueue:workqueue_execute_start");

_______________________________________________
Discuss mailing list
[email protected]
http://lists.lesswatts.org/listinfo/discuss

Reply via email to