add trace event
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Thu, 22 Mar 2007 06:53:01 +0000 (06:53 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Thu, 22 Mar 2007 06:53:01 +0000 (06:53 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@2452 04897980-b3bd-0310-b5e0-8ef037075253

tests/kernel/trace-event.h

index c755503a552af3e45c298be9b35dfc0b80a9d46b..1f2eccac3f6650f7dce095f4079d26e78493015c 100644 (file)
 #define LTT_FLAG_CHANNEL       (1 << _LTT_FLAG_CHANNEL)
 #define LTT_FLAG_FORCE         (1 << _LTT_FLAG_FORCE)
 
+
+char *(*ltt_serialize_cb)(char *buffer, const char *fmt, va_list args);
+
+
+static int skip_atoi(const char **s)
+{
+       int i=0;
+
+       while (isdigit(**s))
+               i = i*10 + *((*s)++) - '0';
+       return i;
+}
+
+/* Inspired from vsnprintf */
+/* New types :
+ * %r : serialized pointer.
+ */
+static inline __attribute__((no_instrument_function))
+char *ltt_serialize_data(char *buffer, const char *fmt, va_list args)
+{
+       int len;
+       const char *s;
+       int elem_size;          /* Size of the integer for 'b' */
+                               /* Size of the data contained by 'r' */
+       int elem_alignment;     /* Element alignment for 'r' */
+       int qualifier;          /* 'h', 'l', or 'L' for integer fields */
+                               /* 'z' support added 23/7/1999 S.H.    */
+                               /* 'z' changed to 'Z' --davidm 1/25/99 */
+                               /* 't' added for ptrdiff_t */
+       char *str;              /* Pointer to write to */
+       ltt_serialize_cb cb;
+
+       str = buf;
+
+       for (; *fmt ; ++fmt) {
+               if (*fmt != '%') {
+                       /* Skip text */
+                       continue;
+               }
+
+               /* process flags : ignore standard print formats for now. */
+               repeat:
+                       ++fmt;          /* this also skips first '%' */
+                       switch (*fmt) {
+                               case '-':
+                               case '+':
+                               case ' ':
+                               case '#':
+                               case '0': goto repeat;
+                       }
+
+               /* get element size */
+               elem_size = -1;
+               if (isdigit(*fmt))
+                       elem_size = skip_atoi(&fmt);
+               else if (*fmt == '*') {
+                       ++fmt;
+                       /* it's the next argument */
+                       elem_size = va_arg(args, int);
+               }
+
+               /* get the alignment */
+               elem_alignment = -1;
+               if (*fmt == '.') {
+                       ++fmt;  
+                       if (isdigit(*fmt))
+                               elem_alignment = skip_atoi(&fmt);
+                       else if (*fmt == '*') {
+                               ++fmt;
+                               /* it's the next argument */
+                               elem_alignment = va_arg(args, int);
+                       }
+               }
+
+               /* get the conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+                   *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
+                       qualifier = *fmt;
+                       ++fmt;
+                       if (qualifier == 'l' && *fmt == 'l') {
+                               qualifier = 'L';
+                               ++fmt;
+                       }
+               }
+
+               switch (*fmt) {
+                       case 'c':
+                               if (buffer)
+                                       *str = (char) va_arg(args, int);
+                               str += sizeof(char);
+                               continue;
+
+                       case 's':
+                               s = va_arg(args, char *);
+                               if ((unsigned long)s < PAGE_SIZE)
+                                       s = "<NULL>";
+                               if (buffer)
+                                       strcpy(str, s);
+                               str += strlen(s);
+                               continue;
+
+                       case 'p':
+                               str += ltt_align(str, sizeof(void*));
+                               if (buffer)
+                                       *(void**)str = va_arg(args, void *);
+                               continue;
+
+                       case 'r':
+                               /* For array, struct, union */
+                               if (elem_alignment < 0)
+                                       elem_alignment = sizeof(void*);
+                               str += ltt_align(str, elem_alignment);
+                               if (elem_size > 0) {
+                                       const char *src = va_arg(args,
+                                                               const char *);
+                                       if (buffer)
+                                               memcpy(str, src, elem_size);
+                                       str += elem_size;
+                               }
+                               continue;
+
+                       case 'v':
+                               /* For sequence */
+                               str += ltt_align(str, sizeof(int));
+                               if (buffer)
+                                       *(int*)str = elem_size;
+                               str += sizeof(int);
+                               if (elem_alignment > 0)
+                                       str += ltt_align(str, elem_alignment);
+                               if (elem_size > 0) {
+                                       const char *src = va_arg(args,
+                                                               const char *);
+                                       if (buffer)
+                                               memcpy(str, src, elem_size);
+                                       str += elem_size;
+                               }
+                               continue;
+
+                       case 'k':
+                               /* For callback */
+                               cb = va_arg(args, ltt_serialize_cb);
+                                /* The callback will take as many arguments
+                                 * as it needs from args. They won't be
+                                 * type verified. */
+                               str = cb(str, fmt, args);
+                               continue;
+
+                       case 'n':
+                               /* FIXME:
+                               * What does C99 say about the overflow case here? */
+                               if (qualifier == 'l') {
+                                       long * ip = va_arg(args, long *);
+                                       *ip = (str - buf);
+                               } else if (qualifier == 'Z' || qualifier == 'z') {
+                                       size_t * ip = va_arg(args, size_t *);
+                                       *ip = (str - buf);
+                               } else {
+                                       int * ip = va_arg(args, int *);
+                                       *ip = (str - buf);
+                               }
+                               continue;
+
+                       case '%':
+                               continue;
+
+                       case 'o':
+                       case 'X':
+                       case 'x':
+                       case 'd':
+                       case 'i':
+                       case 'u':
+                               break;
+
+                       default:
+                               if (!*fmt)
+                                       --fmt;
+                               continue;
+               }
+               switch (qualifier) {
+               case 'L':
+                       str += ltt_align(str, sizeof(long long));
+                       if (buffer)
+                               *(long long*)str = va_arg(args, long long);
+                       str += sizeof(long long);
+                       break;
+               case 'l':
+                       str += ltt_align(str, sizeof(long));
+                       if (buffer)
+                               *(long*)str = va_arg(args, long);
+                       str += sizeof(long);
+                       break;
+               case 'Z':
+               case 'z':
+                       str += ltt_align(str, sizeof(size_t));
+                       if (buffer)
+                               *(size_t*)str = va_arg(args, size_t);
+                       str += sizeof(size_t);
+                       break;
+               case 't':
+                       str += ltt_align(str, sizeof(ptrdiff_t));
+                       if (buffer)
+                               *(ptrdiff_t*)str = va_arg(args, ptrdiff_t);
+                       str += sizeof(ptrdiff_t);
+                       break;
+               case 'h':
+                       str += ltt_align(str, sizeof(short));
+                       if (buffer)
+                               *(short*)str = (short) va_arg(args, int);
+                       str += sizeof(short);
+                       break;
+               case 'b':
+                       if (elem_size > 0)
+                               str += ltt_align(str, elem_size);
+                       if (buffer)
+                               switch (elem_size) {
+                               case 1:
+                                       *(int8_t*)str = (int8_t)va_arg(args, int);
+                                       break;
+                               case 2:
+                                       *(int16_t*)str = (int16_t)va_arg(args, int);
+                                       break;
+                               case 4:
+                                       *(int32_t*)str = va_arg(args, int32_t);
+                                       break;
+                               case 8:
+                                       *(int64_t*)str = va_arg(args, int64_t);
+                                       break;
+                               }
+                       str += elem_size;
+               default:
+                       str += ltt_align(str, sizeof(int));
+                       if (buffer)
+                               *(int*)str = va_arg(args, int);
+                       str += sizeof(int);
+               }
+       }
+       return str;
+}
+
 /* Calculate data size */
 /* Assume that the padding for alignment starts at a
  * sizeof(void *) address. */
@@ -24,50 +264,50 @@ static inline __attribute__((no_instrument_function))
 size_t ltt_get_data_size(ltt_facility_t fID, uint8_t eID,
                                const char *fmt, va_list args)
 {
-
-
-
+       return (size_t)ltt_serialize_data(NULL, fmt, args);
 }
 
 static inline __attribute__((no_instrument_function))
-size_t ltt_write_event_data(char *buffer,
+void ltt_write_event_data(char *buffer,
                                ltt_facility_t fID, uint8_t eID,
                                const char *fmt, va_list args)
 {
-
-
-
+       ltt_serialize_data(buffer, fmt, args);
 }
 
 
 __attribute__((no_instrument_function))
-void vtrace(ltt_facility_t fID, uint8_t eID, long flags, 
+void _vtrace(ltt_facility_t fID, uint8_t eID, long flags,
                const char *fmt, va_list args)
 {
        size_t data_size, slot_size;
-       uint8_t channel_index;
+       int channel_index;
        struct ltt_channel_struct *channel;
        struct ltt_trace_struct *trace, *dest_trace;
        void *transport_data;
        uint64_t tsc;
        char *buffer;
+       va_list args_copy;
 
        /* This test is useful for quickly exiting static tracing when no
         * trace is active. */
        if (likely(ltt_traces.num_active_traces == 0 && !(flags & LTT_FLAG_FORCE)))
                return;
 
-       data_size = ltt_get_data_size(fID, eID, fmt, args);
        preempt_disable();
        ltt_nesting[smp_processor_id()]++;
 
        if (unlikely(flags & LTT_FLAG_TRACE))
                dest_trace = va_arg(args, struct ltt_trace_struct *);
        if (unlikely(flags & LTT_FLAG_CHANNEL))
-               channel_index = va_arg(args, uint8_t);
+               channel_index = va_arg(args, int);
        else
                channel_index = ltt_get_channel_index(fID, eID);
 
+       va_copy(args_copy, args);       /* Check : skip 2 st args if trace/ch */
+       data_size = ltt_get_data_size(fID, eID, fmt, args_copy);
+       va_end(args_copy);
+
        /* Iterate on each traces */
        list_for_each_entry_rcu(trace, &ltt_traces.head, list) {
                if (unlikely(!trace->active && !(flags & LTT_FLAG_FORCE)))
@@ -83,7 +323,9 @@ void vtrace(ltt_facility_t fID, uint8_t eID, long flags,
                /* Out-of-order write : header and data */
                buffer = ltt_write_event_header(trace, channel, buffer,
                                                fID, eID, data_size, tsc);
-               ltt_write_event_data(buffer, fID, eID, fmt, args);
+               va_copy(args_copy, args);
+               ltt_write_event_data(buffer, fID, eID, fmt, args_copy);
+               va_end(args_copy);
                /* Out-of-order commit */
                ltt_commit_slot(channel, &transport_data, buffer, slot_size);
        }
@@ -93,12 +335,12 @@ void vtrace(ltt_facility_t fID, uint8_t eID, long flags,
 }
 
 __attribute__((no_instrument_function))
-void trace(ltt_facility_t fID, uint8_t eID, const char *fmt, ...)
+void _trace(ltt_facility_t fID, uint8_t eID, long flags, const char *fmt, ...)
 {
        va_list args;
 
        va_start(args, fmt);
-       vtrace(fmt, args);
+       _vtrace(fID, eID, flags, fmt, args);
        va_end(args);
 }
 
This page took 0.028472 seconds and 4 git commands to generate.