diff options
Diffstat (limited to 'driver/gator_trace_sched.c')
-rw-r--r-- | driver/gator_trace_sched.c | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/driver/gator_trace_sched.c b/driver/gator_trace_sched.c index 52990e9..6550086 100644 --- a/driver/gator_trace_sched.c +++ b/driver/gator_trace_sched.c | |||
@@ -114,7 +114,7 @@ static void collect_counters(u64 time, struct task_struct *task) | |||
114 | 114 | ||
115 | // Commit buffers on timeout | 115 | // Commit buffers on timeout |
116 | if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { | 116 | if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { |
117 | static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF }; | 117 | static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF }; |
118 | int i; | 118 | int i; |
119 | 119 | ||
120 | for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { | 120 | for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { |
@@ -137,35 +137,44 @@ static void collect_counters(u64 time, struct task_struct *task) | |||
137 | // special case used during a suspend of the system | 137 | // special case used during a suspend of the system |
138 | static void trace_sched_insert_idle(void) | 138 | static void trace_sched_insert_idle(void) |
139 | { | 139 | { |
140 | marshal_sched_trace_switch(0, 0, 0, 0); | 140 | marshal_sched_trace_switch(0, 0); |
141 | } | 141 | } |
142 | 142 | ||
143 | GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child)) | 143 | static void gator_trace_emit_link(struct task_struct *p) |
144 | { | 144 | { |
145 | int cookie; | 145 | int cookie; |
146 | int cpu = get_physical_cpu(); | 146 | int cpu = get_physical_cpu(); |
147 | 147 | ||
148 | cookie = get_exec_cookie(cpu, child); | 148 | cookie = get_exec_cookie(cpu, p); |
149 | emit_pid_name(child); | 149 | emit_pid_name(p); |
150 | 150 | ||
151 | marshal_sched_trace_start(child->tgid, child->pid, cookie); | 151 | marshal_link(cookie, p->tgid, p->pid); |
152 | } | 152 | } |
153 | 153 | ||
154 | GATOR_DEFINE_PROBE(sched_process_fork, TP_PROTO(struct task_struct *parent, struct task_struct *child)) | ||
155 | { | ||
156 | gator_trace_emit_link(child); | ||
157 | } | ||
158 | |||
159 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) | ||
160 | GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm)) | ||
161 | { | ||
162 | gator_trace_emit_link(p); | ||
163 | } | ||
164 | #endif | ||
165 | |||
154 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) | 166 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) |
155 | GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) | 167 | GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) |
156 | #else | 168 | #else |
157 | GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) | 169 | GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) |
158 | #endif | 170 | #endif |
159 | { | 171 | { |
160 | int cookie; | ||
161 | int state; | 172 | int state; |
162 | int cpu = get_physical_cpu(); | 173 | int cpu = get_physical_cpu(); |
163 | 174 | ||
164 | per_cpu(in_scheduler_context, cpu) = true; | 175 | per_cpu(in_scheduler_context, cpu) = true; |
165 | 176 | ||
166 | // do as much work as possible before disabling interrupts | 177 | // do as much work as possible before disabling interrupts |
167 | cookie = get_exec_cookie(cpu, next); | ||
168 | emit_pid_name(next); | ||
169 | if (prev->state == TASK_RUNNING) { | 178 | if (prev->state == TASK_RUNNING) { |
170 | state = STATE_CONTENTION; | 179 | state = STATE_CONTENTION; |
171 | } else if (prev->in_iowait) { | 180 | } else if (prev->in_iowait) { |
@@ -178,7 +187,10 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ | |||
178 | collect_counters(gator_get_time(), prev); | 187 | collect_counters(gator_get_time(), prev); |
179 | per_cpu(collecting, cpu) = 0; | 188 | per_cpu(collecting, cpu) = 0; |
180 | 189 | ||
181 | marshal_sched_trace_switch(next->tgid, next->pid, cookie, state); | 190 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) |
191 | gator_trace_emit_link(next); | ||
192 | #endif | ||
193 | marshal_sched_trace_switch(next->pid, state); | ||
182 | 194 | ||
183 | per_cpu(in_scheduler_context, cpu) = false; | 195 | per_cpu(in_scheduler_context, cpu) = false; |
184 | } | 196 | } |
@@ -199,6 +211,10 @@ static int register_scheduler_tracepoints(void) | |||
199 | // register tracepoints | 211 | // register tracepoints |
200 | if (GATOR_REGISTER_TRACE(sched_process_fork)) | 212 | if (GATOR_REGISTER_TRACE(sched_process_fork)) |
201 | goto fail_sched_process_fork; | 213 | goto fail_sched_process_fork; |
214 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) | ||
215 | if (GATOR_REGISTER_TRACE(sched_process_exec)) | ||
216 | goto fail_sched_process_exec; | ||
217 | #endif | ||
202 | if (GATOR_REGISTER_TRACE(sched_switch)) | 218 | if (GATOR_REGISTER_TRACE(sched_switch)) |
203 | goto fail_sched_switch; | 219 | goto fail_sched_switch; |
204 | if (GATOR_REGISTER_TRACE(sched_process_free)) | 220 | if (GATOR_REGISTER_TRACE(sched_process_free)) |
@@ -216,15 +232,42 @@ fail_sched_process_free: | |||
216 | GATOR_UNREGISTER_TRACE(sched_switch); | 232 | GATOR_UNREGISTER_TRACE(sched_switch); |
217 | fail_sched_switch: | 233 | fail_sched_switch: |
218 | GATOR_UNREGISTER_TRACE(sched_process_fork); | 234 | GATOR_UNREGISTER_TRACE(sched_process_fork); |
235 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) | ||
236 | fail_sched_process_exec: | ||
237 | GATOR_UNREGISTER_TRACE(sched_process_exec); | ||
238 | #endif | ||
219 | fail_sched_process_fork: | 239 | fail_sched_process_fork: |
220 | pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); | 240 | pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); |
221 | 241 | ||
222 | return -1; | 242 | return -1; |
223 | } | 243 | } |
224 | 244 | ||
245 | static void unregister_scheduler_tracepoints(void) | ||
246 | { | ||
247 | GATOR_UNREGISTER_TRACE(sched_process_fork); | ||
248 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) | ||
249 | GATOR_UNREGISTER_TRACE(sched_process_exec); | ||
250 | #endif | ||
251 | GATOR_UNREGISTER_TRACE(sched_switch); | ||
252 | GATOR_UNREGISTER_TRACE(sched_process_free); | ||
253 | pr_debug("gator: unregistered tracepoints\n"); | ||
254 | } | ||
255 | |||
256 | static void gator_trace_sched_stop(void) | ||
257 | { | ||
258 | int cpu; | ||
259 | |||
260 | unregister_scheduler_tracepoints(); | ||
261 | |||
262 | for_each_present_cpu(cpu) { | ||
263 | kfree(per_cpu(taskname_keys, cpu)); | ||
264 | } | ||
265 | } | ||
266 | |||
225 | static int gator_trace_sched_start(void) | 267 | static int gator_trace_sched_start(void) |
226 | { | 268 | { |
227 | int cpu, size; | 269 | int cpu, size; |
270 | int ret; | ||
228 | 271 | ||
229 | for_each_present_cpu(cpu) { | 272 | for_each_present_cpu(cpu) { |
230 | size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); | 273 | size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); |
@@ -234,7 +277,9 @@ static int gator_trace_sched_start(void) | |||
234 | memset(per_cpu(taskname_keys, cpu), 0, size); | 277 | memset(per_cpu(taskname_keys, cpu), 0, size); |
235 | } | 278 | } |
236 | 279 | ||
237 | return register_scheduler_tracepoints(); | 280 | ret = register_scheduler_tracepoints(); |
281 | |||
282 | return ret; | ||
238 | } | 283 | } |
239 | 284 | ||
240 | static void gator_trace_sched_offline(void) | 285 | static void gator_trace_sched_offline(void) |
@@ -242,24 +287,6 @@ static void gator_trace_sched_offline(void) | |||
242 | trace_sched_insert_idle(); | 287 | trace_sched_insert_idle(); |
243 | } | 288 | } |
244 | 289 | ||
245 | static void unregister_scheduler_tracepoints(void) | ||
246 | { | ||
247 | GATOR_UNREGISTER_TRACE(sched_process_fork); | ||
248 | GATOR_UNREGISTER_TRACE(sched_switch); | ||
249 | GATOR_UNREGISTER_TRACE(sched_process_free); | ||
250 | pr_debug("gator: unregistered tracepoints\n"); | ||
251 | } | ||
252 | |||
253 | static void gator_trace_sched_stop(void) | ||
254 | { | ||
255 | int cpu; | ||
256 | unregister_scheduler_tracepoints(); | ||
257 | |||
258 | for_each_present_cpu(cpu) { | ||
259 | kfree(per_cpu(taskname_keys, cpu)); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | static void gator_trace_sched_init(void) | 290 | static void gator_trace_sched_init(void) |
264 | { | 291 | { |
265 | int i; | 292 | int i; |