From d793d5e111fe1436fb8e15daa5d7fb1be8987bb4 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 14 May 2011 12:59:11 -0400 Subject: [PATCH] Packet headers and alignment Signed-off-by: Mathieu Desnoyers --- ltt-events.c | 53 ++++++++++++++++++++-- ltt-events.h | 4 +- ltt-ring-buffer-client.h | 73 ++++++++++++++++++++----------- ltt-ring-buffer-metadata-client.h | 6 +-- ltt-tracer.h | 59 +++++-------------------- probes/lttng-events.h | 26 ++++++----- probes/lttng-types.h | 1 + 7 files changed, 130 insertions(+), 92 deletions(-) diff --git a/ltt-events.c b/ltt-events.c index 1d729210..db1ac86f 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ #include "ltt-events.h" #include "ltt-tracer.h" @@ -48,6 +49,7 @@ struct ltt_session *ltt_session_create(void) return NULL; INIT_LIST_HEAD(&session->chan); INIT_LIST_HEAD(&session->events); + uuid_le_gen(&session->uuid); list_add(&session->list, &sessions); mutex_unlock(&sessions_mutex); return session; @@ -316,10 +318,11 @@ int lttng_metadata_printf(struct ltt_session *session, ret != -ENOBUFS || !ret; }), msecs_to_jiffies(LTTNG_METADATA_TIMEOUT_MSEC)); - if (waitret || ret) { + if (!waitret || waitret == -ERESTARTSYS || ret) { printk(KERN_WARNING "LTTng: Failure to write metadata to buffers (%s)\n", waitret == -ERESTARTSYS ? "interrupted" : (ret == -ENOBUFS ? "timeout" : "I/O error")); + printk("waitret %d retval %d\n", waitret, ret); if (waitret == -ERESTARTSYS) ret = waitret; goto end; @@ -459,7 +462,7 @@ int _ltt_event_metadata_statedump(struct ltt_session *session, */ ret = lttng_metadata_printf(session, " } aligned(%u);\n" - "};\n", ltt_get_header_alignment()); + "};\n\n", ltt_get_header_alignment()); if (ret) goto end; @@ -488,7 +491,7 @@ int _ltt_channel_metadata_statedump(struct ltt_session *session, "stream {\n" " id = %u;\n" " event.header := %s;\n", - "};\n", + "};\n\n", chan->id, chan->header_type == 1 ? "struct event_header_compact" : "struct event_header_large"); @@ -506,6 +509,7 @@ end: static int _ltt_session_metadata_statedump(struct ltt_session *session) { + char uuid_s[37]; struct ltt_channel *chan; struct ltt_event *event; int ret = 0; @@ -519,6 +523,49 @@ int _ltt_session_metadata_statedump(struct ltt_session *session) return -EPERM; } + snprintf(uuid_s, sizeof(uuid_s), + "%x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x%x", + uuid_s[0], uuid_s[1], uuid_s[2], uuid_s[3], + uuid_s[4], uuid_s[5], uuid_s[6], uuid_s[7], + uuid_s[8], uuid_s[9], uuid_s[10], uuid_s[11], + uuid_s[12], uuid_s[13], uuid_s[14], uuid_s[15]); + + ret = lttng_metadata_printf(session, + "typealias integer {size = 8; align = %u; signed = false; } := uint8_t;\n" + "typealias integer {size = 32; align = %u; signed = false; } := uint32_t;\n" + "typealias integer {size = 64; align = %u; signed = false; } := uint64_t;\n" + "\n" + "trace {\n" + " major = %u;\n" + " minor = %u;\n" + " uuid = %s;\n" + " byte_order = %s;\n" + " packet.header := struct {\n" + " uint32_t magic;\n" + " uint8_t trace_uuid[16];\n" + " uint32_t stream_id;\n" + " uint64_t timestamp_begin;\n" + " uint64_t timestamp_end;\n" + " uint32_t content_size;\n" + " uint32_t packet_size;\n" + " uint32_t events_lost;\n" + " };\n", + "};\n\n", + ltt_alignof(uint8_t) * CHAR_BIT, + ltt_alignof(uint32_t) * CHAR_BIT, + ltt_alignof(uint64_t) * CHAR_BIT, + CTF_VERSION_MAJOR, + CTF_VERSION_MINOR, + uuid_s, +#ifdef __BIG_ENDIAN + "be" +#else + "le" +#endif + ); + if (ret) + goto end; + skip_session: list_for_each_entry(chan, &session->chan, list) { ret = _ltt_channel_metadata_statedump(session, chan); diff --git a/ltt-events.h b/ltt-events.h index 3bacac78..5b5dcb50 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -10,6 +10,7 @@ */ #include +#include #include "ltt-debugfs-abi.h" struct ltt_channel; @@ -46,7 +47,7 @@ struct lttng_enum_entry { .u.basic.integer = \ { \ .size = sizeof(_type), \ - .alignment = __alignof__(_type), \ + .alignment = ltt_alignof(_type) * CHAR_BIT, \ .signedness = is_signed_type(_type), \ .reverse_byte_order = _byte_order != __BYTE_ORDER, \ }, \ @@ -171,6 +172,7 @@ struct ltt_session { struct list_head events; /* Event list head */ struct list_head list; /* Session list */ unsigned int free_chan_id; /* Next chan ID to allocate */ + uuid_le uuid; /* Trace session unique ID */ int metadata_dumped:1; }; diff --git a/ltt-ring-buffer-client.h b/ltt-ring-buffer-client.h index 9056dd79..aa763837 100644 --- a/ltt-ring-buffer-client.h +++ b/ltt-ring-buffer-client.h @@ -15,6 +15,41 @@ #include "ltt-events.h" #include "ltt-tracer.h" +/* + * Keep the natural field alignment for _each field_ within this structure if + * you ever add/remove a field from this header. Packed attribute is not used + * because gcc generates poor code on at least powerpc and mips. Don't ever + * let gcc add padding between the structure elements. + */ +struct packet_header { + uint32_t magic; /* + * Trace magic number. + * contains endianness information. + */ + uint8_t trace_uuid[16]; + uint32_t stream_id; + uint64_t timestamp_begin; /* Cycle count at subbuffer start */ + uint64_t timestamp_end; /* Cycle count at subbuffer end */ + uint32_t content_size; /* Size of data in subbuffer */ + uint32_t packet_size; /* Subbuffer size (include padding) */ + uint32_t events_lost; /* + * Events lost in this subbuffer since + * the beginning of the trace. + * (may overflow) + */ +#if 0 + uint64_t start_time_sec; /* NTP-corrected start time */ + uint64_t start_time_usec; + uint64_t start_freq; /* + * Frequency at trace start, + * used all along the trace. + */ + uint32_t freq_scale; /* Frequency scaling (divisor) */ +#endif //0 + uint8_t header_end[0]; /* End of header */ +}; + + static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan) { return trace_clock_read64(); @@ -122,29 +157,6 @@ slow_path: ltt_write_event_header_slow(config, ctx, eID, event_size); } -/** - * ltt_write_trace_header - Write trace header - * @priv: Private data (struct trace) - * @header: Memory address where the information must be written to - */ -static __inline__ -void write_trace_header(const struct lib_ring_buffer_config *config, - struct packet_header *header) -{ - header->magic = CTF_MAGIC_NUMBER; -#if 0 - /* TODO: move start time to metadata */ - header->major_version = LTT_TRACER_VERSION_MAJOR; - header->minor_version = LTT_TRACER_VERSION_MINOR; - header->arch_size = sizeof(void *); - header->alignment = lib_ring_buffer_get_alignment(config); - header->start_time_sec = ltt_chan->session->start_time.tv_sec; - header->start_time_usec = ltt_chan->session->start_time.tv_usec; - header->start_freq = ltt_chan->session->start_freq; - header->freq_scale = ltt_chan->session->freq_scale; -#endif //0 -} - void ltt_write_event_header_slow(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_ctx *ctx, u16 eID, u32 event_size) @@ -234,10 +246,21 @@ static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, (struct packet_header *) lib_ring_buffer_offset_address(&buf->backend, subbuf_idx * chan->backend.subbuf_size); + struct ltt_session *session = channel_get_private(chan); + header->magic = CTF_MAGIC_NUMBER; + memcpy(header->trace_uuid, session->uuid.b, sizeof(session->uuid)); header->timestamp_begin = tsc; + header->timestamp_end = 0; header->content_size = 0xFFFFFFFF; /* for debugging */ - write_trace_header(&client_config, header); + header->packet_size = 0xFFFFFFFF; + header->events_lost = 0; +#if 0 + header->start_time_sec = ltt_chan->session->start_time.tv_sec; + header->start_time_usec = ltt_chan->session->start_time.tv_usec; + header->start_freq = ltt_chan->session->start_freq; + header->freq_scale = ltt_chan->session->freq_scale; +#endif //0 } /* @@ -254,9 +277,9 @@ static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, subbuf_idx * chan->backend.subbuf_size); unsigned long records_lost = 0; + header->timestamp_end = tsc; header->content_size = data_size; header->packet_size = PAGE_ALIGN(data_size); - header->timestamp_end = tsc; records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf); records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); diff --git a/ltt-ring-buffer-metadata-client.h b/ltt-ring-buffer-metadata-client.h index a0f6f9e1..c6dce5f9 100644 --- a/ltt-ring-buffer-metadata-client.h +++ b/ltt-ring-buffer-metadata-client.h @@ -86,10 +86,10 @@ static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, (struct metadata_packet_header *) lib_ring_buffer_offset_address(&buf->backend, subbuf_idx * chan->backend.subbuf_size); + struct ltt_session *session = channel_get_private(chan); header->magic = TSDL_MAGIC_NUMBER; - /* TODO */ - //header->trace_uuid = ; /* Unique Universal Identifier */ + memcpy(header->trace_uuid, session->uuid.b, sizeof(session->uuid)); header->checksum = 0; /* 0 if unused */ header->content_size = 0xFFFFFFFF; /* in bits, for debugging */ header->packet_size = 0xFFFFFFFF; /* in bits, for debugging */ @@ -106,7 +106,7 @@ static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, unsigned int subbuf_idx, unsigned long data_size) { struct channel *chan = buf->backend.chan; - struct packet_header *header = + struct metadata_packet_header *header = (struct packet_header *) lib_ring_buffer_offset_address(&buf->backend, subbuf_idx * chan->backend.subbuf_size); diff --git a/ltt-tracer.h b/ltt-tracer.h index 3bb55234..f1cd2d90 100644 --- a/ltt-tracer.h +++ b/ltt-tracer.h @@ -113,66 +113,29 @@ struct event_header { #define LTT_MAX_SMALL_SIZE 0xFFFFU +#ifdef RING_BUFFER_ALIGN static inline size_t ltt_get_header_alignment(void) { -#ifdef RING_BUFFER_ALIGN return sizeof(struct event_header) * CHAR_BIT; +} + +#define ltt_alignof(type) __alignof__(type) #else +static inline +size_t ltt_get_header_alignment(void) +{ return CHAR_BIT; -#endif } -/* - * We use asm/timex.h : cpu_khz/HZ variable in here : we might have to deal - * specifically with CPU frequency scaling someday, so using an interpolation - * between the start and end of buffer values is not flexible enough. Using an - * immediate frequency value permits to calculate directly the times for parts - * of a buffer that would be before a frequency change. - * - * Keep the natural field alignment for _each field_ within this structure if - * you ever add/remove a field from this header. Packed attribute is not used - * because gcc generates poor code on at least powerpc and mips. Don't ever - * let gcc add padding between the structure elements. - */ -struct packet_header { - uint32_t magic; /* - * Trace magic number. - * contains endianness information. - */ - uint8_t trace_uuid[16]; - uint32_t stream_id; - uint64_t timestamp_begin; /* Cycle count at subbuffer start */ - uint64_t timestamp_end; /* Cycle count at subbuffer end */ - uint32_t content_size; /* Size of data in subbuffer */ - uint32_t packet_size; /* Subbuffer size (include padding) */ - uint32_t events_lost; /* - * Events lost in this subbuffer since - * the beginning of the trace. - * (may overflow) - */ - /* TODO: move to metadata */ -#if 0 - uint8_t major_version; - uint8_t minor_version; - uint8_t arch_size; /* Architecture pointer size */ - uint8_t alignment; /* LTT data alignment */ - uint64_t start_time_sec; /* NTP-corrected start time */ - uint64_t start_time_usec; - uint64_t start_freq; /* - * Frequency at trace start, - * used all along the trace. - */ - uint32_t freq_scale; /* Frequency scaling (divisor) */ -#endif //0 - uint8_t header_end[0]; /* End of header */ -}; +#define ltt_alignof(type) 1 +#endif /* Tracer properties */ #define CTF_MAGIC_NUMBER 0xC1FC1FC1 #define TSDL_MAGIC_NUMBER 0x75D11D57 -#define LTT_TRACER_VERSION_MAJOR 3 -#define LTT_TRACER_VERSION_MINOR 0 +#define CTF_VERSION_MAJOR 0 +#define CTF_VERSION_MINOR 1 /* * Number of milliseconds to retry before failing metadata writes on buffer full diff --git a/probes/lttng-events.h b/probes/lttng-events.h index f64e0217..5ee61bc6 100644 --- a/probes/lttng-events.h +++ b/probes/lttng-events.h @@ -222,7 +222,7 @@ static struct lttng_probe_desc TP_ID(__probe_desc___, TRACE_SYSTEM) = { #undef __field #define __field(_type, _item) \ - __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ + __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ __event_len += sizeof(_type); #undef __field_ext @@ -230,14 +230,14 @@ static struct lttng_probe_desc TP_ID(__probe_desc___, TRACE_SYSTEM) = { #undef __array #define __array(_type, _item, _length) \ - __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ + __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ __event_len += sizeof(_type) * (_length); #undef __dynamic_array #define __dynamic_array(_type, _item, _length) \ - __event_len += lib_ring_buffer_align(__event_len, __alignof__(u32)); \ + __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(u32)); \ __event_len += sizeof(u32); \ - __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ + __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ __event_len += sizeof(_type) * (_length); #undef __string @@ -277,19 +277,19 @@ static inline size_t __event_get_size__##_name(size_t *__dynamic_len, _proto) \ #undef __field #define __field(_type, _item) \ - __event_align = max_t(size_t, __event_align, __alignof__(_type)); + __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); #undef __field_ext #define __field_ext(_type, _item, _filter_type) __field(_type, _item) #undef __array #define __array(_type, _item, _length) \ - __event_align = max_t(size_t, __event_align, __alignof__(_type)); + __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); #undef __dynamic_array #define __dynamic_array(_type, _item, _length) \ - __event_align = max_t(size_t, __event_align, __alignof__(u32)); \ - __event_align = max_t(size_t, __event_align, __alignof__(_type)); + __event_align = max_t(size_t, __event_align, ltt_alignof(u32)); \ + __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); #undef __string #define __string(_item, _src) @@ -397,7 +397,7 @@ __end_field_##_item: __assign_##dest: \ { \ __typeof__(__typemap.dest) __tmp = (src); \ - lib_ring_buffer_align_ctx(&ctx, __alignof__(__tmp)); \ + lib_ring_buffer_align_ctx(&ctx, ltt_alignof(__tmp)); \ __chan->ops->event_write(&ctx, &__tmp, sizeof(__tmp)); \ } \ goto __end_field_##dest; @@ -405,7 +405,9 @@ __assign_##dest: \ #undef tp_memcpy #define tp_memcpy(dest, src, len) \ __assign_##dest: \ - lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest)); \ + if (0) \ + (void) __typemap.dest; \ + lib_ring_buffer_align_ctx(&ctx, ltt_alignof(__typemap.dest)); \ __chan->ops->event_write(&ctx, src, len); \ goto __end_field_##dest; @@ -414,12 +416,12 @@ __assign_##dest: \ __assign_##dest##_1: \ { \ u32 __tmpl = (len); \ - lib_ring_buffer_align_ctx(&ctx, __alignof__(u32)); \ + lib_ring_buffer_align_ctx(&ctx, ltt_alignof(u32)); \ __chan->ops->event_write(&ctx, &__tmpl, sizeof(u32)); \ } \ goto __end_field_##dest##_1; \ __assign_##dest##_2: \ - lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest)); \ + lib_ring_buffer_align_ctx(&ctx, ltt_alignof(__typemap.dest)); \ __chan->ops->event_write(&ctx, src, len); \ goto __end_field_##dest##_2; diff --git a/probes/lttng-types.h b/probes/lttng-types.h index bbae8747..5a7a6554 100644 --- a/probes/lttng-types.h +++ b/probes/lttng-types.h @@ -8,6 +8,7 @@ #include #include "lttng.h" #include "../ltt-events.h" +#include "../ltt-tracer.h" #ifdef __KERNEL__ # include -- 2.34.1