aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-05-12 15:20:51 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-23 15:04:06 -0400
commit57422797dc009fc83766bcf230d29dbe6e08e21e (patch)
tree9ba5768539c08d99679f72a9709f5e345fd359c9 /kernel
parente309b41dd65aa953f86765eeeecc941d8e1e8b8f (diff)
ftrace: add wakeup events to sched tracer
Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c42
-rw-r--r--kernel/trace/trace.h12
-rw-r--r--kernel/trace/trace_sched_switch.c36
-rw-r--r--kernel/trace/trace_sched_wakeup.c2
-rw-r--r--kernel/trace/trace_selftest.c1
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;
57static DEFINE_PER_CPU(struct trace_array_cpu, max_data); 57static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
58 58
59static int tracer_enabled = 1; 59static int tracer_enabled = 1;
60static unsigned long trace_nr_entries = 16384UL; 60static unsigned long trace_nr_entries = 65536UL;
61 61
62static struct tracer *trace_types __read_mostly; 62static struct tracer *trace_types __read_mostly;
63static struct tracer *current_trace __read_mostly; 63static 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
715void
716tracing_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
715static void 740static void
716function_trace_call(unsigned long ip, unsigned long parent_ip) 741function_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);
166void tracing_record_cmdline(struct task_struct *tsk); 166void tracing_record_cmdline(struct task_struct *tsk);
167
168void 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);
167void trace_special(struct trace_array *tr, 173void 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
195extern void 201extern void
196wakeup_sched_switch(struct task_struct *prev, struct task_struct *next); 202wakeup_sched_switch(struct task_struct *prev, struct task_struct *next);
203extern void
204wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr);
197#else 205#else
198static inline void 206static inline void
199wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) 207wakeup_sched_switch(struct task_struct *prev, struct task_struct *next)
200{ 208{
201} 209}
210static inline void
211wakeup_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
44static 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
44void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) 67void 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
83void
84ftrace_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
60static void sched_switch_reset(struct trace_array *tr) 96static 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
204void 204void
205ftrace_wake_up_task(struct task_struct *wakee, struct task_struct *curr) 205wakeup_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;