diff options
-rw-r--r-- | samples/trace_events/trace-events-sample.c | 19 | ||||
-rw-r--r-- | samples/trace_events/trace-events-sample.h | 145 |
2 files changed, 150 insertions, 14 deletions
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c index aabc4e970911..16c15c08ed38 100644 --- a/samples/trace_events/trace-events-sample.c +++ b/samples/trace_events/trace-events-sample.c | |||
@@ -10,12 +10,29 @@ | |||
10 | #define CREATE_TRACE_POINTS | 10 | #define CREATE_TRACE_POINTS |
11 | #include "trace-events-sample.h" | 11 | #include "trace-events-sample.h" |
12 | 12 | ||
13 | static const char *random_strings[] = { | ||
14 | "Mother Goose", | ||
15 | "Snoopy", | ||
16 | "Gandalf", | ||
17 | "Frodo", | ||
18 | "One ring to rule them all" | ||
19 | }; | ||
13 | 20 | ||
14 | static void simple_thread_func(int cnt) | 21 | static void simple_thread_func(int cnt) |
15 | { | 22 | { |
23 | int array[6]; | ||
24 | int len = cnt % 5; | ||
25 | int i; | ||
26 | |||
16 | set_current_state(TASK_INTERRUPTIBLE); | 27 | set_current_state(TASK_INTERRUPTIBLE); |
17 | schedule_timeout(HZ); | 28 | schedule_timeout(HZ); |
18 | trace_foo_bar("hello", cnt); | 29 | |
30 | for (i = 0; i < len; i++) | ||
31 | array[i] = i + 1; | ||
32 | array[i] = 0; | ||
33 | |||
34 | trace_foo_bar("hello", cnt, array, random_strings[len], | ||
35 | tsk_cpus_allowed(current)); | ||
19 | } | 36 | } |
20 | 37 | ||
21 | static int simple_thread(void *arg) | 38 | static int simple_thread(void *arg) |
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 476429281389..dd65f7b8c0d9 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * If TRACE_SYSTEM is defined, that will be the directory created | 2 | * If TRACE_SYSTEM is defined, that will be the directory created |
3 | * in the ftrace directory under /sys/kernel/debug/tracing/events/<system> | 3 | * in the ftrace directory under /sys/kernel/tracing/events/<system> |
4 | * | 4 | * |
5 | * The define_trace.h below will also look for a file name of | 5 | * The define_trace.h below will also look for a file name of |
6 | * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. | 6 | * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. |
@@ -54,44 +54,163 @@ | |||
54 | * Here it is simply "foo, bar". | 54 | * Here it is simply "foo, bar". |
55 | * | 55 | * |
56 | * struct: This defines the way the data will be stored in the ring buffer. | 56 | * struct: This defines the way the data will be stored in the ring buffer. |
57 | * There are currently two types of elements. __field and __array. | 57 | * The items declared here become part of a special structure |
58 | * a __field is broken up into (type, name). Where type can be any | 58 | * called "__entry", which can be used in the fast_assign part of the |
59 | * primitive type (integer, long or pointer). __field_struct() can | 59 | * TRACE_EVENT macro. |
60 | * be any static complex data value (struct, union, but not an array). | 60 | * |
61 | * For an array. there are three fields. (type, name, size). The | 61 | * Here are the currently defined types you can use: |
62 | * type of elements in the array, the name of the field and the size | 62 | * |
63 | * of the array. | 63 | * __field : Is broken up into type and name. Where type can be any |
64 | * primitive type (integer, long or pointer). | ||
65 | * | ||
66 | * __field(int, foo) | ||
67 | * | ||
68 | * __entry->foo = 5; | ||
69 | * | ||
70 | * __field_struct : This can be any static complex data type (struct, union | ||
71 | * but not an array). Be careful using complex types, as each | ||
72 | * event is limited in size, and copying large amounts of data | ||
73 | * into the ring buffer can slow things down. | ||
74 | * | ||
75 | * __field_struct(struct bar, foo) | ||
76 | * | ||
77 | * __entry->bar.x = y; | ||
78 | |||
79 | * __array: There are three fields (type, name, size). The type is the | ||
80 | * type of elements in teh array, the name is the name of the array. | ||
81 | * size is the number of items in the array (not the total size). | ||
82 | * | ||
83 | * __array( char, foo, 10) is the same as saying: char foo[10]; | ||
84 | * | ||
85 | * Assigning arrays can be done like any array: | ||
86 | * | ||
87 | * __entry->foo[0] = 'a'; | ||
88 | * | ||
89 | * memcpy(__entry->foo, bar, 10); | ||
90 | * | ||
91 | * __dynamic_array: This is similar to array, but can vary is size from | ||
92 | * instance to instance of the tracepoint being called. | ||
93 | * Like __array, this too has three elements (type, name, size); | ||
94 | * type is the type of the element, name is the name of the array. | ||
95 | * The size is different than __array. It is not a static number, | ||
96 | * but the algorithm to figure out the length of the array for the | ||
97 | * specific instance of tracepoint. Again, size is the numebr of | ||
98 | * items in the array, not the total length in bytes. | ||
99 | * | ||
100 | * __dynamic_array( int, foo, bar) is similar to: int foo[bar]; | ||
101 | * | ||
102 | * Note, unlike arrays, you must use the __get_dynamic_array() macro | ||
103 | * to access the array. | ||
104 | * | ||
105 | * memcpy(__get_dynamic_array(foo), bar, 10); | ||
106 | * | ||
107 | * Notice, that "__entry" is not needed here. | ||
108 | * | ||
109 | * __string: This is a special kind of __dynamic_array. It expects to | ||
110 | * have a nul terminated character array passed to it (it allows | ||
111 | * for NULL too, which would be converted into "(null)"). __string | ||
112 | * takes two paramenter (name, src), where name is the name of | ||
113 | * the string saved, and src is the string to copy into the | ||
114 | * ring buffer. | ||
115 | * | ||
116 | * __string(foo, bar) is similar to: strcpy(foo, bar) | ||
117 | * | ||
118 | * To assign a string, use the helper macro __assign_str(). | ||
119 | * | ||
120 | * __assign_str(foo, bar); | ||
121 | * | ||
122 | * In most cases, the __assign_str() macro will take the same | ||
123 | * parameters as the __string() macro had to declare the string. | ||
124 | * | ||
125 | * __bitmask: This is another kind of __dynamic_array, but it expects | ||
126 | * an array of longs, and the number of bits to parse. It takes | ||
127 | * two parameters (name, nr_bits), where name is the name of the | ||
128 | * bitmask to save, and the nr_bits is the number of bits to record. | ||
129 | * | ||
130 | * __bitmask(target_cpu, nr_cpumask_bits) | ||
131 | * | ||
132 | * To assign a bitmask, use the __assign_bitmask() helper macro. | ||
133 | * | ||
134 | * __assign_bitmask(target_cpus, cpumask_bits(bar), nr_cpumask_bits); | ||
64 | * | 135 | * |
65 | * __array( char, foo, 10) is the same as saying char foo[10]. | ||
66 | * | 136 | * |
67 | * fast_assign: This is a C like function that is used to store the items | 137 | * fast_assign: This is a C like function that is used to store the items |
68 | * into the ring buffer. | 138 | * into the ring buffer. A special variable called "__entry" will be the |
139 | * structure that points into the ring buffer and has the same fields as | ||
140 | * described by the struct part of TRACE_EVENT above. | ||
69 | * | 141 | * |
70 | * printk: This is a way to print out the data in pretty print. This is | 142 | * printk: This is a way to print out the data in pretty print. This is |
71 | * useful if the system crashes and you are logging via a serial line, | 143 | * useful if the system crashes and you are logging via a serial line, |
72 | * the data can be printed to the console using this "printk" method. | 144 | * the data can be printed to the console using this "printk" method. |
145 | * This is also used to print out the data from the trace files. | ||
146 | * Again, the __entry macro is used to access the data from the ring buffer. | ||
147 | * | ||
148 | * Note, __dynamic_array, __string, and __bitmask require special helpers | ||
149 | * to access the data. | ||
150 | * | ||
151 | * For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo) | ||
152 | * Use __get_dynamic_array_len(foo) to get the length of the array | ||
153 | * saved. | ||
154 | * | ||
155 | * For __string(foo, bar) use __get_str(foo) | ||
156 | * | ||
157 | * For __bitmask(target_cpus, nr_cpumask_bits) use __get_bitmask(target_cpus) | ||
158 | * | ||
73 | * | 159 | * |
74 | * Note, that for both the assign and the printk, __entry is the handler | 160 | * Note, that for both the assign and the printk, __entry is the handler |
75 | * to the data structure in the ring buffer, and is defined by the | 161 | * to the data structure in the ring buffer, and is defined by the |
76 | * TP_STRUCT__entry. | 162 | * TP_STRUCT__entry. |
77 | */ | 163 | */ |
164 | |||
165 | /* | ||
166 | * It is OK to have helper functions in the file, but they need to be protected | ||
167 | * from being defined more than once. Remember, this file gets included more | ||
168 | * than once. | ||
169 | */ | ||
170 | #ifndef __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS | ||
171 | #define __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS | ||
172 | static inline int __length_of(const int *list) | ||
173 | { | ||
174 | int i; | ||
175 | |||
176 | if (!list) | ||
177 | return 0; | ||
178 | |||
179 | for (i = 0; list[i]; i++) | ||
180 | ; | ||
181 | return i; | ||
182 | } | ||
183 | #endif | ||
184 | |||
78 | TRACE_EVENT(foo_bar, | 185 | TRACE_EVENT(foo_bar, |
79 | 186 | ||
80 | TP_PROTO(char *foo, int bar), | 187 | TP_PROTO(const char *foo, int bar, const int *lst, |
188 | const char *string, const struct cpumask *mask), | ||
81 | 189 | ||
82 | TP_ARGS(foo, bar), | 190 | TP_ARGS(foo, bar, lst, string, mask), |
83 | 191 | ||
84 | TP_STRUCT__entry( | 192 | TP_STRUCT__entry( |
85 | __array( char, foo, 10 ) | 193 | __array( char, foo, 10 ) |
86 | __field( int, bar ) | 194 | __field( int, bar ) |
195 | __dynamic_array(int, list, __length_of(lst)) | ||
196 | __string( str, string ) | ||
197 | __bitmask( cpus, num_possible_cpus() ) | ||
87 | ), | 198 | ), |
88 | 199 | ||
89 | TP_fast_assign( | 200 | TP_fast_assign( |
90 | strlcpy(__entry->foo, foo, 10); | 201 | strlcpy(__entry->foo, foo, 10); |
91 | __entry->bar = bar; | 202 | __entry->bar = bar; |
203 | memcpy(__get_dynamic_array(list), lst, | ||
204 | __length_of(lst) * sizeof(int)); | ||
205 | __assign_str(str, string); | ||
206 | __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus()); | ||
92 | ), | 207 | ), |
93 | 208 | ||
94 | TP_printk("foo %s %d", __entry->foo, __entry->bar) | 209 | TP_printk("foo %s %d %s %s (%s)", __entry->foo, __entry->bar, |
210 | __print_array(__get_dynamic_array(list), | ||
211 | __get_dynamic_array_len(list), | ||
212 | sizeof(int)), | ||
213 | __get_str(str), __get_bitmask(cpus)) | ||
95 | ); | 214 | ); |
96 | #endif | 215 | #endif |
97 | 216 | ||