On 05/12/12 20:49, Mathieu Desnoyers wrote:
* David Bryant (david.bry...@quantum.com) wrote:
So, building on your example:

#define tracepoint_cond(provider, name, pre, post, ...) \
     do { \
         if (caa_unlikely(__tracepoint_##provider##___##name.state)) { \
             pre \
             __tracepoint_cb_##provider##___##name(__VA_ARGS__); \
             post \
         } \
     } \
     while (0)

And a contrived example:

#include <stdio.h>
#include <stdlib.h>

int main() {
     char * a;
     tracepoint_cond(provider, name,
                     { printf("pre\n");  a = malloc(16); },
                     { printf("post\n"); free(a);        }
                    );
     return 0;
}

This is ok. But more work with the macro handling would be required to
get the pre/post code fragments through as parameters. The example only
compiles because its pre/post arguments don't contain any commas.

What do you think?
I'm not sure what parameters would cause issues with commas. If they are
between parenthesis or brackets, it should be fine. Do you have an
example perhaps ?
Ok, I've just learnt what 'statement-expressions' are (http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html). Would this be the first use of these in lttng-ust? If so, I'm wary of making lttng-ust dependent on this gcc extension. Would it be dependent on this? It is up to the user to decide what to pass to the macro, but the macro may impose constraints by way of how the arguments are employed within the macro...

As it happens, we compile with -pedantic which won't allow statement-expressions. (As an aside, -pedantic doesn't like tracepoint that don't take any arguments because it expects the "..." to have at least one argument).

My example above (that doesn't use statement-expressions - I removed the round brackets) compiles correctly. But it you introduce a comma then the compiler seems to interpret this as an argument separator. So this works:

  #include <stdio.h>
  #include <stdlib.h>

  #define tracepoint_cond(provider, name, cond, pre, post, ...) \
      do { \
          if (caa_unlikely(__tracepoint_##provider##___##name.state)) { \
              if (cond) { \
                  pre \
__tracepoint_cb_##provider##___##name(__VA_ARGS__); \
                  post \
              } \
          } \
      } \
      while (0)

  int main() {
      int i = 1, j = 1;

      char * a;
      tracepoint_cond(provider, name,
                      i == j,  /* condition */
                      {   /* pre */
                      a = malloc(16);
                      memset(a, 0, 16);
                      },
                      {   /* post */
                      free(a);
                      int dummy1;
                      },
                      a
                     );
      return 0;
  }

But changing tracepoint_cond to this breaks it:

      tracepoint_cond(provider, name,
                      i == j,  /* condition */
                      {   /* pre */
                      a = malloc(16);
                      memset(a, 0, 16);
                      },
                      {   /* post */
                      free(a);
                      int dummy1, dummy2;  /* XXX */
                      },
                      a
                     );

Examining the pre-processed code reveals that the comma causes dummy2 to become a subsequent argument to the macro and land in the "..." region, and hell breaks loose.

Do you think we could come up with a scheme that doesn't impose the use of statement-expressions, but supports them if they are provided? In my example, I simply provide 'i == j' as the condition, but a statement-expression would also work. Are we conflating separate ideas - the idea of user conditions and the idea of setup/cleanup?

While we are there, it would be good to make the "pre" handler test a
condition. For your use-case, you would just have to pass a pre :

  { printf("pre\n");  a = malloc(16); 1; }

So we could do:

    if (pre)
         __tracepoint_cb_##provider##___##name(__VA_ARGS__);
    (post)

and therefore support not only to setup something, but also to add an
extra check on whether tracing should be skipped or not. If someone
passes "1" as end of the compound statement, it will always evaluate to
1, and therefore the compiler will remove any extra branch in -O2.

One question stands though: how would we integrate this with sdt.h
STAP_PROVEV() ?
I'm yet to look at this.

Thanks,
Dave

----------------------------------------------------------------------
The information contained in this transmission may be confidential. Any 
disclosure, copying, or further distribution of confidential information is not 
permitted unless such privilege is explicitly granted in writing by Quantum. 
Quantum reserves the right to have electronic communications, including email 
and attachments, sent across its networks filtered through anti virus and spam 
software programs and retain such messages in order to comply with applicable 
data security and retention requirements. Quantum is not responsible for the 
proper and complete transmission of the substance of this communication or for 
any delay in its receipt.

_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to