/* * If TRACE_SYSTEM is defined, that will be the directory created * in the ftrace directory under /sys/kernel/tracing/events/ * * The define_trace.h below will also look for a file name of * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. * In this case, it would look for sample.h * * If the header name will be different than the system name * (as in this case), then you can override the header name that * define_trace.h will look up by defining TRACE_INCLUDE_FILE * * This file is called trace-events-sample.h but we want the system * to be called "sample". Therefore we must define the name of this * file: * * #define TRACE_INCLUDE_FILE trace-events-sample * * As we do an the bottom of this file. * * Notice that TRACE_SYSTEM should be defined outside of #if * protection, just like TRACE_INCLUDE_FILE. */ #undef TRACE_SYSTEM #define TRACE_SYSTEM sample /* * Notice that this file is not protected like a normal header. * We also must allow for rereading of this file. The * * || defined(TRACE_HEADER_MULTI_READ) * * serves this purpose. */ #if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_EVENT_SAMPLE_H /* * All trace headers should include tracepoint.h, until we finally * make it into a standard header. */ #include /* * The TRACE_EVENT macro is broken up into 5 parts. * * name: name of the trace point. This is also how to enable the tracepoint. * A function called trace_foo_bar() will be created. * * proto: the prototype of the function trace_foo_bar() * Here it is trace_foo_bar(char *foo, int bar). * * args: must match the arguments in the prototype. * Here it is simply "foo, bar". * * struct: This defines the way the data will be stored in the ring buffer. * The items declared here become part of a special structure * called "__entry", which can be used in the fast_assign part of the * TRACE_EVENT macro. * * Here are the currently defined types you can use: * * __field : Is broken up into type and name. Where type can be any * primitive type (integer, long or pointer). * * __field(int, foo) * * __entry->foo = 5; * * __field_struct : This can be any static complex data type (struct, union * but not an array). Be careful using complex types, as each * event is limited in size, and copying large amounts of data * into the ring buffer can slow things down. * * __field_struct(struct bar, foo) * * __entry->bar.x = y; * __array: There are three fields (type, name, size). The type is the * type of elements in teh array, the name is the name of the array. * size is the number of items in the array (not the total size). * * __array( char, foo, 10) is the same as saying: char foo[10]; * * Assigning arrays can be done like any array: * * __entry->foo[0] = 'a'; * * memcpy(__entry->foo, bar, 10); * * __dynamic_array: This is similar to array, but can vary is size from * instance to instance of the tracepoint being called. * Like __array, this too has three elements (type, name, size); * type is the type of the element, name is the name of the array. * The size is different than __array. It is not a static number, * but the algorithm to figure out the length of the array for the * specific instance of tracepoint. Again, size is the numebr of * items in the array, not the total length in bytes. * * __dynamic_array( int, foo, bar) is similar to: int foo[bar]; * * Note, unlike arrays, you must use the __get_dynamic_array() macro * to access the array. * * memcpy(__get_dynamic_array(foo), bar, 10); * * Notice, that "__entry" is not needed here. * * __string: This is a special kind of __dynamic_array. It expects to * have a nul terminated character array passed to it (it allows * for NULL too, which would be converted into "(null)"). __string * takes two paramenter (name, src), where name is the name of * the string saved, and src is the string to copy into the * ring buffer. * * __string(foo, bar) is similar to: strcpy(foo, bar) * * To assign a string, use the helper macro __assign_str(). * * __assign_str(foo, bar); * * In most cases, the __assign_str() macro will take the same * parameters as the __string() macro had to declare the string. * * __bitmask: This is another kind of __dynamic_array, but it expects * an array of longs, and the number of bits to parse. It takes * two parameters (name, nr_bits), where name is the name of the * bitmask to save, and the nr_bits is the number of bits to record. * * __bitmask(target_cpu, nr_cpumask_bits) * * To assign a bitmask, use the __assign_bitmask() helper macro. * * __assign_bitmask(target_cpus, cpumask_bits(bar), nr_cpumask_bits); * * * fast_assign: This is a C like function that is used to store the items * into the ring buffer. A special variable called "__entry" will be the * structure that points into the ring buffer and has the same fields as * described by the struct part of TRACE_EVENT above. * * printk: This is a way to print out the data in pretty print. This is * useful if the system crashes and you are logging via a serial line, * the data can be printed to the console using this "printk" method. * This is also used to print out the data from the trace files. * Again, the __entry macro is used to access the data from the ring buffer. * * Note, __dynamic_array, __string, and __bitmask require special helpers * to access the data. * * For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo) * Use __get_dynamic_array_len(foo) to get the length of the array * saved. * * For __string(foo, bar) use __get_str(foo) * * For __bitmask(target_cpus, nr_cpumask_bits) use __get_bitmask(target_cpus) * * * Note, that for both the assign and the printk, __entry is the handler * to the data structure in the ring buffer, and is defined by the * TP_STRUCT__entry. */ /* * It is OK to have helper functions in the file, but they need to be protected * from being defined more than once. Remember, this file gets included more * than once. */ #ifndef __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS #define __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS static inline int __length_of(const int *list) { int i; if (!list) return 0; for (i = 0; list[i]; i++) ; return i; } #endif TRACE_EVENT(foo_bar, TP_PROTO(const char *foo, int bar, const int *lst, const char *string, const struct cpumask *mask), TP_ARGS(foo, bar, lst, string, mask), TP_STRUCT__entry( __array( char, foo, 10 ) __field( int, bar ) __dynamic_array(int, list, __length_of(lst)) __string( str, string ) __bitmask( cpus, num_possible_cpus() ) ), TP_fast_assign( strlcpy(__entry->foo, foo, 10); __entry->bar = bar; memcpy(__get_dynamic_array(list), lst, __length_of(lst) * sizeof(int)); __assign_str(str, string); __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus()); ), TP_printk("foo %s %d %s %s (%s)", __entry->foo, __entry->bar, __print_array(__get_dynamic_array(list), __get_dynamic_array_len(list), sizeof(int)), __get_str(str), __get_bitmask(cpus)) ); #endif /***** NOTICE! The #if protection ends here. *****/ /* * There are several ways I could have done this. If I left out the * TRACE_INCLUDE_PATH, then it would default to the kernel source * include/trace/events directory. * * I could specify a path from the define_trace.h file back to this * file. * * #define TRACE_INCLUDE_PATH ../../samples/trace_events * * But the safest and easiest way to simply make it use the directory * that the file is in is to add in the Makefile: * * CFLAGS_trace-events-sample.o := -I$(src) * * This will make sure the current path is part of the include * structure for our file so that define_trace.h can find it. * * I could have made only the top level directory the include: * * CFLAGS_trace-events-sample.o := -I$(PWD) * * And then let the path to this directory be the TRACE_INCLUDE_PATH: * * #define TRACE_INCLUDE_PATH samples/trace_events * * But then if something defines "samples" or "trace_events" as a macro * then we could risk that being converted too, and give us an unexpected * result. */ #undef TRACE_INCLUDE_PATH #undef TRACE_INCLUDE_FILE #define TRACE_INCLUDE_PATH . /* * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal */ #define TRACE_INCLUDE_FILE trace-events-sample #include