Merge branch 'tracing/core' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[linux-2.6-block.git] / include / trace / ftrace.h
CommitLineData
f42c85e7
SR
1/*
2 * Stage 1 of the trace events.
3 *
4 * Override the macros in <trace/trace_events.h> to include the following:
5 *
6 * struct ftrace_raw_<call> {
7 * struct trace_entry ent;
8 * <type> <item>;
9 * <type2> <item2>[<len>];
10 * [...]
11 * };
12 *
13 * The <type> <item> is created by the __field(type, item) macro or
14 * the __array(type2, item2, len) macro.
15 * We simply do "type item;", and that will create the fields
16 * in the structure.
17 */
18
19#include <linux/ftrace_event.h>
20
7fcb7c47
LZ
21#undef __field
22#define __field(type, item) type item;
23
43b51ead
LZ
24#undef __field_ext
25#define __field_ext(type, item, filter_type) type item;
26
f42c85e7
SR
27#undef __array
28#define __array(type, item, len) type item[len];
29
7fcb7c47 30#undef __dynamic_array
7d536cb3 31#define __dynamic_array(type, item, len) u32 __data_loc_##item;
f42c85e7 32
9cbf1176 33#undef __string
7fcb7c47 34#define __string(item, src) __dynamic_array(char, item, -1)
9cbf1176 35
f42c85e7
SR
36#undef TP_STRUCT__entry
37#define TP_STRUCT__entry(args...) args
38
39#undef TRACE_EVENT
40#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
41 struct ftrace_raw_##name { \
42 struct trace_entry ent; \
43 tstruct \
7fcb7c47 44 char __data[0]; \
f42c85e7
SR
45 }; \
46 static struct ftrace_event_call event_##name
47
97419875
JS
48/* Callbacks are meaningless to ftrace. */
49#undef TRACE_EVENT_FN
50#define TRACE_EVENT_FN(name, proto, args, tstruct, \
51 assign, print, reg, unreg) \
52 TRACE_EVENT(name, TP_PROTO(proto), TP_ARGS(args), \
53 TP_STRUCT__entry(tstruct), \
54 TP_fast_assign(assign), \
55 TP_printk(print))
56
f42c85e7
SR
57#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
58
9cbf1176 59
f42c85e7
SR
60/*
61 * Stage 2 of the trace events.
62 *
9cbf1176
FW
63 * Include the following:
64 *
7fcb7c47 65 * struct ftrace_data_offsets_<call> {
7d536cb3
LZ
66 * u32 <item1>;
67 * u32 <item2>;
9cbf1176
FW
68 * [...]
69 * };
70 *
7d536cb3 71 * The __dynamic_array() macro will create each u32 <item>, this is
7fcb7c47 72 * to keep the offset of each array from the beginning of the event.
7d536cb3 73 * The size of an array is also encoded, in the higher 16 bits of <item>.
9cbf1176
FW
74 */
75
7fcb7c47 76#undef __field
43b51ead
LZ
77#define __field(type, item)
78
79#undef __field_ext
80#define __field_ext(type, item, filter_type)
7fcb7c47 81
9cbf1176
FW
82#undef __array
83#define __array(type, item, len)
84
7fcb7c47 85#undef __dynamic_array
7d536cb3 86#define __dynamic_array(type, item, len) u32 item;
9cbf1176
FW
87
88#undef __string
7fcb7c47 89#define __string(item, src) __dynamic_array(char, item, -1)
9cbf1176
FW
90
91#undef TRACE_EVENT
92#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
7fcb7c47 93 struct ftrace_data_offsets_##call { \
9cbf1176
FW
94 tstruct; \
95 };
96
97#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
98
6ff9a64d
SR
99/*
100 * Setup the showing format of trace point.
101 *
102 * int
103 * ftrace_format_##call(struct trace_seq *s)
104 * {
105 * struct ftrace_raw_##call field;
106 * int ret;
107 *
108 * ret = trace_seq_printf(s, #type " " #item ";"
109 * " offset:%u; size:%u;\n",
110 * offsetof(struct ftrace_raw_##call, item),
111 * sizeof(field.type));
112 *
113 * }
114 */
115
116#undef TP_STRUCT__entry
117#define TP_STRUCT__entry(args...) args
118
119#undef __field
120#define __field(type, item) \
121 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
122 "offset:%u;\tsize:%u;\n", \
123 (unsigned int)offsetof(typeof(field), item), \
124 (unsigned int)sizeof(field.item)); \
125 if (!ret) \
126 return 0;
127
43b51ead
LZ
128#undef __field_ext
129#define __field_ext(type, item, filter_type) __field(type, item)
130
6ff9a64d
SR
131#undef __array
132#define __array(type, item, len) \
133 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
134 "offset:%u;\tsize:%u;\n", \
135 (unsigned int)offsetof(typeof(field), item), \
136 (unsigned int)sizeof(field.item)); \
137 if (!ret) \
138 return 0;
139
140#undef __dynamic_array
141#define __dynamic_array(type, item, len) \
68fd60a8 142 ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\
6ff9a64d
SR
143 "offset:%u;\tsize:%u;\n", \
144 (unsigned int)offsetof(typeof(field), \
145 __data_loc_##item), \
146 (unsigned int)sizeof(field.__data_loc_##item)); \
147 if (!ret) \
148 return 0;
149
150#undef __string
151#define __string(item, src) __dynamic_array(char, item, -1)
152
153#undef __entry
154#define __entry REC
155
156#undef __print_symbolic
157#undef __get_dynamic_array
158#undef __get_str
159
160#undef TP_printk
161#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args)
162
163#undef TP_fast_assign
164#define TP_fast_assign(args...) args
165
3a659305
PZ
166#undef TP_perf_assign
167#define TP_perf_assign(args...)
168
6ff9a64d
SR
169#undef TRACE_EVENT
170#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
171static int \
e8f9f4d7
FW
172ftrace_format_##call(struct ftrace_event_call *unused, \
173 struct trace_seq *s) \
6ff9a64d
SR
174{ \
175 struct ftrace_raw_##call field __attribute__((unused)); \
176 int ret = 0; \
177 \
178 tstruct; \
179 \
180 trace_seq_printf(s, "\nprint fmt: " print); \
181 \
182 return ret; \
183}
184
185#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
186
9cbf1176
FW
187/*
188 * Stage 3 of the trace events.
189 *
f42c85e7
SR
190 * Override the macros in <trace/trace_events.h> to include the following:
191 *
192 * enum print_line_t
193 * ftrace_raw_output_<call>(struct trace_iterator *iter, int flags)
194 * {
195 * struct trace_seq *s = &iter->seq;
196 * struct ftrace_raw_<call> *field; <-- defined in stage 1
197 * struct trace_entry *entry;
be74b73a 198 * struct trace_seq *p;
f42c85e7
SR
199 * int ret;
200 *
201 * entry = iter->ent;
202 *
203 * if (entry->type != event_<call>.id) {
204 * WARN_ON_ONCE(1);
205 * return TRACE_TYPE_UNHANDLED;
206 * }
207 *
208 * field = (typeof(field))entry;
209 *
be74b73a 210 * p = get_cpu_var(ftrace_event_seq);
56d8bd3f 211 * trace_seq_init(p);
f42c85e7 212 * ret = trace_seq_printf(s, <TP_printk> "\n");
be74b73a 213 * put_cpu();
f42c85e7
SR
214 * if (!ret)
215 * return TRACE_TYPE_PARTIAL_LINE;
216 *
217 * return TRACE_TYPE_HANDLED;
218 * }
219 *
220 * This is the method used to print the raw event to the trace
221 * output format. Note, this is not needed if the data is read
222 * in binary.
223 */
224
225#undef __entry
226#define __entry field
227
228#undef TP_printk
229#define TP_printk(fmt, args...) fmt "\n", args
230
7fcb7c47
LZ
231#undef __get_dynamic_array
232#define __get_dynamic_array(field) \
7d536cb3 233 ((void *)__entry + (__entry->__data_loc_##field & 0xffff))
7fcb7c47 234
9cbf1176 235#undef __get_str
7fcb7c47 236#define __get_str(field) (char *)__get_dynamic_array(field)
9cbf1176 237
be74b73a
SR
238#undef __print_flags
239#define __print_flags(flag, delim, flag_array...) \
240 ({ \
241 static const struct trace_print_flags flags[] = \
242 { flag_array, { -1, NULL }}; \
243 ftrace_print_flags_seq(p, delim, flag, flags); \
244 })
245
0f4fc29d
SR
246#undef __print_symbolic
247#define __print_symbolic(value, symbol_array...) \
248 ({ \
249 static const struct trace_print_flags symbols[] = \
250 { symbol_array, { -1, NULL }}; \
251 ftrace_print_symbols_seq(p, value, symbols); \
252 })
253
f42c85e7
SR
254#undef TRACE_EVENT
255#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
256enum print_line_t \
257ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
258{ \
259 struct trace_seq *s = &iter->seq; \
260 struct ftrace_raw_##call *field; \
261 struct trace_entry *entry; \
be74b73a 262 struct trace_seq *p; \
f42c85e7
SR
263 int ret; \
264 \
265 entry = iter->ent; \
266 \
267 if (entry->type != event_##call.id) { \
268 WARN_ON_ONCE(1); \
269 return TRACE_TYPE_UNHANDLED; \
270 } \
271 \
272 field = (typeof(field))entry; \
273 \
be74b73a 274 p = &get_cpu_var(ftrace_event_seq); \
56d8bd3f 275 trace_seq_init(p); \
f42c85e7 276 ret = trace_seq_printf(s, #call ": " print); \
be74b73a 277 put_cpu(); \
f42c85e7
SR
278 if (!ret) \
279 return TRACE_TYPE_PARTIAL_LINE; \
280 \
281 return TRACE_TYPE_HANDLED; \
282}
283
284#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
285
43b51ead
LZ
286#undef __field_ext
287#define __field_ext(type, item, filter_type) \
f42c85e7
SR
288 ret = trace_define_field(event_call, #type, #item, \
289 offsetof(typeof(field), item), \
43b51ead
LZ
290 sizeof(field.item), \
291 is_signed_type(type), filter_type); \
f42c85e7
SR
292 if (ret) \
293 return ret;
294
43b51ead
LZ
295#undef __field
296#define __field(type, item) __field_ext(type, item, FILTER_OTHER)
297
f42c85e7
SR
298#undef __array
299#define __array(type, item, len) \
300 BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
301 ret = trace_define_field(event_call, #type "[" #len "]", #item, \
302 offsetof(typeof(field), item), \
43b51ead 303 sizeof(field.item), 0, FILTER_OTHER); \
f42c85e7
SR
304 if (ret) \
305 return ret;
306
7fcb7c47
LZ
307#undef __dynamic_array
308#define __dynamic_array(type, item, len) \
68fd60a8 309 ret = trace_define_field(event_call, "__data_loc " #type "[]", #item, \
43b51ead
LZ
310 offsetof(typeof(field), __data_loc_##item), \
311 sizeof(field.__data_loc_##item), 0, \
312 FILTER_OTHER);
7fcb7c47 313
9cbf1176 314#undef __string
7fcb7c47 315#define __string(item, src) __dynamic_array(char, item, -1)
9cbf1176 316
f42c85e7
SR
317#undef TRACE_EVENT
318#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
319int \
14be96c9 320ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
f42c85e7
SR
321{ \
322 struct ftrace_raw_##call field; \
f42c85e7
SR
323 int ret; \
324 \
e647d6b3
LZ
325 ret = trace_define_common_fields(event_call); \
326 if (ret) \
327 return ret; \
f42c85e7
SR
328 \
329 tstruct; \
330 \
331 return ret; \
332}
333
334#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
335
7fcb7c47
LZ
336/*
337 * remember the offset of each array from the beginning of the event.
338 */
339
340#undef __entry
341#define __entry entry
342
343#undef __field
344#define __field(type, item)
345
43b51ead
LZ
346#undef __field_ext
347#define __field_ext(type, item, filter_type)
348
7fcb7c47
LZ
349#undef __array
350#define __array(type, item, len)
351
352#undef __dynamic_array
353#define __dynamic_array(type, item, len) \
354 __data_offsets->item = __data_size + \
355 offsetof(typeof(*entry), __data); \
7d536cb3 356 __data_offsets->item |= (len * sizeof(type)) << 16; \
7fcb7c47
LZ
357 __data_size += (len) * sizeof(type);
358
359#undef __string
360#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1) \
361
362#undef TRACE_EVENT
363#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
364static inline int ftrace_get_offsets_##call( \
365 struct ftrace_data_offsets_##call *__data_offsets, proto) \
366{ \
367 int __data_size = 0; \
368 struct ftrace_raw_##call __maybe_unused *entry; \
369 \
370 tstruct; \
371 \
372 return __data_size; \
373}
374
375#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
376
3a659305
PZ
377#ifdef CONFIG_EVENT_PROFILE
378
379/*
380 * Generate the functions needed for tracepoint perf_counter support.
381 *
f413cdb8 382 * NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later
3a659305
PZ
383 *
384 * static int ftrace_profile_enable_<call>(struct ftrace_event_call *event_call)
385 * {
386 * int ret = 0;
387 *
388 * if (!atomic_inc_return(&event_call->profile_count))
389 * ret = register_trace_<call>(ftrace_profile_<call>);
390 *
391 * return ret;
392 * }
393 *
394 * static void ftrace_profile_disable_<call>(struct ftrace_event_call *event_call)
395 * {
396 * if (atomic_add_negative(-1, &event->call->profile_count))
397 * unregister_trace_<call>(ftrace_profile_<call>);
398 * }
399 *
400 */
401
3a659305
PZ
402#undef TRACE_EVENT
403#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
404 \
f413cdb8 405static void ftrace_profile_##call(proto); \
3a659305
PZ
406 \
407static int ftrace_profile_enable_##call(struct ftrace_event_call *event_call) \
408{ \
409 int ret = 0; \
410 \
411 if (!atomic_inc_return(&event_call->profile_count)) \
412 ret = register_trace_##call(ftrace_profile_##call); \
413 \
414 return ret; \
415} \
416 \
417static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
418{ \
419 if (atomic_add_negative(-1, &event_call->profile_count)) \
420 unregister_trace_##call(ftrace_profile_##call); \
421}
422
423#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
424
3a659305
PZ
425#endif
426
c32e827b 427/*
9cbf1176 428 * Stage 4 of the trace events.
c32e827b 429 *
ea20d929 430 * Override the macros in <trace/trace_events.h> to include the following:
c32e827b
SR
431 *
432 * static void ftrace_event_<call>(proto)
433 * {
ef18012b 434 * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
c32e827b
SR
435 * }
436 *
437 * static int ftrace_reg_event_<call>(void)
438 * {
ef18012b 439 * int ret;
c32e827b 440 *
ef18012b
SR
441 * ret = register_trace_<call>(ftrace_event_<call>);
442 * if (!ret)
443 * pr_info("event trace: Could not activate trace point "
444 * "probe to <call>");
445 * return ret;
c32e827b
SR
446 * }
447 *
448 * static void ftrace_unreg_event_<call>(void)
449 * {
ef18012b 450 * unregister_trace_<call>(ftrace_event_<call>);
c32e827b
SR
451 * }
452 *
c32e827b 453 *
157587d7 454 * For those macros defined with TRACE_EVENT:
c32e827b
SR
455 *
456 * static struct ftrace_event_call event_<call>;
457 *
458 * static void ftrace_raw_event_<call>(proto)
459 * {
ef18012b
SR
460 * struct ring_buffer_event *event;
461 * struct ftrace_raw_<call> *entry; <-- defined in stage 1
462 * unsigned long irq_flags;
463 * int pc;
464 *
465 * local_save_flags(irq_flags);
466 * pc = preempt_count();
467 *
468 * event = trace_current_buffer_lock_reserve(event_<call>.id,
469 * sizeof(struct ftrace_raw_<call>),
470 * irq_flags, pc);
471 * if (!event)
472 * return;
473 * entry = ring_buffer_event_data(event);
474 *
475 * <assign>; <-- Here we assign the entries by the __field and
0e3d0f05 476 * __array macros.
c32e827b 477 *
ef18012b 478 * trace_current_buffer_unlock_commit(event, irq_flags, pc);
c32e827b
SR
479 * }
480 *
481 * static int ftrace_raw_reg_event_<call>(void)
482 * {
ef18012b 483 * int ret;
c32e827b 484 *
ef18012b
SR
485 * ret = register_trace_<call>(ftrace_raw_event_<call>);
486 * if (!ret)
487 * pr_info("event trace: Could not activate trace point "
488 * "probe to <call>");
489 * return ret;
c32e827b
SR
490 * }
491 *
492 * static void ftrace_unreg_event_<call>(void)
493 * {
ef18012b 494 * unregister_trace_<call>(ftrace_raw_event_<call>);
c32e827b
SR
495 * }
496 *
497 * static struct trace_event ftrace_event_type_<call> = {
ef18012b 498 * .trace = ftrace_raw_output_<call>, <-- stage 2
c32e827b
SR
499 * };
500 *
501 * static int ftrace_raw_init_event_<call>(void)
502 * {
ef18012b 503 * int id;
c32e827b 504 *
ef18012b
SR
505 * id = register_ftrace_event(&ftrace_event_type_<call>);
506 * if (!id)
507 * return -ENODEV;
508 * event_<call>.id = id;
509 * return 0;
c32e827b
SR
510 * }
511 *
512 * static struct ftrace_event_call __used
513 * __attribute__((__aligned__(4)))
514 * __attribute__((section("_ftrace_events"))) event_<call> = {
ef18012b 515 * .name = "<call>",
0e3d0f05 516 * .system = "<system>",
ef18012b
SR
517 * .raw_init = ftrace_raw_init_event_<call>,
518 * .regfunc = ftrace_reg_event_<call>,
519 * .unregfunc = ftrace_unreg_event_<call>,
981d081e 520 * .show_format = ftrace_format_<call>,
c32e827b
SR
521 * }
522 *
523 */
524
2939b046
SR
525#undef TP_FMT
526#define TP_FMT(fmt, args...) fmt "\n", ##args
c32e827b 527
ac199db0 528#ifdef CONFIG_EVENT_PROFILE
ac199db0
PZ
529
530#define _TRACE_PROFILE_INIT(call) \
531 .profile_count = ATOMIC_INIT(-1), \
532 .profile_enable = ftrace_profile_enable_##call, \
533 .profile_disable = ftrace_profile_disable_##call,
534
535#else
ac199db0
PZ
536#define _TRACE_PROFILE_INIT(call)
537#endif
538
da4d0302
SR
539#undef __entry
540#define __entry entry
d20e3b03 541
9cbf1176
FW
542#undef __field
543#define __field(type, item)
544
545#undef __array
546#define __array(type, item, len)
547
7fcb7c47
LZ
548#undef __dynamic_array
549#define __dynamic_array(type, item, len) \
550 __entry->__data_loc_##item = __data_offsets.item;
551
9cbf1176 552#undef __string
7fcb7c47 553#define __string(item, src) __dynamic_array(char, item, -1) \
9cbf1176
FW
554
555#undef __assign_str
556#define __assign_str(dst, src) \
9cbf1176
FW
557 strcpy(__get_str(dst), src);
558
da4d0302 559#undef TRACE_EVENT
30a8fecc 560#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
c32e827b
SR
561 \
562static struct ftrace_event_call event_##call; \
563 \
564static void ftrace_raw_event_##call(proto) \
565{ \
7fcb7c47 566 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
f2aebaee 567 struct ftrace_event_call *event_call = &event_##call; \
c32e827b
SR
568 struct ring_buffer_event *event; \
569 struct ftrace_raw_##call *entry; \
570 unsigned long irq_flags; \
7fcb7c47 571 int __data_size; \
c32e827b
SR
572 int pc; \
573 \
574 local_save_flags(irq_flags); \
575 pc = preempt_count(); \
576 \
7fcb7c47 577 __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
9cbf1176 578 \
c32e827b 579 event = trace_current_buffer_lock_reserve(event_##call.id, \
7fcb7c47 580 sizeof(*entry) + __data_size, \
9cbf1176 581 irq_flags, pc); \
c32e827b
SR
582 if (!event) \
583 return; \
584 entry = ring_buffer_event_data(event); \
585 \
7fcb7c47
LZ
586 \
587 tstruct \
588 \
a9c1c3ab 589 { assign; } \
c32e827b 590 \
f2aebaee 591 if (!filter_current_check_discard(event_call, entry, event)) \
77d9f465 592 trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
c32e827b
SR
593} \
594 \
69fd4f0e 595static int ftrace_raw_reg_event_##call(void *ptr) \
c32e827b
SR
596{ \
597 int ret; \
598 \
599 ret = register_trace_##call(ftrace_raw_event_##call); \
633ddaa7 600 if (ret) \
c32e827b 601 pr_info("event trace: Could not activate trace point " \
633ddaa7 602 "probe to " #call "\n"); \
c32e827b
SR
603 return ret; \
604} \
605 \
69fd4f0e 606static void ftrace_raw_unreg_event_##call(void *ptr) \
c32e827b
SR
607{ \
608 unregister_trace_##call(ftrace_raw_event_##call); \
609} \
610 \
611static struct trace_event ftrace_event_type_##call = { \
612 .trace = ftrace_raw_output_##call, \
613}; \
614 \
615static int ftrace_raw_init_event_##call(void) \
616{ \
617 int id; \
618 \
619 id = register_ftrace_event(&ftrace_event_type_##call); \
620 if (!id) \
621 return -ENODEV; \
622 event_##call.id = id; \
cf027f64 623 INIT_LIST_HEAD(&event_##call.fields); \
0a19e53c 624 init_preds(&event_##call); \
c32e827b
SR
625 return 0; \
626} \
627 \
628static struct ftrace_event_call __used \
629__attribute__((__aligned__(4))) \
630__attribute__((section("_ftrace_events"))) event_##call = { \
ef18012b 631 .name = #call, \
9cc26a26 632 .system = __stringify(TRACE_SYSTEM), \
6d723736 633 .event = &ftrace_event_type_##call, \
c32e827b 634 .raw_init = ftrace_raw_init_event_##call, \
da4d0302
SR
635 .regfunc = ftrace_raw_reg_event_##call, \
636 .unregfunc = ftrace_raw_unreg_event_##call, \
981d081e 637 .show_format = ftrace_format_##call, \
cf027f64 638 .define_fields = ftrace_define_fields_##call, \
ac199db0 639 _TRACE_PROFILE_INIT(call) \
c32e827b 640}
ac199db0 641
f42c85e7 642#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
ac199db0 643
f413cdb8
FW
644/*
645 * Define the insertion callback to profile events
646 *
647 * The job is very similar to ftrace_raw_event_<call> except that we don't
648 * insert in the ring buffer but in a perf counter.
649 *
650 * static void ftrace_profile_<call>(proto)
651 * {
652 * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
653 * struct ftrace_event_call *event_call = &event_<call>;
654 * extern void perf_tpcounter_event(int, u64, u64, void *, int);
655 * struct ftrace_raw_##call *entry;
656 * u64 __addr = 0, __count = 1;
657 * unsigned long irq_flags;
658 * int __entry_size;
659 * int __data_size;
660 * int pc;
661 *
662 * local_save_flags(irq_flags);
663 * pc = preempt_count();
664 *
665 * __data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
304703ab
FW
666 *
667 * // Below we want to get the aligned size by taking into account
668 * // the u32 field that will later store the buffer size
669 * __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),
670 * sizeof(u64));
671 * __entry_size -= sizeof(u32);
f413cdb8
FW
672 *
673 * do {
674 * char raw_data[__entry_size]; <- allocate our sample in the stack
675 * struct trace_entry *ent;
676 *
1853db0e
FW
677 * zero dead bytes from alignment to avoid stack leak to userspace:
678 *
679 * *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
f413cdb8
FW
680 * entry = (struct ftrace_raw_<call> *)raw_data;
681 * ent = &entry->ent;
682 * tracing_generic_entry_update(ent, irq_flags, pc);
683 * ent->type = event_call->id;
684 *
685 * <tstruct> <- do some jobs with dynamic arrays
686 *
687 * <assign> <- affect our values
688 *
689 * perf_tpcounter_event(event_call->id, __addr, __count, entry,
690 * __entry_size); <- submit them to perf counter
691 * } while (0);
692 *
693 * }
694 */
695
696#ifdef CONFIG_EVENT_PROFILE
697
698#undef __perf_addr
699#define __perf_addr(a) __addr = (a)
700
701#undef __perf_count
702#define __perf_count(c) __count = (c)
703
704#undef TRACE_EVENT
705#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
706static void ftrace_profile_##call(proto) \
707{ \
708 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
709 struct ftrace_event_call *event_call = &event_##call; \
710 extern void perf_tpcounter_event(int, u64, u64, void *, int); \
711 struct ftrace_raw_##call *entry; \
712 u64 __addr = 0, __count = 1; \
713 unsigned long irq_flags; \
714 int __entry_size; \
715 int __data_size; \
716 int pc; \
717 \
718 local_save_flags(irq_flags); \
719 pc = preempt_count(); \
720 \
721 __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
a044560c
PZ
722 __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
723 sizeof(u64)); \
304703ab 724 __entry_size -= sizeof(u32); \
f413cdb8
FW
725 \
726 do { \
727 char raw_data[__entry_size]; \
728 struct trace_entry *ent; \
729 \
1853db0e 730 *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
f413cdb8
FW
731 entry = (struct ftrace_raw_##call *)raw_data; \
732 ent = &entry->ent; \
733 tracing_generic_entry_update(ent, irq_flags, pc); \
734 ent->type = event_call->id; \
735 \
736 tstruct \
737 \
738 { assign; } \
739 \
740 perf_tpcounter_event(event_call->id, __addr, __count, entry,\
741 __entry_size); \
742 } while (0); \
743 \
744}
745
746#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
747#endif /* CONFIG_EVENT_PROFILE */
748
ac199db0
PZ
749#undef _TRACE_PROFILE_INIT
750