aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--perf/perf_bundle.cpp4
-rw-r--r--perf/perf_bundle.h2
-rw-r--r--perf/perf_event.h19
-rw-r--r--process/do_process.cpp52
-rw-r--r--process/powerconsumer.h4
-rw-r--r--process/process.cpp3
-rw-r--r--process/process.h2
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);