aboutsummaryrefslogtreecommitdiffstats
path: root/include/trace
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-04-18 22:51:29 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-22 06:29:18 -0400
commit9cbf117662e24c6d33245666804487f92c21b59d (patch)
treec4c7bed1ccb7a0a332abdc7cbf4620c98a0321cf /include/trace
parent7a4f453b6d7379a7c380825949977c5a838aa012 (diff)
tracing/events: provide string with undefined size support
This patch provides the support for dynamic size strings on event tracing. The key concept is to use a structure with an ending char array field of undefined size and use such ability to allocate the minimal size on the ring buffer to make one or more string entries fit inside, as opposite to a fixed length strings with upper bound. The strings themselves are represented using fields which have an offset value from the beginning of the entry. This patch provides three new macros: __string(item, src) This one declares a string to the structure inside TP_STRUCT__entry. You need to provide the name of the string field and the source that will be copied inside. This will also add the dynamic size of the string needed for the ring buffer entry allocation. A stack allocated structure is used to temporarily store the offset of each strings, avoiding double calls to strlen() on each event insertion. __get_str(field) This one will give you a pointer to the string you have created. This is an abstract helper to resolve the absolute address given the field name which is a relative address from the beginning of the trace_structure. __assign_str(dst, src) Use this macro to automatically perform the string copy from src to dst. src must be a variable to assign and dst is the name of a __string field. Example on how to use it: TRACE_EVENT(my_event, TP_PROTO(char *src1, char *src2), TP_ARGS(src1, src2), TP_STRUCT__entry( __string(str1, src1) __string(str2, src2) ), TP_fast_assign( __assign_str(str1, src1); __assign_str(str2, src2); ), TP_printk("%s %s", __get_str(src1), __get_str(src2)) ) Of course you can mix-up any __field or __array inside this TRACE_EVENT. The position of the __string or __assign_str doesn't matter. Changes in v2: Address the suggestion of Steven Rostedt: drop the opening_string() macro and redefine __ending_string() to get the size of the string to be copied instead of overwritting the whole ring buffer allocation. Changes in v3: Address other suggestions of Steven Rostedt and Peter Zijlstra with some changes: drop the __ending_string and the need to have only one string field. Use offsets instead of absolute addresses. [ Impact: allow more compact memory usage for string tracing ] Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Diffstat (limited to 'include/trace')
-rw-r--r--include/trace/ftrace.h88
1 files changed, 85 insertions, 3 deletions
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 15ef08d9add1..5a7d18c43634 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -27,6 +27,9 @@
27#undef __field 27#undef __field
28#define __field(type, item) type item; 28#define __field(type, item) type item;
29 29
30#undef __string
31#define __string(item, src) int __str_loc_##item;
32
30#undef TP_STRUCT__entry 33#undef TP_STRUCT__entry
31#define TP_STRUCT__entry(args...) args 34#define TP_STRUCT__entry(args...) args
32 35
@@ -35,14 +38,53 @@
35 struct ftrace_raw_##name { \ 38 struct ftrace_raw_##name { \
36 struct trace_entry ent; \ 39 struct trace_entry ent; \
37 tstruct \ 40 tstruct \
41 char __str_data[0]; \
38 }; \ 42 }; \
39 static struct ftrace_event_call event_##name 43 static struct ftrace_event_call event_##name
40 44
41#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 45#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
42 46
47
43/* 48/*
44 * Stage 2 of the trace events. 49 * Stage 2 of the trace events.
45 * 50 *
51 * Include the following:
52 *
53 * struct ftrace_str_offsets_<call> {
54 * int <str1>;
55 * int <str2>;
56 * [...]
57 * };
58 *
59 * The __string() macro will create each int <str>, this is to
60 * keep the offset of each string from the beggining of the event
61 * once we perform the strlen() of the src strings.
62 *
63 */
64
65#undef TRACE_FORMAT
66#define TRACE_FORMAT(call, proto, args, fmt)
67
68#undef __array
69#define __array(type, item, len)
70
71#undef __field
72#define __field(type, item);
73
74#undef __string
75#define __string(item, src) int item;
76
77#undef TRACE_EVENT
78#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
79 struct ftrace_str_offsets_##call { \
80 tstruct; \
81 };
82
83#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
84
85/*
86 * Stage 3 of the trace events.
87 *
46 * Override the macros in <trace/trace_events.h> to include the following: 88 * Override the macros in <trace/trace_events.h> to include the following:
47 * 89 *
48 * enum print_line_t 90 * enum print_line_t
@@ -80,6 +122,9 @@
80#undef TP_printk 122#undef TP_printk
81#define TP_printk(fmt, args...) fmt "\n", args 123#define TP_printk(fmt, args...) fmt "\n", args
82 124
125#undef __get_str
126#define __get_str(field) (char *)__entry + __entry->__str_loc_##field
127
83#undef TRACE_EVENT 128#undef TRACE_EVENT
84#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 129#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
85enum print_line_t \ 130enum print_line_t \
@@ -146,6 +191,16 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
146 if (!ret) \ 191 if (!ret) \
147 return 0; 192 return 0;
148 193
194#undef __string
195#define __string(item, src) \
196 ret = trace_seq_printf(s, "\tfield: __str_loc " #item ";\t" \
197 "offset:%u;tsize:%u;\n", \
198 (unsigned int)offsetof(typeof(field), \
199 __str_loc_##item), \
200 (unsigned int)sizeof(field.__str_loc_##item)); \
201 if (!ret) \
202 return 0;
203
149#undef __entry 204#undef __entry
150#define __entry REC 205#define __entry REC
151 206
@@ -189,6 +244,12 @@ ftrace_format_##call(struct trace_seq *s) \
189 if (ret) \ 244 if (ret) \
190 return ret; 245 return ret;
191 246
247#undef __string
248#define __string(item, src) \
249 ret = trace_define_field(event_call, "__str_loc", #item, \
250 offsetof(typeof(field), __str_loc_##item), \
251 sizeof(field.__str_loc_##item));
252
192#undef TRACE_EVENT 253#undef TRACE_EVENT
193#define TRACE_EVENT(call, proto, args, tstruct, func, print) \ 254#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
194int \ 255int \
@@ -212,7 +273,7 @@ ftrace_define_fields_##call(void) \
212#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 273#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
213 274
214/* 275/*
215 * Stage 3 of the trace events. 276 * Stage 4 of the trace events.
216 * 277 *
217 * Override the macros in <trace/trace_events.h> to include the following: 278 * Override the macros in <trace/trace_events.h> to include the following:
218 * 279 *
@@ -409,6 +470,23 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
409#undef __entry 470#undef __entry
410#define __entry entry 471#define __entry entry
411 472
473#undef __field
474#define __field(type, item)
475
476#undef __array
477#define __array(type, item, len)
478
479#undef __string
480#define __string(item, src) \
481 __str_offsets.item = __str_size + \
482 offsetof(typeof(*entry), __str_data); \
483 __str_size += strlen(src) + 1;
484
485#undef __assign_str
486#define __assign_str(dst, src) \
487 __entry->__str_loc_##dst = __str_offsets.dst; \
488 strcpy(__get_str(dst), src);
489
412#undef TRACE_EVENT 490#undef TRACE_EVENT
413#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 491#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
414_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \ 492_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
@@ -417,18 +495,22 @@ static struct ftrace_event_call event_##call; \
417 \ 495 \
418static void ftrace_raw_event_##call(proto) \ 496static void ftrace_raw_event_##call(proto) \
419{ \ 497{ \
498 struct ftrace_str_offsets_##call __maybe_unused __str_offsets; \
420 struct ftrace_event_call *call = &event_##call; \ 499 struct ftrace_event_call *call = &event_##call; \
421 struct ring_buffer_event *event; \ 500 struct ring_buffer_event *event; \
422 struct ftrace_raw_##call *entry; \ 501 struct ftrace_raw_##call *entry; \
423 unsigned long irq_flags; \ 502 unsigned long irq_flags; \
503 int __str_size = 0; \
424 int pc; \ 504 int pc; \
425 \ 505 \
426 local_save_flags(irq_flags); \ 506 local_save_flags(irq_flags); \
427 pc = preempt_count(); \ 507 pc = preempt_count(); \
428 \ 508 \
509 tstruct; \
510 \
429 event = trace_current_buffer_lock_reserve(event_##call.id, \ 511 event = trace_current_buffer_lock_reserve(event_##call.id, \
430 sizeof(struct ftrace_raw_##call), \ 512 sizeof(struct ftrace_raw_##call) + __str_size,\
431 irq_flags, pc); \ 513 irq_flags, pc); \
432 if (!event) \ 514 if (!event) \
433 return; \ 515 return; \
434 entry = ring_buffer_event_data(event); \ 516 entry = ring_buffer_event_data(event); \