diff options
Diffstat (limited to 'include/linux/kernel.h')
-rw-r--r-- | include/linux/kernel.h | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 79fdd80a42d4..2dac79c39199 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -486,6 +486,8 @@ enum ftrace_dump_mode { | |||
486 | void tracing_on(void); | 486 | void tracing_on(void); |
487 | void tracing_off(void); | 487 | void tracing_off(void); |
488 | int tracing_is_on(void); | 488 | int tracing_is_on(void); |
489 | void tracing_snapshot(void); | ||
490 | void tracing_snapshot_alloc(void); | ||
489 | 491 | ||
490 | extern void tracing_start(void); | 492 | extern void tracing_start(void); |
491 | extern void tracing_stop(void); | 493 | extern void tracing_stop(void); |
@@ -515,10 +517,32 @@ do { \ | |||
515 | * | 517 | * |
516 | * This is intended as a debugging tool for the developer only. | 518 | * This is intended as a debugging tool for the developer only. |
517 | * Please refrain from leaving trace_printks scattered around in | 519 | * Please refrain from leaving trace_printks scattered around in |
518 | * your code. | 520 | * your code. (Extra memory is used for special buffers that are |
521 | * allocated when trace_printk() is used) | ||
522 | * | ||
523 | * A little optization trick is done here. If there's only one | ||
524 | * argument, there's no need to scan the string for printf formats. | ||
525 | * The trace_puts() will suffice. But how can we take advantage of | ||
526 | * using trace_puts() when trace_printk() has only one argument? | ||
527 | * By stringifying the args and checking the size we can tell | ||
528 | * whether or not there are args. __stringify((__VA_ARGS__)) will | ||
529 | * turn into "()\0" with a size of 3 when there are no args, anything | ||
530 | * else will be bigger. All we need to do is define a string to this, | ||
531 | * and then take its size and compare to 3. If it's bigger, use | ||
532 | * do_trace_printk() otherwise, optimize it to trace_puts(). Then just | ||
533 | * let gcc optimize the rest. | ||
519 | */ | 534 | */ |
520 | 535 | ||
521 | #define trace_printk(fmt, args...) \ | 536 | #define trace_printk(fmt, ...) \ |
537 | do { \ | ||
538 | char _______STR[] = __stringify((__VA_ARGS__)); \ | ||
539 | if (sizeof(_______STR) > 3) \ | ||
540 | do_trace_printk(fmt, ##__VA_ARGS__); \ | ||
541 | else \ | ||
542 | trace_puts(fmt); \ | ||
543 | } while (0) | ||
544 | |||
545 | #define do_trace_printk(fmt, args...) \ | ||
522 | do { \ | 546 | do { \ |
523 | static const char *trace_printk_fmt \ | 547 | static const char *trace_printk_fmt \ |
524 | __attribute__((section("__trace_printk_fmt"))) = \ | 548 | __attribute__((section("__trace_printk_fmt"))) = \ |
@@ -538,7 +562,45 @@ int __trace_bprintk(unsigned long ip, const char *fmt, ...); | |||
538 | extern __printf(2, 3) | 562 | extern __printf(2, 3) |
539 | int __trace_printk(unsigned long ip, const char *fmt, ...); | 563 | int __trace_printk(unsigned long ip, const char *fmt, ...); |
540 | 564 | ||
541 | extern void trace_dump_stack(void); | 565 | /** |
566 | * trace_puts - write a string into the ftrace buffer | ||
567 | * @str: the string to record | ||
568 | * | ||
569 | * Note: __trace_bputs is an internal function for trace_puts and | ||
570 | * the @ip is passed in via the trace_puts macro. | ||
571 | * | ||
572 | * This is similar to trace_printk() but is made for those really fast | ||
573 | * paths that a developer wants the least amount of "Heisenbug" affects, | ||
574 | * where the processing of the print format is still too much. | ||
575 | * | ||
576 | * This function allows a kernel developer to debug fast path sections | ||
577 | * that printk is not appropriate for. By scattering in various | ||
578 | * printk like tracing in the code, a developer can quickly see | ||
579 | * where problems are occurring. | ||
580 | * | ||
581 | * This is intended as a debugging tool for the developer only. | ||
582 | * Please refrain from leaving trace_puts scattered around in | ||
583 | * your code. (Extra memory is used for special buffers that are | ||
584 | * allocated when trace_puts() is used) | ||
585 | * | ||
586 | * Returns: 0 if nothing was written, positive # if string was. | ||
587 | * (1 when __trace_bputs is used, strlen(str) when __trace_puts is used) | ||
588 | */ | ||
589 | |||
590 | extern int __trace_bputs(unsigned long ip, const char *str); | ||
591 | extern int __trace_puts(unsigned long ip, const char *str, int size); | ||
592 | #define trace_puts(str) ({ \ | ||
593 | static const char *trace_printk_fmt \ | ||
594 | __attribute__((section("__trace_printk_fmt"))) = \ | ||
595 | __builtin_constant_p(str) ? str : NULL; \ | ||
596 | \ | ||
597 | if (__builtin_constant_p(str)) \ | ||
598 | __trace_bputs(_THIS_IP_, trace_printk_fmt); \ | ||
599 | else \ | ||
600 | __trace_puts(_THIS_IP_, str, strlen(str)); \ | ||
601 | }) | ||
602 | |||
603 | extern void trace_dump_stack(int skip); | ||
542 | 604 | ||
543 | /* | 605 | /* |
544 | * The double __builtin_constant_p is because gcc will give us an error | 606 | * The double __builtin_constant_p is because gcc will give us an error |
@@ -573,6 +635,8 @@ static inline void trace_dump_stack(void) { } | |||
573 | static inline void tracing_on(void) { } | 635 | static inline void tracing_on(void) { } |
574 | static inline void tracing_off(void) { } | 636 | static inline void tracing_off(void) { } |
575 | static inline int tracing_is_on(void) { return 0; } | 637 | static inline int tracing_is_on(void) { return 0; } |
638 | static inline void tracing_snapshot(void) { } | ||
639 | static inline void tracing_snapshot_alloc(void) { } | ||
576 | 640 | ||
577 | static inline __printf(1, 2) | 641 | static inline __printf(1, 2) |
578 | int trace_printk(const char *fmt, ...) | 642 | int trace_printk(const char *fmt, ...) |