Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at ee9dce44362b2d8132c32964656ab6dff7dfbc6a 203 lines 6.9 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_TRACE_PRINTK_H 3#define _LINUX_TRACE_PRINTK_H 4 5#include <linux/compiler_attributes.h> 6#include <linux/instruction_pointer.h> 7#include <linux/stddef.h> 8#include <linux/stringify.h> 9 10/* 11 * General tracing related utility functions - trace_printk(), 12 * tracing_on/tracing_off and tracing_start()/tracing_stop 13 * 14 * Use tracing_on/tracing_off when you want to quickly turn on or off 15 * tracing. It simply enables or disables the recording of the trace events. 16 * This also corresponds to the user space /sys/kernel/tracing/tracing_on 17 * file, which gives a means for the kernel and userspace to interact. 18 * Place a tracing_off() in the kernel where you want tracing to end. 19 * From user space, examine the trace, and then echo 1 > tracing_on 20 * to continue tracing. 21 * 22 * tracing_stop/tracing_start has slightly more overhead. It is used 23 * by things like suspend to ram where disabling the recording of the 24 * trace is not enough, but tracing must actually stop because things 25 * like calling smp_processor_id() may crash the system. 26 * 27 * Most likely, you want to use tracing_on/tracing_off. 28 */ 29 30enum ftrace_dump_mode { 31 DUMP_NONE, 32 DUMP_ALL, 33 DUMP_ORIG, 34 DUMP_PARAM, 35}; 36 37#ifdef CONFIG_TRACING 38void tracing_on(void); 39void tracing_off(void); 40int tracing_is_on(void); 41void tracing_snapshot(void); 42void tracing_snapshot_alloc(void); 43 44extern void tracing_start(void); 45extern void tracing_stop(void); 46 47static inline __printf(1, 2) 48void ____trace_printk_check_format(const char *fmt, ...) 49{ 50} 51#define __trace_printk_check_format(fmt, args...) \ 52do { \ 53 if (0) \ 54 ____trace_printk_check_format(fmt, ##args); \ 55} while (0) 56 57/** 58 * trace_printk - printf formatting in the ftrace buffer 59 * @fmt: the printf format for printing 60 * 61 * Note: __trace_printk is an internal function for trace_printk() and 62 * the @ip is passed in via the trace_printk() macro. 63 * 64 * This function allows a kernel developer to debug fast path sections 65 * that printk is not appropriate for. By scattering in various 66 * printk like tracing in the code, a developer can quickly see 67 * where problems are occurring. 68 * 69 * This is intended as a debugging tool for the developer only. 70 * Please refrain from leaving trace_printks scattered around in 71 * your code. (Extra memory is used for special buffers that are 72 * allocated when trace_printk() is used.) 73 * 74 * A little optimization trick is done here. If there's only one 75 * argument, there's no need to scan the string for printf formats. 76 * The trace_puts() will suffice. But how can we take advantage of 77 * using trace_puts() when trace_printk() has only one argument? 78 * By stringifying the args and checking the size we can tell 79 * whether or not there are args. __stringify((__VA_ARGS__)) will 80 * turn into "()\0" with a size of 3 when there are no args, anything 81 * else will be bigger. All we need to do is define a string to this, 82 * and then take its size and compare to 3. If it's bigger, use 83 * do_trace_printk() otherwise, optimize it to trace_puts(). Then just 84 * let gcc optimize the rest. 85 */ 86 87#define trace_printk(fmt, ...) \ 88do { \ 89 char _______STR[] = __stringify((__VA_ARGS__)); \ 90 if (sizeof(_______STR) > 3) \ 91 do_trace_printk(fmt, ##__VA_ARGS__); \ 92 else \ 93 trace_puts(fmt); \ 94} while (0) 95 96#define do_trace_printk(fmt, args...) \ 97do { \ 98 static const char *trace_printk_fmt __used \ 99 __section("__trace_printk_fmt") = \ 100 __builtin_constant_p(fmt) ? fmt : NULL; \ 101 \ 102 __trace_printk_check_format(fmt, ##args); \ 103 \ 104 if (__builtin_constant_p(fmt)) \ 105 __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \ 106 else \ 107 __trace_printk(_THIS_IP_, fmt, ##args); \ 108} while (0) 109 110int __trace_bprintk(unsigned long ip, const char *fmt, ...); 111 112extern __printf(2, 3) 113int __trace_printk(unsigned long ip, const char *fmt, ...); 114 115/** 116 * trace_puts - write a string into the ftrace buffer 117 * @str: the string to record 118 * 119 * Note: __trace_bputs is an internal function for trace_puts and 120 * the @ip is passed in via the trace_puts macro. 121 * 122 * This is similar to trace_printk() but is made for those really fast 123 * paths that a developer wants the least amount of "Heisenbug" effects, 124 * where the processing of the print format is still too much. 125 * 126 * This function allows a kernel developer to debug fast path sections 127 * that printk is not appropriate for. By scattering in various 128 * printk like tracing in the code, a developer can quickly see 129 * where problems are occurring. 130 * 131 * This is intended as a debugging tool for the developer only. 132 * Please refrain from leaving trace_puts scattered around in 133 * your code. (Extra memory is used for special buffers that are 134 * allocated when trace_puts() is used.) 135 * 136 * Returns: 0 if nothing was written, positive # if string was. 137 * (1 when __trace_bputs is used, strlen(str) when __trace_puts is used) 138 */ 139 140#define trace_puts(str) ({ \ 141 static const char *trace_printk_fmt __used \ 142 __section("__trace_printk_fmt") = \ 143 __builtin_constant_p(str) ? str : NULL; \ 144 \ 145 if (__builtin_constant_p(str)) \ 146 __trace_bputs(_THIS_IP_, trace_printk_fmt); \ 147 else \ 148 __trace_puts(_THIS_IP_, str); \ 149}) 150extern int __trace_bputs(unsigned long ip, const char *str); 151extern int __trace_puts(unsigned long ip, const char *str); 152 153extern void trace_dump_stack(int skip); 154 155/* 156 * The double __builtin_constant_p is because gcc will give us an error 157 * if we try to allocate the static variable to fmt if it is not a 158 * constant. Even with the outer if statement. 159 */ 160#define ftrace_vprintk(fmt, vargs) \ 161do { \ 162 if (__builtin_constant_p(fmt)) { \ 163 static const char *trace_printk_fmt __used \ 164 __section("__trace_printk_fmt") = \ 165 __builtin_constant_p(fmt) ? fmt : NULL; \ 166 \ 167 __ftrace_vbprintk(_THIS_IP_, trace_printk_fmt, vargs); \ 168 } else \ 169 __ftrace_vprintk(_THIS_IP_, fmt, vargs); \ 170} while (0) 171 172extern __printf(2, 0) int 173__ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap); 174 175extern __printf(2, 0) int 176__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); 177 178extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode); 179#else 180static inline void tracing_start(void) { } 181static inline void tracing_stop(void) { } 182static inline void trace_dump_stack(int skip) { } 183 184static inline void tracing_on(void) { } 185static inline void tracing_off(void) { } 186static inline int tracing_is_on(void) { return 0; } 187static inline void tracing_snapshot(void) { } 188static inline void tracing_snapshot_alloc(void) { } 189 190static inline __printf(1, 2) 191int trace_printk(const char *fmt, ...) 192{ 193 return 0; 194} 195static __printf(1, 0) inline int 196ftrace_vprintk(const char *fmt, va_list ap) 197{ 198 return 0; 199} 200static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } 201#endif /* CONFIG_TRACING */ 202 203#endif