Re: [PATCH 1/2 v2] tracing/events: provide string with undefinedsize support

From: Steven Rostedt
Date: Fri Apr 17 2009 - 06:40:31 EST


On Fri, 17 Apr 2009, Steven Rostedt wrote:
>
> But that said, one could still do what you are suggesting. The "__ending"
> wart still needs to be there, since it must happen at the end of the
> struct.
>
>
> TP_STRUCT__entry(
> __field(int, str2loc)
> __field(int, str3loc)
> __string(str1)
> __string(str2)
> __ending_string(data, str3)
> ),
> TP_fast_assign(
> __entry->str2loc = strlen(str1);
> __entry->str3loc = strlen(str2) + __entry->str2loc;
> strcpy(__entry->data, str1);
> strcpy(__entry->data + __entry->str2loc, str2)
> strcpy(__entry->data + __entry->str3loc, str3)
> ),
> TP_printk("str1:%s str2:%s str3:%s\n",
> __entry->data,
> __entry->data + __entry->str2loc,
> __entry->date + __entry->str3loc)
>
>
> For this to work, we need to just add a define for the __string macro for
> the reservation:
>
> #define __string(x) __str_size_ += strlen(x) + 1;

Hmm, thinking about this more, we could do...


Make all structs end with:

char __str_data__[0];


then we could just have __string(dec, param), ie.


__string(str1, param_str1)
__string(str2, param_str2)
__string(srt3, param_str3)

But instead of defining string as a character, it would just be an index
into the __str_data_.

#define __string(dec, param) int dec;


We can break up the TRACE_EVENT macro again to create the declaration:

#undef everything and make empty macros of all we don't use

#define __string(dec, str) int __str_loc_##dec;

#define TRACE_EVENT(...) \
static void ftrace_raw_event_##call(proto) \
{ \
struct ring_buffer_event *event; \
struct ftrace_raw_##call *entry; \
unsigned long flags; \
int pc; \
int _str_size_ = 0; \
\
tstruct

#include the file

#undef __string
#define __string(str, param) __str_loc_##str = _str_size_; \
_str_size_ += strlen(param) + 1;

#define TRACE_EVENT(...)
tstruct

#include the file again

Then we can do the assignment for the user:

#undef everything again
#define the usual suspects

#define __string(str, param) __entry->str = __str_loc_##str;

#define TRACE_EVENT(...)
local_save_flags(irq_flags); \
pc = preempt_count(); \
\
event = trace_current_buffer_lock_reserve(event_##call.id, \
sizeof(struct ftrace_raw_##call), \
irq_flags, pc); \
if (!event) \
return; \
entry = ring_buffer_event_data(event); \
\
tstruct \
assign; \

#include the file again

#undef everything again,

#define __string(str, param) strcpy(__entry->__str_data__ + \
__str_loc_##str, param);

#define TRACE_EVENT(...) \
tstruct \
trace_current_buffer_unlock_commit(event, irq_flags, pc); \
}


The tstruct would do the assign for the user.

Then this is what a TRACE_EVENT would look like:

TRACE_EVENT(my_event,

TP_PROTO(char *str1, char *str2, char *str3),

TP_ARGS(str1, str2, str3),

TP_STRUCT__entry(
__string(str1, str1)
__string(str2, str2)
__string(str3, str3)
),

TP_fast_assign(
/* empty, strings are automated */
),

TP_printk("str1:%s str2:%s str3:%s\n",
__entry->__str_data__ + __entry->str1,
__entry->__str_data__ + __entry->str2,
__entry->__str_data__ + __entry->str3)
);


/me feels more evil than ever ;-)

-- Steve


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/