diff options
-rw-r--r-- | perf/perf_bundle.cpp | 4 | ||||
-rw-r--r-- | perf/perf_bundle.h | 2 | ||||
-rw-r--r-- | perf/perf_event.h | 19 | ||||
-rw-r--r-- | process/do_process.cpp | 52 | ||||
-rw-r--r-- | process/powerconsumer.h | 4 | ||||
-rw-r--r-- | process/process.cpp | 3 | ||||
-rw-r--r-- | process/process.h | 2 |
7 files changed, 78 insertions, 8 deletions
diff --git a/perf/perf_bundle.cpp b/perf/perf_bundle.cpp index df3b684..78dee30 100644 --- a/perf/perf_bundle.cpp +++ b/perf/perf_bundle.cpp @@ -180,11 +180,11 @@ void perf_bundle::process(void) continue; - handle_trace_point(sample->trace.type, &sample->data, sample->trace.cpu, sample->trace.time); + handle_trace_point(sample->trace.type, &sample->data, sample->trace.cpu, sample->trace.time, sample->trace.flags); } } -void perf_bundle::handle_trace_point(int type, void *trace, int cpu, uint64_t time) +void perf_bundle::handle_trace_point(int type, void *trace, int cpu, uint64_t time, unsigned char flags) { } diff --git a/perf/perf_bundle.h b/perf/perf_bundle.h index 471f406..5ac8c2c 100644 --- a/perf/perf_bundle.h +++ b/perf/perf_bundle.h @@ -25,7 +25,7 @@ public: void process(void); - virtual void handle_trace_point(int type, void *trace, int cpu = 0, uint64_t time = 0); + virtual void handle_trace_point(int type, void *trace, int cpu = 0, uint64_t time = 0, unsigned char flags = 0); }; diff --git a/perf/perf_event.h b/perf/perf_event.h index 3b6c3e5..7d7cb5b 100644 --- a/perf/perf_event.h +++ b/perf/perf_event.h @@ -872,4 +872,23 @@ static inline void perf_event_init(void) { } perf_output_copy((handle), &(x), sizeof(x)) #endif /* __KERNEL__ */ + + +/* + * trace_flag_type is an enumeration that holds different + * states when a trace occurs. These are: + * IRQS_OFF - interrupts were disabled + * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags + * NEED_RESCED - reschedule is requested + * HARDIRQ - inside an interrupt handler + * SOFTIRQ - inside a softirq handler + */ +enum trace_flag_type { + TRACE_FLAG_IRQS_OFF = 0x01, + TRACE_FLAG_IRQS_NOSUPPORT = 0x02, + TRACE_FLAG_NEED_RESCHED = 0x04, + TRACE_FLAG_HARDIRQ = 0x08, + TRACE_FLAG_SOFTIRQ = 0x10, +}; + #endif /* _LINUX_PERF_EVENT_H */ diff --git a/process/do_process.cpp b/process/do_process.cpp index 610f5a1..23eb689 100644 --- a/process/do_process.cpp +++ b/process/do_process.cpp @@ -8,6 +8,7 @@ #include <string.h> #include "../perf/perf_bundle.h" +#include "../perf/perf_event.h" static class perf_bundle * perf_events; @@ -21,11 +22,12 @@ vector <class power_consumer *> all_power; class perf_process_bundle: public perf_bundle { - virtual void handle_trace_point(int type, void *trace, int cpu, uint64_t time); + virtual void handle_trace_point(int type, void *trace, int cpu, uint64_t time, unsigned char flags); }; + #define TASK_COMM_LEN 16 struct sched_switch { char prev_comm[TASK_COMM_LEN]; @@ -43,6 +45,16 @@ struct irq_entry { char handler[16]; }; + + +struct wakeup_entry { + char comm[TASK_COMM_LEN]; + int pid; + int prio; + int success; +}; + + struct irq_exit { int irq; int ret; @@ -85,7 +97,7 @@ static class interrupt * find_create_interrupt(char *_handler, int nr, int cpu) return new_irq; } -void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uint64_t time) +void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uint64_t time, unsigned char flags) { const char *event_name; @@ -93,7 +105,7 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin return; event_name = event_names[type]; - if (strcmp(event_name, "sched:sched_switch")==0) { + if (strcmp(event_name, "sched:sched_switch") == 0) { int from_idle = 0; struct sched_switch *sw; class process *old_proc = NULL; @@ -126,6 +138,12 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin return; } + /* if we got woken by someone else... account the wakeup to them, not to us */ + if (from_idle && new_proc->waker != NULL) { + new_proc->waker->wake_ups ++; + from_idle = 0; + } + new_proc->schedule_thread(time, sw->next_pid, from_idle); /* stick process in cpu cache, expand as needed */ @@ -133,9 +151,32 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin if ((int)cpu_cache.size() <= cpu) cpu_cache.resize(cpu + 1, NULL); cpu_cache[cpu] = new_proc; + new_proc->waker = NULL; + + + } + if (strcmp(event_name, "sched:sched_wakeup") == 0) { + struct wakeup_entry *we; + class power_consumer *from = NULL; + class process *dest_proc; + + we = (struct wakeup_entry *)trace; + + if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) { + /* woken from interrupt */ + /* TODO: find the current irq handler and set "from" to that */ + } else { + if ((int)cpu_cache.size() > cpu) + from = cpu_cache[cpu]; + } + + dest_proc = find_create_process(we->comm, we->pid); + + if (!dest_proc->running && dest_proc->waker == NULL) + dest_proc->waker = from; } - if (strcmp(event_name, "irq:irq_handler_entry")==0) { + if (strcmp(event_name, "irq:irq_handler_entry") == 0) { struct irq_entry *irqe; class interrupt *irq; int from_idle = 0; @@ -159,7 +200,7 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin irq->start_interrupt(time, from_idle); } - if (strcmp(event_name, "irq:irq_handler_exit")==0) { + if (strcmp(event_name, "irq:irq_handler_exit") == 0) { struct irq_exit *irqe; class interrupt *irq; irqe = (struct irq_exit *)trace; @@ -180,6 +221,7 @@ void start_process_measurement(void) if (!perf_events) { perf_events = new perf_process_bundle(); perf_events->add_event("sched:sched_switch"); + perf_events->add_event("sched:sched_wakeup"); perf_events->add_event("irq:irq_handler_entry"); perf_events->add_event("irq:irq_handler_exit"); } diff --git a/process/powerconsumer.h b/process/powerconsumer.h index b61599b..f49f22b 100644 --- a/process/powerconsumer.h +++ b/process/powerconsumer.h @@ -1,12 +1,16 @@ #ifndef __INCLUDE_GUARD_POWER_CONSUMER_ #define __INCLUDE_GUARD_POWER_CONSUMER_ + +class power_consumer; + class power_consumer { public: uint64_t accumulated_runtime; int disk_hits; int wake_ups; + class power_consumer *waker; virtual double Witts(void) { return 0.0;}; virtual const char * description(void) { return ""; }; diff --git a/process/process.cpp b/process/process.cpp index baea49a..e5d15b5 100644 --- a/process/process.cpp +++ b/process/process.cpp @@ -17,6 +17,7 @@ void process::schedule_thread(uint64_t time, int thread_id, int from_idle) wake_ups++; running_since = time; + running = 1; } @@ -26,6 +27,7 @@ void process::deschedule_thread(uint64_t time, int thread_id) delta = time - running_since; accumulated_runtime += delta; + running = 0; } @@ -37,6 +39,7 @@ process::process(const char *_comm, int _pid) wake_ups = 0; disk_hits = 0; is_idle = 0; + running = 0; if (strncmp(_comm, "kondemand/", 10) == 0) is_idle = 1; diff --git a/process/process.h b/process/process.h index b4e7a25..84efeb8 100644 --- a/process/process.h +++ b/process/process.h @@ -5,6 +5,7 @@ #include "powerconsumer.h" + /* Need to collect * CPU time consumed by each application @@ -20,6 +21,7 @@ public: int is_idle; /* count this as if the cpu was idle */ + int running; process(const char *_comm, int _pid); |