Search code examples
ckerneltracepoint

What happens to unused parameters in macro?


this question comes from reading the kernel, more specifically the trace macros. I got to them when I was studying how the kernel modules executes binary, elf and scripts files (fs/exec.c).

For some reason, I don't remember which got to the tracepoint.h file, where the macro TRACE_EVENT, among others, is defined. I'm using trace_event as an example because the trace example in the kernel uses this macro. The example has this use of the macro

    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 %s (%s)", __entry->foo, __entry->bar,
/*
 * Notice here the use of some helper functions. This includes:
 *
 *  __print_symbolic( variable, { value, "string" }, ... ),
 *
 *    The variable is tested against each value of the { } pair. If
 *    the variable matches one of the values, then it will print the
 *    string in that pair. If non are matched, it returns a string
 *    version of the number (if __entry->bar == 7 then "7" is returned).
 */
          __print_symbolic(__entry->bar,
                   { 0, "zero" },
                   { TRACE_SAMPLE_FOO, "TWO" },
                   { TRACE_SAMPLE_BAR, "FOUR" },
                   { TRACE_SAMPLE_ZOO, "EIGHT" },
                   { 10, "TEN" }
              ),

/*
 *  __print_flags( variable, "delim", { value, "flag" }, ... ),
 *
 *    This is similar to __print_symbolic, except that it tests the bits
 *    of the value. If ((FLAG & variable) == FLAG) then the string is
 *    printed. If more than one flag matches, then each one that does is
 *    also printed with delim in between them.
 *    If not all bits are accounted for, then the not found bits will be
 *    added in hex format: 0x506 will show BIT2|BIT4|0x500
 */
          __print_flags(__entry->bar, "|",
                { 1, "BIT1" },
                { 2, "BIT2" },
                { 4, "BIT3" },
                { 8, "BIT4" }
              ),
/*
 *  __print_array( array, len, element_size )
 *
 *    This prints out the array that is defined by __array in a nice format.
 */
          __print_array(__get_dynamic_array(list),
                __get_dynamic_array_len(list) / sizeof(int),
                sizeof(int)),
          __get_str(str), __get_bitmask(cpus))
);

So, naturally, after this I wentto the definition of TRACE_EVENT and found this

#define TRACE_EVENT(name, proto, args, struct, assign, print) \ DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))

As you can see, the trace_event macro does not use the print parameter (or argument?), as well as the struct and assign parameters.

It is very clearly stated that the macro needs them, but underneath it all it is simply calling the declare_trace macro which doesn't need them.

As for the rest of the continuation of the macro expansion I'm ok with it, nothing unexpected, but this particular usage of the macro bugs me. Do all the other fields serve some purpose or are they just ... there with no reason whatsoever for existing?


Solution

  • As correctly @pvg points, linux/tracepoint.h is just the tip of the iceberg of the tracepoints. This header only declares appropriate functions and types. That is why it doesn't handle some args for TRACE_EVENT.

    But the header with trace definitions is processed twice (or even more times), and next time all arguments to TRACE_EVENT are handled.

    More about tracepoints in Linux kernel see Documentation/trace/tracepoints.txt.