From mboxrd@z Thu Jan 1 00:00:00 1970 From: nils@as68123.uab.ericsson.se (Nils Carlson) Date: Wed, 25 Aug 2010 08:21:40 +0200 (CEST) Subject: [ltt-dev] [PATCH 1/2] Import TRACE_EVENT macro from the kernel In-Reply-To: <1282647883-6540-1-git-send-email-nils.carlson@ericsson.com> References: <1282647883-6540-1-git-send-email-nils.carlson@ericsson.com> Message-ID: Will fix there into Makefiles as well and taking an example from URCU I'll add a notice concerning the license. Also noticed that the copyright in the headers was quite flimsy, so I'll attribute all authors and as well. Pierre-Marc: Where do we have the LGPL license text? A grep for LGPL yields quite sparse output... /Nils On Tue, 24 Aug 2010, Nils Carlson wrote: > This is a slightly modified version of the TRACE_EVENT > macro from the kernel, TP_printf has replaced TP_printk. > > The TRACE_EVENT macro expansion is currently a dummy which > only expands to a printf probe, connected in a constructor. > > All copyright holders have approved, any contributions for which > approval is lacking are trivial. > --- > include/ust/define_trace.h | 98 ++++++++++++++++++++++++++++++++ > include/ust/kcompat/compiler.h | 1 + > include/ust/kcompat/stringify.h | 12 ++++ > include/ust/tracepoint.h | 119 +++++++++++++++++++++++++++++++++++++++ > include/ust/ust_trace.h | 56 ++++++++++++++++++ > 5 files changed, 286 insertions(+), 0 deletions(-) > create mode 100644 include/ust/define_trace.h > create mode 100644 include/ust/kcompat/stringify.h > create mode 100644 include/ust/ust_trace.h > > diff --git a/include/ust/define_trace.h b/include/ust/define_trace.h > new file mode 100644 > index 0000000..ec709a9 > --- /dev/null > +++ b/include/ust/define_trace.h > @@ -0,0 +1,98 @@ > +/* > + * Trace files that want to automate creationg of all tracepoints defined > + * in their file should include this file. The following are macros that the > + * trace file may define: > + * > + * TRACE_SYSTEM defines the system the tracepoint is for > + * > + * TRACE_INCLUDE_FILE if the file name is something other than TRACE_SYSTEM.h > + * This macro may be defined to tell define_trace.h what file to include. > + * Note, leave off the ".h". > + * > + * TRACE_INCLUDE_PATH if the path is something other than core kernel include/trace > + * then this macro can define the path to use. Note, the path is relative to > + * define_trace.h, not the file including it. Full path names for out of tree > + * modules must be used. > + */ > + > +#ifdef CREATE_TRACE_POINTS > + > +/* Prevent recursion */ > +#undef CREATE_TRACE_POINTS > + > +#include > + > +#undef TRACE_EVENT > +#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ > + DEFINE_TRACE(name) > + > +#undef TRACE_EVENT_FN > +#define TRACE_EVENT_FN(name, proto, args, tstruct, \ > + assign, print, reg, unreg) \ > + DEFINE_TRACE_FN(name, reg, unreg) > + > +#undef DEFINE_EVENT > +#define DEFINE_EVENT(template, name, proto, args) \ > + DEFINE_TRACE(name) > + > +#undef DEFINE_EVENT_PRINT > +#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ > + DEFINE_TRACE(name) > + > +#undef DECLARE_TRACE > +#define DECLARE_TRACE(name, proto, args) \ > + DEFINE_TRACE(name) > + > +#undef TRACE_INCLUDE > +#undef __TRACE_INCLUDE > + > +#ifndef TRACE_INCLUDE_FILE > +# define TRACE_INCLUDE_FILE TRACE_SYSTEM > +# define UNDEF_TRACE_INCLUDE_FILE > +#endif > + > +#ifndef TRACE_INCLUDE_PATH > +# define __TRACE_INCLUDE(system) > +# define UNDEF_TRACE_INCLUDE_PATH > +#else > +# define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h) > +#endif > + > +# define TRACE_INCLUDE(system) __TRACE_INCLUDE(system) > + > +/* Let the trace headers be reread */ > +#define TRACE_HEADER_MULTI_READ > + > +#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) > + > +/* Make all open coded DECLARE_TRACE nops */ > +#undef DECLARE_TRACE > +#define DECLARE_TRACE(name, proto, args) > + > +#ifndef CONFIG_NO_EVENT_TRACING > +#include > +#endif > + > +#undef TRACE_EVENT > +#undef TRACE_EVENT_FN > +#undef DECLARE_EVENT_CLASS > +#undef DEFINE_EVENT > +#undef DEFINE_EVENT_PRINT > +#undef TRACE_HEADER_MULTI_READ > +#undef DECLARE_TRACE > + > +/* Only undef what we defined in this file */ > +#ifdef UNDEF_TRACE_INCLUDE_FILE > +# undef TRACE_INCLUDE_FILE > +# undef UNDEF_TRACE_INCLUDE_FILE > +#endif > + > +#ifdef UNDEF_TRACE_INCLUDE_PATH > +# undef TRACE_INCLUDE_PATH > +# undef UNDEF_TRACE_INCLUDE_PATH > +#endif > + > +/* We may be processing more files */ > +#define CREATE_TRACE_POINTS > + > +#endif /* CREATE_TRACE_POINTS */ > diff --git a/include/ust/kcompat/compiler.h b/include/ust/kcompat/compiler.h > index d3ef8a1..f2fbd3e 100644 > --- a/include/ust/kcompat/compiler.h > +++ b/include/ust/kcompat/compiler.h > @@ -34,6 +34,7 @@ > #define __printf(a,b) __attribute__((format(printf,a,b))) > #define noinline __attribute__((noinline)) > #define __attribute_const__ __attribute__((__const__)) > +#define __used __attribute__((used)) > #define __maybe_unused __attribute__((unused)) > > #define notrace __attribute__((no_instrument_function)) > diff --git a/include/ust/kcompat/stringify.h b/include/ust/kcompat/stringify.h > new file mode 100644 > index 0000000..841cec8 > --- /dev/null > +++ b/include/ust/kcompat/stringify.h > @@ -0,0 +1,12 @@ > +#ifndef __LINUX_STRINGIFY_H > +#define __LINUX_STRINGIFY_H > + > +/* Indirect stringification. Doing two levels allows the parameter to be a > + * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) > + * converts to "bar". > + */ > + > +#define __stringify_1(x...) #x > +#define __stringify(x...) __stringify_1(x) > + > +#endif /* !__LINUX_STRINGIFY_H */ > diff --git a/include/ust/tracepoint.h b/include/ust/tracepoint.h > index be35f92..3409585 100644 > --- a/include/ust/tracepoint.h > +++ b/include/ust/tracepoint.h > @@ -43,6 +43,8 @@ struct tracepoint { > * Keep in sync with vmlinux.lds.h. > */ > > +#define PARAMS(args...) args > + > #define TP_PROTO(args...) args > #define TP_ARGS(args...) args > > @@ -206,4 +208,121 @@ extern int tracepoint_unregister_lib(struct tracepoint *tracepoints_start); > tracepoint_unregister_lib(__start___tracepoints); \ > } > > + > +#ifndef TRACE_EVENT > +/* > + * For use with the TRACE_EVENT macro: > + * > + * We define a tracepoint, its arguments, its printf format > + * and its 'fast binary record' layout. > + * > + * Firstly, name your tracepoint via TRACE_EVENT(name : the > + * 'subsystem_event' notation is fine. > + * > + * Think about this whole construct as the > + * 'trace_sched_switch() function' from now on. > + * > + * > + * TRACE_EVENT(sched_switch, > + * > + * * > + * * A function has a regular function arguments > + * * prototype, declare it via TP_PROTO(): > + * * > + * > + * TP_PROTO(struct rq *rq, struct task_struct *prev, > + * struct task_struct *next), > + * > + * * > + * * Define the call signature of the 'function'. > + * * (Design sidenote: we use this instead of a > + * * TP_PROTO1/TP_PROTO2/TP_PROTO3 ugliness.) > + * * > + * > + * TP_ARGS(rq, prev, next), > + * > + * * > + * * Fast binary tracing: define the trace record via > + * * TP_STRUCT__entry(). You can think about it like a > + * * regular C structure local variable definition. > + * * > + * * This is how the trace record is structured and will > + * * be saved into the ring buffer. These are the fields > + * * that will be exposed to readers. > + * * > + * * The declared 'local variable' is called '__entry' > + * * > + * * __field(pid_t, prev_prid) is equivalent to a standard declariton: > + * * > + * * pid_t prev_pid; > + * * > + * * __array(char, prev_comm, TASK_COMM_LEN) is equivalent to: > + * * > + * * char prev_comm[TASK_COMM_LEN]; > + * * > + * > + * TP_STRUCT__entry( > + * __array( char, prev_comm, TASK_COMM_LEN ) > + * __field( pid_t, prev_pid ) > + * __field( int, prev_prio ) > + * __array( char, next_comm, TASK_COMM_LEN ) > + * __field( pid_t, next_pid ) > + * __field( int, next_prio ) > + * ), > + * > + * * > + * * Assign the entry into the trace record, by embedding > + * * a full C statement block into TP_fast_assign(). You > + * * can refer to the trace record as '__entry' - > + * * otherwise you can put arbitrary C code in here. > + * * > + * * Note: this C code will execute every time a trace event > + * * happens, on an active tracepoint. > + * * > + * > + * TP_fast_assign( > + * memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN); > + * __entry->prev_pid = prev->pid; > + * __entry->prev_prio = prev->prio; > + * memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); > + * __entry->next_pid = next->pid; > + * __entry->next_prio = next->prio; > + * ) > + * > + * * > + * * Formatted output of a trace record via TP_printf(). > + * * This is how the tracepoint will appear under debugging > + * * of tracepoints. > + * * > + * * (raw-binary tracing wont actually perform this step.) > + * * > + * > + * TP_printf("task %s:%d [%d] ==> %s:%d [%d]", > + * __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, > + * __entry->next_comm, __entry->next_pid, __entry->next_prio), > + * > + * ); > + * > + * This macro construct is thus used for the regular printf format > + * tracing setup. > + * > + * A set of (un)registration functions can be passed to the variant > + * TRACE_EVENT_FN to perform any (un)registration work. > + */ > + > +#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) > +#define DEFINE_EVENT(template, name, proto, args) \ > + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) > +#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ > + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) > + > +#define TRACE_EVENT(name, proto, args, struct, assign, print) \ > + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) > +#define TRACE_EVENT_FN(name, proto, args, struct, \ > + assign, print, reg, unreg) \ > + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) > + > +#endif /* ifdef TRACE_EVENT (see note above) */ > + > + > #endif /* _UST_TRACEPOINT_H */ > diff --git a/include/ust/ust_trace.h b/include/ust/ust_trace.h > new file mode 100644 > index 0000000..d1a0e17 > --- /dev/null > +++ b/include/ust/ust_trace.h > @@ -0,0 +1,56 @@ > +/* > + * This whole file is currently a dummy, mapping a TRACE_EVENT > + * to a printf > + */ > + > +/* > + * Stage 1. Create a struct and a printf calling function > + * that is connected to the tracepoint at load time. > + */ > +#undef TRACE_EVENT > +#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ > + DECLARE_EVENT_CLASS(name, \ > + PARAMS(proto), \ > + PARAMS(args), \ > + PARAMS(tstruct), \ > + PARAMS(assign), \ > + PARAMS(print)); \ > + DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)); > + > +#undef __field > +#define __field(type, item) type item; > + > +#undef TP_STRUCT__entry > +#define TP_STRUCT__entry(args...) args > + > +#undef TP_printf > +#define TP_printf(fmt, args...) fmt "\n", args > + > +#undef TP_fast_assign > +#define TP_fast_assign(args...) args > + > +#undef DEFINE_EVENT > +#define DEFINE_EVENT(template, name, proto, args) > + > + > +#undef DECLARE_EVENT_CLASS > +#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \ > + struct trace_raw_##name { \ > + tstruct \ > + }; \ > + static void trace_printf_##name(proto) \ > + { \ > + struct trace_raw_##name entry_struct, *__entry; \ > + __entry = &entry_struct; \ > + { assign }; \ > + \ > + printf(print); \ > + } \ > + static void __attribute__((constructor)) init_##name() \ > + { \ > + printf("connecting tracepoint " #name "\n"); \ > + register_trace_##name(trace_printf_##name); \ > + } > + > + > +#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) > -- > 1.7.1 > >