diff options
author | Pekka Paalanen <pq@iki.fi> | 2008-09-16 15:02:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-14 04:37:14 -0400 |
commit | fc5e27ae4b45a0619701a83f30d9b7fad7ed9400 (patch) | |
tree | 236b53e76430aae9f6b1abc37de9259ba95c38c6 | |
parent | 9e57fb35d711331a9b1410c5c56ebeb3733428a0 (diff) |
mmiotrace: handle TRACE_PRINT entries
Also make trace_seq_print_cont() non-static, and add a newline if the
seq buffer can't hold all data.
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/trace/trace.c | 31 | ||||
-rw-r--r-- | kernel/trace/trace.h | 19 | ||||
-rw-r--r-- | kernel/trace/trace_mmiotrace.c | 23 |
3 files changed, 53 insertions, 20 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 406de9cf2820..7e7154f77009 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -200,23 +200,6 @@ unsigned long nsecs_to_usecs(unsigned long nsecs) | |||
200 | } | 200 | } |
201 | 201 | ||
202 | /* | 202 | /* |
203 | * trace_flag_type is an enumeration that holds different | ||
204 | * states when a trace occurs. These are: | ||
205 | * IRQS_OFF - interrupts were disabled | ||
206 | * NEED_RESCED - reschedule is requested | ||
207 | * HARDIRQ - inside an interrupt handler | ||
208 | * SOFTIRQ - inside a softirq handler | ||
209 | * CONT - multiple entries hold the trace item | ||
210 | */ | ||
211 | enum trace_flag_type { | ||
212 | TRACE_FLAG_IRQS_OFF = 0x01, | ||
213 | TRACE_FLAG_NEED_RESCHED = 0x02, | ||
214 | TRACE_FLAG_HARDIRQ = 0x04, | ||
215 | TRACE_FLAG_SOFTIRQ = 0x08, | ||
216 | TRACE_FLAG_CONT = 0x10, | ||
217 | }; | ||
218 | |||
219 | /* | ||
220 | * TRACE_ITER_SYM_MASK masks the options in trace_flags that | 203 | * TRACE_ITER_SYM_MASK masks the options in trace_flags that |
221 | * control the output of kernel symbols. | 204 | * control the output of kernel symbols. |
222 | */ | 205 | */ |
@@ -1517,12 +1500,16 @@ lat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs, | |||
1517 | 1500 | ||
1518 | static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; | 1501 | static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; |
1519 | 1502 | ||
1520 | static void | 1503 | /* |
1521 | trace_seq_print_cont(struct trace_seq *s, struct trace_iterator *iter) | 1504 | * The message is supposed to contain an ending newline. |
1505 | * If the printing stops prematurely, try to add a newline of our own. | ||
1506 | */ | ||
1507 | void trace_seq_print_cont(struct trace_seq *s, struct trace_iterator *iter) | ||
1522 | { | 1508 | { |
1523 | struct trace_array *tr = iter->tr; | 1509 | struct trace_array *tr = iter->tr; |
1524 | struct trace_array_cpu *data = tr->data[iter->cpu]; | 1510 | struct trace_array_cpu *data = tr->data[iter->cpu]; |
1525 | struct trace_entry *ent; | 1511 | struct trace_entry *ent; |
1512 | bool ok = true; | ||
1526 | 1513 | ||
1527 | ent = trace_entry_idx(tr, data, iter, iter->cpu); | 1514 | ent = trace_entry_idx(tr, data, iter, iter->cpu); |
1528 | if (!ent || ent->type != TRACE_CONT) { | 1515 | if (!ent || ent->type != TRACE_CONT) { |
@@ -1531,10 +1518,14 @@ trace_seq_print_cont(struct trace_seq *s, struct trace_iterator *iter) | |||
1531 | } | 1518 | } |
1532 | 1519 | ||
1533 | do { | 1520 | do { |
1534 | trace_seq_printf(s, "%s", ent->cont.buf); | 1521 | if (ok) |
1522 | ok = (trace_seq_printf(s, "%s", ent->cont.buf) > 0); | ||
1535 | __trace_iterator_increment(iter, iter->cpu); | 1523 | __trace_iterator_increment(iter, iter->cpu); |
1536 | ent = trace_entry_idx(tr, data, iter, iter->cpu); | 1524 | ent = trace_entry_idx(tr, data, iter, iter->cpu); |
1537 | } while (ent && ent->type == TRACE_CONT); | 1525 | } while (ent && ent->type == TRACE_CONT); |
1526 | |||
1527 | if (!ok) | ||
1528 | trace_seq_putc(s, '\n'); | ||
1538 | } | 1529 | } |
1539 | 1530 | ||
1540 | static int | 1531 | static int |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index be3b3cf95f4b..648433d18ccb 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -72,6 +72,23 @@ struct print_entry { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * trace_flag_type is an enumeration that holds different | ||
76 | * states when a trace occurs. These are: | ||
77 | * IRQS_OFF - interrupts were disabled | ||
78 | * NEED_RESCED - reschedule is requested | ||
79 | * HARDIRQ - inside an interrupt handler | ||
80 | * SOFTIRQ - inside a softirq handler | ||
81 | * CONT - multiple entries hold the trace item | ||
82 | */ | ||
83 | enum trace_flag_type { | ||
84 | TRACE_FLAG_IRQS_OFF = 0x01, | ||
85 | TRACE_FLAG_NEED_RESCHED = 0x02, | ||
86 | TRACE_FLAG_HARDIRQ = 0x04, | ||
87 | TRACE_FLAG_SOFTIRQ = 0x08, | ||
88 | TRACE_FLAG_CONT = 0x10, | ||
89 | }; | ||
90 | |||
91 | /* | ||
75 | * The trace field - the most basic unit of tracing. This is what | 92 | * The trace field - the most basic unit of tracing. This is what |
76 | * is printed in the end as a single line in the trace output, such as: | 93 | * is printed in the end as a single line in the trace output, such as: |
77 | * | 94 | * |
@@ -330,6 +347,8 @@ extern int trace_selftest_startup_sysprof(struct tracer *trace, | |||
330 | 347 | ||
331 | extern void *head_page(struct trace_array_cpu *data); | 348 | extern void *head_page(struct trace_array_cpu *data); |
332 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...); | 349 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...); |
350 | extern void trace_seq_print_cont(struct trace_seq *s, | ||
351 | struct trace_iterator *iter); | ||
333 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, | 352 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, |
334 | size_t cnt); | 353 | size_t cnt); |
335 | extern long ns2usecs(cycle_t nsec); | 354 | extern long ns2usecs(cycle_t nsec); |
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index 767d1faf56e5..a108c326f36e 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c | |||
@@ -245,6 +245,27 @@ static int mmio_print_map(struct trace_iterator *iter) | |||
245 | return 0; | 245 | return 0; |
246 | } | 246 | } |
247 | 247 | ||
248 | static int mmio_print_mark(struct trace_iterator *iter) | ||
249 | { | ||
250 | struct trace_entry *entry = iter->ent; | ||
251 | const char *msg = entry->field.print.buf; | ||
252 | struct trace_seq *s = &iter->seq; | ||
253 | unsigned long long t = ns2usecs(entry->field.t); | ||
254 | unsigned long usec_rem = do_div(t, 1000000ULL); | ||
255 | unsigned secs = (unsigned long)t; | ||
256 | int ret; | ||
257 | |||
258 | /* The trailing newline must be in the message. */ | ||
259 | ret = trace_seq_printf(s, "MARK %lu.%06lu %s", secs, usec_rem, msg); | ||
260 | if (!ret) | ||
261 | return 0; | ||
262 | |||
263 | if (entry->field.flags & TRACE_FLAG_CONT) | ||
264 | trace_seq_print_cont(s, iter); | ||
265 | |||
266 | return 1; | ||
267 | } | ||
268 | |||
248 | /* return 0 to abort printing without consuming current entry in pipe mode */ | 269 | /* return 0 to abort printing without consuming current entry in pipe mode */ |
249 | static int mmio_print_line(struct trace_iterator *iter) | 270 | static int mmio_print_line(struct trace_iterator *iter) |
250 | { | 271 | { |
@@ -253,6 +274,8 @@ static int mmio_print_line(struct trace_iterator *iter) | |||
253 | return mmio_print_rw(iter); | 274 | return mmio_print_rw(iter); |
254 | case TRACE_MMIO_MAP: | 275 | case TRACE_MMIO_MAP: |
255 | return mmio_print_map(iter); | 276 | return mmio_print_map(iter); |
277 | case TRACE_PRINT: | ||
278 | return mmio_print_mark(iter); | ||
256 | default: | 279 | default: |
257 | return 1; /* ignore unknown entries */ | 280 | return 1; /* ignore unknown entries */ |
258 | } | 281 | } |