diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-05-12 15:20:51 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 15:04:06 -0400 |
commit | 57422797dc009fc83766bcf230d29dbe6e08e21e (patch) | |
tree | 9ba5768539c08d99679f72a9709f5e345fd359c9 | |
parent | e309b41dd65aa953f86765eeeecc941d8e1e8b8f (diff) |
ftrace: add wakeup events to sched tracer
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | kernel/trace/trace.c | 42 | ||||
-rw-r--r-- | kernel/trace/trace.h | 12 | ||||
-rw-r--r-- | kernel/trace/trace_sched_switch.c | 36 | ||||
-rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace_selftest.c | 1 |
5 files changed, 88 insertions, 5 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index f5898051fdd9..192c1354a7e0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -57,7 +57,7 @@ static struct trace_array max_tr; | |||
57 | static DEFINE_PER_CPU(struct trace_array_cpu, max_data); | 57 | static DEFINE_PER_CPU(struct trace_array_cpu, max_data); |
58 | 58 | ||
59 | static int tracer_enabled = 1; | 59 | static int tracer_enabled = 1; |
60 | static unsigned long trace_nr_entries = 16384UL; | 60 | static unsigned long trace_nr_entries = 65536UL; |
61 | 61 | ||
62 | static struct tracer *trace_types __read_mostly; | 62 | static struct tracer *trace_types __read_mostly; |
63 | static struct tracer *current_trace __read_mostly; | 63 | static struct tracer *current_trace __read_mostly; |
@@ -87,6 +87,7 @@ enum trace_type { | |||
87 | 87 | ||
88 | TRACE_FN, | 88 | TRACE_FN, |
89 | TRACE_CTX, | 89 | TRACE_CTX, |
90 | TRACE_WAKE, | ||
90 | TRACE_SPECIAL, | 91 | TRACE_SPECIAL, |
91 | 92 | ||
92 | __TRACE_LAST_TYPE | 93 | __TRACE_LAST_TYPE |
@@ -711,6 +712,30 @@ tracing_sched_switch_trace(struct trace_array *tr, | |||
711 | wake_up (&trace_wait); | 712 | wake_up (&trace_wait); |
712 | } | 713 | } |
713 | 714 | ||
715 | void | ||
716 | tracing_sched_wakeup_trace(struct trace_array *tr, | ||
717 | struct trace_array_cpu *data, | ||
718 | struct task_struct *wakee, struct task_struct *curr, | ||
719 | unsigned long flags) | ||
720 | { | ||
721 | struct trace_entry *entry; | ||
722 | unsigned long irq_flags; | ||
723 | |||
724 | spin_lock_irqsave(&data->lock, irq_flags); | ||
725 | entry = tracing_get_trace_entry(tr, data); | ||
726 | tracing_generic_entry_update(entry, flags); | ||
727 | entry->type = TRACE_WAKE; | ||
728 | entry->ctx.prev_pid = curr->pid; | ||
729 | entry->ctx.prev_prio = curr->prio; | ||
730 | entry->ctx.prev_state = curr->state; | ||
731 | entry->ctx.next_pid = wakee->pid; | ||
732 | entry->ctx.next_prio = wakee->prio; | ||
733 | spin_unlock_irqrestore(&data->lock, irq_flags); | ||
734 | |||
735 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
736 | wake_up(&trace_wait); | ||
737 | } | ||
738 | |||
714 | #ifdef CONFIG_FTRACE | 739 | #ifdef CONFIG_FTRACE |
715 | static void | 740 | static void |
716 | function_trace_call(unsigned long ip, unsigned long parent_ip) | 741 | function_trace_call(unsigned long ip, unsigned long parent_ip) |
@@ -1183,13 +1208,14 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1183 | trace_seq_puts(s, ")\n"); | 1208 | trace_seq_puts(s, ")\n"); |
1184 | break; | 1209 | break; |
1185 | case TRACE_CTX: | 1210 | case TRACE_CTX: |
1211 | case TRACE_WAKE: | ||
1186 | S = entry->ctx.prev_state < sizeof(state_to_char) ? | 1212 | S = entry->ctx.prev_state < sizeof(state_to_char) ? |
1187 | state_to_char[entry->ctx.prev_state] : 'X'; | 1213 | state_to_char[entry->ctx.prev_state] : 'X'; |
1188 | comm = trace_find_cmdline(entry->ctx.next_pid); | 1214 | comm = trace_find_cmdline(entry->ctx.next_pid); |
1189 | trace_seq_printf(s, " %d:%d:%c --> %d:%d %s\n", | 1215 | trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d %s\n", |
1190 | entry->ctx.prev_pid, | 1216 | entry->ctx.prev_pid, |
1191 | entry->ctx.prev_prio, | 1217 | entry->ctx.prev_prio, |
1192 | S, | 1218 | S, entry->type == TRACE_CTX ? "==>" : " +", |
1193 | entry->ctx.next_pid, | 1219 | entry->ctx.next_pid, |
1194 | entry->ctx.next_prio, | 1220 | entry->ctx.next_prio, |
1195 | comm); | 1221 | comm); |
@@ -1256,12 +1282,14 @@ static int print_trace_fmt(struct trace_iterator *iter) | |||
1256 | return 0; | 1282 | return 0; |
1257 | break; | 1283 | break; |
1258 | case TRACE_CTX: | 1284 | case TRACE_CTX: |
1285 | case TRACE_WAKE: | ||
1259 | S = entry->ctx.prev_state < sizeof(state_to_char) ? | 1286 | S = entry->ctx.prev_state < sizeof(state_to_char) ? |
1260 | state_to_char[entry->ctx.prev_state] : 'X'; | 1287 | state_to_char[entry->ctx.prev_state] : 'X'; |
1261 | ret = trace_seq_printf(s, " %d:%d:%c ==> %d:%d\n", | 1288 | ret = trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d\n", |
1262 | entry->ctx.prev_pid, | 1289 | entry->ctx.prev_pid, |
1263 | entry->ctx.prev_prio, | 1290 | entry->ctx.prev_prio, |
1264 | S, | 1291 | S, |
1292 | entry->type == TRACE_CTX ? "==>" : " +", | ||
1265 | entry->ctx.next_pid, | 1293 | entry->ctx.next_pid, |
1266 | entry->ctx.next_prio); | 1294 | entry->ctx.next_prio); |
1267 | if (!ret) | 1295 | if (!ret) |
@@ -1301,8 +1329,11 @@ static int print_raw_fmt(struct trace_iterator *iter) | |||
1301 | return 0; | 1329 | return 0; |
1302 | break; | 1330 | break; |
1303 | case TRACE_CTX: | 1331 | case TRACE_CTX: |
1332 | case TRACE_WAKE: | ||
1304 | S = entry->ctx.prev_state < sizeof(state_to_char) ? | 1333 | S = entry->ctx.prev_state < sizeof(state_to_char) ? |
1305 | state_to_char[entry->ctx.prev_state] : 'X'; | 1334 | state_to_char[entry->ctx.prev_state] : 'X'; |
1335 | if (entry->type == TRACE_WAKE) | ||
1336 | S = '+'; | ||
1306 | ret = trace_seq_printf(s, "%d %d %c %d %d\n", | 1337 | ret = trace_seq_printf(s, "%d %d %c %d %d\n", |
1307 | entry->ctx.prev_pid, | 1338 | entry->ctx.prev_pid, |
1308 | entry->ctx.prev_prio, | 1339 | entry->ctx.prev_prio, |
@@ -1355,8 +1386,11 @@ static int print_hex_fmt(struct trace_iterator *iter) | |||
1355 | SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip); | 1386 | SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip); |
1356 | break; | 1387 | break; |
1357 | case TRACE_CTX: | 1388 | case TRACE_CTX: |
1389 | case TRACE_WAKE: | ||
1358 | S = entry->ctx.prev_state < sizeof(state_to_char) ? | 1390 | S = entry->ctx.prev_state < sizeof(state_to_char) ? |
1359 | state_to_char[entry->ctx.prev_state] : 'X'; | 1391 | state_to_char[entry->ctx.prev_state] : 'X'; |
1392 | if (entry->type == TRACE_WAKE) | ||
1393 | S = '+'; | ||
1360 | SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid); | 1394 | SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid); |
1361 | SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio); | 1395 | SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio); |
1362 | SEQ_PUT_HEX_FIELD_RET(s, S); | 1396 | SEQ_PUT_HEX_FIELD_RET(s, S); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2b7352bf1ce6..90e0ba0f6eba 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -164,6 +164,12 @@ void tracing_sched_switch_trace(struct trace_array *tr, | |||
164 | struct task_struct *next, | 164 | struct task_struct *next, |
165 | unsigned long flags); | 165 | unsigned long flags); |
166 | void tracing_record_cmdline(struct task_struct *tsk); | 166 | void tracing_record_cmdline(struct task_struct *tsk); |
167 | |||
168 | void tracing_sched_wakeup_trace(struct trace_array *tr, | ||
169 | struct trace_array_cpu *data, | ||
170 | struct task_struct *wakee, | ||
171 | struct task_struct *cur, | ||
172 | unsigned long flags); | ||
167 | void trace_special(struct trace_array *tr, | 173 | void trace_special(struct trace_array *tr, |
168 | struct trace_array_cpu *data, | 174 | struct trace_array_cpu *data, |
169 | unsigned long arg1, | 175 | unsigned long arg1, |
@@ -194,11 +200,17 @@ extern cycle_t ftrace_now(int cpu); | |||
194 | #ifdef CONFIG_SCHED_TRACER | 200 | #ifdef CONFIG_SCHED_TRACER |
195 | extern void | 201 | extern void |
196 | wakeup_sched_switch(struct task_struct *prev, struct task_struct *next); | 202 | wakeup_sched_switch(struct task_struct *prev, struct task_struct *next); |
203 | extern void | ||
204 | wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr); | ||
197 | #else | 205 | #else |
198 | static inline void | 206 | static inline void |
199 | wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) | 207 | wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) |
200 | { | 208 | { |
201 | } | 209 | } |
210 | static inline void | ||
211 | wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr) | ||
212 | { | ||
213 | } | ||
202 | #endif | 214 | #endif |
203 | 215 | ||
204 | #ifdef CONFIG_CONTEXT_SWITCH_TRACER | 216 | #ifdef CONFIG_CONTEXT_SWITCH_TRACER |
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c index b738eaca1dbe..8b1cf1a3aee0 100644 --- a/kernel/trace/trace_sched_switch.c +++ b/kernel/trace/trace_sched_switch.c | |||
@@ -41,6 +41,29 @@ ctx_switch_func(struct task_struct *prev, struct task_struct *next) | |||
41 | local_irq_restore(flags); | 41 | local_irq_restore(flags); |
42 | } | 42 | } |
43 | 43 | ||
44 | static void wakeup_func(struct task_struct *wakee, struct task_struct *curr) | ||
45 | { | ||
46 | struct trace_array *tr = ctx_trace; | ||
47 | struct trace_array_cpu *data; | ||
48 | unsigned long flags; | ||
49 | long disabled; | ||
50 | int cpu; | ||
51 | |||
52 | if (!tracer_enabled) | ||
53 | return; | ||
54 | |||
55 | local_irq_save(flags); | ||
56 | cpu = raw_smp_processor_id(); | ||
57 | data = tr->data[cpu]; | ||
58 | disabled = atomic_inc_return(&data->disabled); | ||
59 | |||
60 | if (likely(disabled == 1)) | ||
61 | tracing_sched_wakeup_trace(tr, data, wakee, curr, flags); | ||
62 | |||
63 | atomic_dec(&data->disabled); | ||
64 | local_irq_restore(flags); | ||
65 | } | ||
66 | |||
44 | void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) | 67 | void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) |
45 | { | 68 | { |
46 | tracing_record_cmdline(prev); | 69 | tracing_record_cmdline(prev); |
@@ -57,6 +80,19 @@ void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) | |||
57 | wakeup_sched_switch(prev, next); | 80 | wakeup_sched_switch(prev, next); |
58 | } | 81 | } |
59 | 82 | ||
83 | void | ||
84 | ftrace_wake_up_task(struct task_struct *wakee, struct task_struct *curr) | ||
85 | { | ||
86 | tracing_record_cmdline(curr); | ||
87 | |||
88 | wakeup_func(wakee, curr); | ||
89 | |||
90 | /* | ||
91 | * Chain to the wakeup tracer (this is a NOP if disabled): | ||
92 | */ | ||
93 | wakeup_sched_wakeup(wakee, curr); | ||
94 | } | ||
95 | |||
60 | static void sched_switch_reset(struct trace_array *tr) | 96 | static void sched_switch_reset(struct trace_array *tr) |
61 | { | 97 | { |
62 | int cpu; | 98 | int cpu; |
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 662679c78b66..87fa7b253b57 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
@@ -202,7 +202,7 @@ out: | |||
202 | } | 202 | } |
203 | 203 | ||
204 | void | 204 | void |
205 | ftrace_wake_up_task(struct task_struct *wakee, struct task_struct *curr) | 205 | wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr) |
206 | { | 206 | { |
207 | if (likely(!tracer_enabled)) | 207 | if (likely(!tracer_enabled)) |
208 | return; | 208 | return; |
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 85715b86a342..39dd452647da 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
@@ -8,6 +8,7 @@ static inline int trace_valid_entry(struct trace_entry *entry) | |||
8 | switch (entry->type) { | 8 | switch (entry->type) { |
9 | case TRACE_FN: | 9 | case TRACE_FN: |
10 | case TRACE_CTX: | 10 | case TRACE_CTX: |
11 | case TRACE_WAKE: | ||
11 | return 1; | 12 | return 1; |
12 | } | 13 | } |
13 | return 0; | 14 | return 0; |