X-Git-Url: https://git.lttng.org/?p=ust.git;a=blobdiff_plain;f=libust%2Fserialize.c;h=8f393ed074d08ad98836db24e39ae729cd0f0122;hp=d603815b50621e74332f96301d1b6b9a38266200;hb=bf0d695d692163edb23b8fbbbd976387dfef232d;hpb=b5b073e22d34bec71259d39b8946354f170f01a9 diff --git a/libust/serialize.c b/libust/serialize.c index d603815..8f393ed 100644 --- a/libust/serialize.c +++ b/libust/serialize.c @@ -24,6 +24,9 @@ * va_list * to ltt_vtrace. */ +#define _GNU_SOURCE +#include +#include #include #include #include @@ -38,6 +41,7 @@ #include "tracer.h" //#include "list.h" #include "usterr.h" +#include "ust_snprintf.h" enum ltt_type { LTT_TYPE_SIGNED_INT, @@ -46,6 +50,11 @@ enum ltt_type { LTT_TYPE_NONE, }; +static int ust_get_cpu(void) +{ + return sched_getcpu(); +} + #define LTT_ATTRIBUTE_NETWORK_BYTE_ORDER (1<<1) /* @@ -248,8 +257,9 @@ parse_end: * Field width and precision are *not* supported. * %n not supported. */ -static inline const char *parse_c_type(const char *fmt, - char *c_size, enum ltt_type *c_type) +static inline +const char *parse_c_type(const char *fmt, char *c_size, enum ltt_type *c_type, + char *outfmt) { int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ @@ -281,6 +291,13 @@ repeat: } } + if (outfmt) { + if (qualifier != -1) + *outfmt++ = (char)qualifier; + *outfmt++ = *fmt; + *outfmt = 0; + } + switch (*fmt) { case 'c': *c_type = LTT_TYPE_UNSIGNED_INT; @@ -374,16 +391,13 @@ static inline size_t serialize_trace_data(struct ust_buffer *buf, case LTT_TYPE_UNSIGNED_INT: switch (c_size) { case 1: - tmp.v_ulong = (unsigned long)(uint8_t) - va_arg(*args, unsigned int); + tmp.v_ulong = (unsigned long)(uint8_t)va_arg(*args, unsigned int); break; case 2: - tmp.v_ulong = (unsigned long)(uint16_t) - va_arg(*args, unsigned int); + tmp.v_ulong = (unsigned long)(uint16_t)va_arg(*args, unsigned int); break; case 4: - tmp.v_ulong = (unsigned long)(uint32_t) - va_arg(*args, unsigned int); + tmp.v_ulong = (unsigned long)(uint32_t)va_arg(*args, unsigned int); break; case 8: tmp.v_uint64 = va_arg(*args, uint64_t); @@ -497,92 +511,6 @@ copydone: return buf_offset; } -static notrace void skip_space(const char **ps) -{ - while(**ps == ' ') - (*ps)++; -} - -static notrace void copy_token(char **out, const char **in) -{ - while(**in != ' ' && **in != '\0') { - **out = **in; - (*out)++; - (*in)++; - } -} - -/* serialize_to_text - * - * Given a format string and a va_list of arguments, convert them to a - * human-readable string. - * - * @outbuf: the buffer to output the string to - * @bufsize: the max size that can be used in outbuf - * @fmt: the marker format string - * @ap: a va_list that contains the arguments corresponding to fmt - * - * Return value: the number of chars that have been put in outbuf, excluding - * the final \0, or, if the buffer was too small, the number of chars that - * would have been written in outbuf if it had been large enough. - * - * outbuf may be NULL. The return value may then be used be allocate an - * appropriate outbuf. - * - */ - -notrace -int serialize_to_text(char *outbuf, int bufsize, const char *fmt, va_list ap) -{ - int fmt_len = strlen(fmt); - char *new_fmt = alloca(fmt_len + 1); - const char *orig_fmt_p = fmt; - char *new_fmt_p = new_fmt; - char false_buf; - int result; - enum { none, cfmt, tracefmt, argname } prev_token = none; - - while(*orig_fmt_p != '\0') { - if(*orig_fmt_p == '%') { - prev_token = cfmt; - copy_token(&new_fmt_p, &orig_fmt_p); - } - else if(*orig_fmt_p == '#') { - prev_token = tracefmt; - do { - orig_fmt_p++; - } while(*orig_fmt_p != ' ' && *orig_fmt_p != '\0'); - } - else if(*orig_fmt_p == ' ') { - if(prev_token == argname) { - *new_fmt_p = '='; - new_fmt_p++; - } - else if(prev_token == cfmt) { - *new_fmt_p = ' '; - new_fmt_p++; - } - - skip_space(&orig_fmt_p); - } - else { - prev_token = argname; - copy_token(&new_fmt_p, &orig_fmt_p); - } - } - - *new_fmt_p = '\0'; - - if(outbuf == NULL) { - /* use this false_buffer for compatibility with pre-C99 */ - outbuf = &false_buf; - bufsize = 1; - } - result = vsnprintf(outbuf, bufsize, new_fmt, ap); - - return result; -} - notrace size_t ltt_serialize_data(struct ust_buffer *buf, size_t buf_offset, struct ltt_serialize_closure *closure, void *serialize_private, int *largest_align, @@ -610,7 +538,7 @@ notrace size_t ltt_serialize_data(struct ust_buffer *buf, size_t buf_offset, ++fmt; /* skip first '%' */ if (*fmt == '%') /* Escaped %% */ break; - fmt = parse_c_type(fmt, &c_size, &c_type); + fmt = parse_c_type(fmt, &c_size, &c_type, NULL); /* * Output c types if no trace types has been * specified. @@ -675,7 +603,7 @@ notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, size_t data_size, slot_size; unsigned int chan_index; struct ust_channel *channel; - struct ltt_trace_struct *trace, *dest_trace = NULL; + struct ust_trace *trace, *dest_trace = NULL; struct ust_buffer *buf; void *transport_data; u64 tsc; @@ -684,7 +612,7 @@ notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, struct ltt_serialize_closure closure; struct ltt_probe_private_data *private_data = call_data; void *serialize_private = NULL; -//ust// int cpu; + int cpu; unsigned int rflags; /* @@ -696,7 +624,9 @@ notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, rcu_read_lock(); //ust// rcu_read_lock_sched_notrace(); //ust// cpu = smp_processor_id(); + cpu = ust_get_cpu(); //ust// __get_cpu_var(ltt_nesting)++; + /* FIXME: should nesting be per-cpu? */ ltt_nesting++; pdata = (struct ltt_active_marker *)probe_data; @@ -750,29 +680,36 @@ notrace void ltt_vtrace(const struct marker *mdata, void *probe_data, if (!channel->active) continue; + /* If a new cpu was plugged since the trace was started, we did + * not add it to the trace, and therefore we write the event to + * cpu 0. + */ + if(cpu >= channel->n_cpus) { + cpu = 0; + } + /* reserve space : header and data */ ret = ltt_reserve_slot(trace, channel, &transport_data, data_size, &slot_size, &buf_offset, &tsc, &rflags, - largest_align); + largest_align, cpu); if (unlikely(ret < 0)) continue; /* buffer full */ va_copy(args_copy, *args); /* FIXME : could probably encapsulate transport better. */ //ust// buf = ((struct rchan *)channel->trans_channel_data)->buf[cpu]; - buf = channel->buf; + buf = channel->buf[cpu]; /* Out-of-order write : header and data */ buf_offset = ltt_write_event_header(trace, - buf, buf_offset, + channel, buf, buf_offset, eID, data_size, tsc, rflags); ltt_write_event_data(buf, buf_offset, &closure, serialize_private, largest_align, fmt, &args_copy); va_end(args_copy); /* Out-of-order commit */ - ltt_commit_slot(channel, &transport_data, buf_offset, - data_size, slot_size); + ltt_commit_slot(channel, buf, buf_offset, data_size, slot_size); DBG("just commited event at offset %ld and size %zd", buf_offset, slot_size); } //ust// __get_cpu_var(ltt_nesting)--; @@ -791,6 +728,88 @@ notrace void ltt_trace(const struct marker *mdata, void *probe_data, va_end(args); } -//ust// MODULE_LICENSE("GPL"); -//ust// MODULE_AUTHOR("Mathieu Desnoyers"); -//ust// MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Serializer"); +static notrace void skip_space(const char **ps) +{ + while(**ps == ' ') + (*ps)++; +} + +static notrace void copy_token(char **out, const char **in) +{ + while(**in != ' ' && **in != '\0') { + **out = **in; + (*out)++; + (*in)++; + } +} + +/* serialize_to_text + * + * Given a format string and a va_list of arguments, convert them to a + * human-readable string. + * + * @outbuf: the buffer to output the string to + * @bufsize: the max size that can be used in outbuf + * @fmt: the marker format string + * @ap: a va_list that contains the arguments corresponding to fmt + * + * Return value: the number of chars that have been put in outbuf, excluding + * the final \0, or, if the buffer was too small, the number of chars that + * would have been written in outbuf if it had been large enough. + * + * outbuf may be NULL. The return value may then be used be allocate an + * appropriate outbuf. + * + */ + +notrace +int serialize_to_text(char *outbuf, int bufsize, const char *fmt, va_list ap) +{ + int fmt_len = strlen(fmt); + char *new_fmt = alloca(fmt_len + 1); + const char *orig_fmt_p = fmt; + char *new_fmt_p = new_fmt; + char false_buf; + int result; + enum { none, cfmt, tracefmt, argname } prev_token = none; + + while(*orig_fmt_p != '\0') { + if(*orig_fmt_p == '%') { + prev_token = cfmt; + copy_token(&new_fmt_p, &orig_fmt_p); + } + else if(*orig_fmt_p == '#') { + prev_token = tracefmt; + do { + orig_fmt_p++; + } while(*orig_fmt_p != ' ' && *orig_fmt_p != '\0'); + } + else if(*orig_fmt_p == ' ') { + if(prev_token == argname) { + *new_fmt_p = '='; + new_fmt_p++; + } + else if(prev_token == cfmt) { + *new_fmt_p = ' '; + new_fmt_p++; + } + + skip_space(&orig_fmt_p); + } + else { + prev_token = argname; + copy_token(&new_fmt_p, &orig_fmt_p); + } + } + + *new_fmt_p = '\0'; + + if(outbuf == NULL) { + /* use this false_buffer for compatibility with pre-C99 */ + outbuf = &false_buf; + bufsize = 1; + } + result = ust_safe_vsnprintf(outbuf, bufsize, new_fmt, ap); + + return result; +}