From 9115fbdc0d5b0d69b32d3d4d924624fbbe22638e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 18 May 2011 13:57:42 -0400 Subject: [PATCH] Update stream packet and event headers Signed-off-by: Mathieu Desnoyers --- lib/bitfield.h | 400 ++++++++++++++++++++++++++++++ lib/ringbuffer/frontend.h | 6 - lib/ringbuffer/frontend_types.h | 6 + ltt-endian.h | 23 ++ ltt-events.c | 89 ++++++- ltt-events.h | 4 +- ltt-ring-buffer-client.h | 260 ++++++++++--------- ltt-ring-buffer-metadata-client.h | 3 +- ltt-tracer.h | 27 -- probes/lttng-types.h | 21 +- 10 files changed, 654 insertions(+), 185 deletions(-) create mode 100644 lib/bitfield.h create mode 100644 ltt-endian.h diff --git a/lib/bitfield.h b/lib/bitfield.h new file mode 100644 index 00000000..a509e35f --- /dev/null +++ b/lib/bitfield.h @@ -0,0 +1,400 @@ +#ifndef _BABELTRACE_BITFIELD_H +#define _BABELTRACE_BITFIELD_H + +/* + * BabelTrace + * + * Bitfields read/write functions. + * + * Copyright 2010 - Mathieu Desnoyers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + +#include "ltt-endian.h" + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */ +#define _bt_piecewise_rshift(_v, _shift) \ +({ \ + typeof(_v) ___v = (_v); \ + typeof(_shift) ___shift = (_shift); \ + unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \ + unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \ + \ + for (; sb; sb--) \ + ___v >>= sizeof(___v) * CHAR_BIT - 1; \ + ___v >>= final; \ +}) + +#define _bt_piecewise_lshift(_v, _shift) \ +({ \ + typeof(_v) ___v = (_v); \ + typeof(_shift) ___shift = (_shift); \ + unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \ + unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \ + \ + for (; sb; sb--) \ + ___v <<= sizeof(___v) * CHAR_BIT - 1; \ + ___v <<= final; \ +}) + +#define _bt_is_signed_type(type) (((type)(-1)) < 0) + +#define _bt_unsigned_cast(type, v) \ +({ \ + (sizeof(v) < sizeof(type)) ? \ + ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \ + (type) (v); \ +}) + +/* + * bt_bitfield_write - write integer to a bitfield in native endianness + * + * Save integer to the bitfield, which starts at the "start" bit, has "len" + * bits. + * The inside of a bitfield is from high bits to low bits. + * Uses native endianness. + * For unsigned "v", pad MSB with 0 if bitfield is larger than v. + * For signed "v", sign-extend v if bitfield is larger than v. + * + * On little endian, bytes are placed from the less significant to the most + * significant. Also, consecutive bitfields are placed from lower bits to higher + * bits. + * + * On big endian, bytes are places from most significant to less significant. + * Also, consecutive bitfields are placed from higher to lower bits. + */ + +#define _bt_bitfield_write_le(_ptr, type, _start, _length, _v) \ +do { \ + typeof(_v) __v = (_v); \ + type *__ptr = (void *) (_ptr); \ + unsigned long __start = (_start), __length = (_length); \ + type mask, cmask; \ + unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ + unsigned long start_unit, end_unit, this_unit; \ + unsigned long end, cshift; /* cshift is "complement shift" */ \ + \ + if (!__length) \ + break; \ + \ + end = __start + __length; \ + start_unit = __start / ts; \ + end_unit = (end + (ts - 1)) / ts; \ + \ + /* Trim v high bits */ \ + if (__length < sizeof(__v) * CHAR_BIT) \ + __v &= ~((~(typeof(__v)) 0) << __length); \ + \ + /* We can now append v with a simple "or", shift it piece-wise */ \ + this_unit = start_unit; \ + if (start_unit == end_unit - 1) { \ + mask = ~((~(type) 0) << (__start % ts)); \ + if (end % ts) \ + mask |= (~(type) 0) << (end % ts); \ + cmask = (type) __v << (__start % ts); \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + break; \ + } \ + if (__start % ts) { \ + cshift = __start % ts; \ + mask = ~((~(type) 0) << cshift); \ + cmask = (type) __v << cshift; \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + __v = _bt_piecewise_rshift(__v, ts - cshift); \ + __start += ts - cshift; \ + this_unit++; \ + } \ + for (; this_unit < end_unit - 1; this_unit++) { \ + __ptr[this_unit] = (type) __v; \ + __v = _bt_piecewise_rshift(__v, ts); \ + __start += ts; \ + } \ + if (end % ts) { \ + mask = (~(type) 0) << (end % ts); \ + cmask = (type) __v; \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + } else \ + __ptr[this_unit] = (type) __v; \ +} while (0) + +#define _bt_bitfield_write_be(_ptr, type, _start, _length, _v) \ +do { \ + typeof(_v) __v = (_v); \ + type *__ptr = (void *) (_ptr); \ + unsigned long __start = (_start), __length = (_length); \ + type mask, cmask; \ + unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ + unsigned long start_unit, end_unit, this_unit; \ + unsigned long end, cshift; /* cshift is "complement shift" */ \ + \ + if (!__length) \ + break; \ + \ + end = __start + __length; \ + start_unit = __start / ts; \ + end_unit = (end + (ts - 1)) / ts; \ + \ + /* Trim v high bits */ \ + if (__length < sizeof(__v) * CHAR_BIT) \ + __v &= ~((~(typeof(__v)) 0) << __length); \ + \ + /* We can now append v with a simple "or", shift it piece-wise */ \ + this_unit = end_unit - 1; \ + if (start_unit == end_unit - 1) { \ + mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \ + if (__start % ts) \ + mask |= (~((type) 0)) << (ts - (__start % ts)); \ + cmask = (type) __v << ((ts - (end % ts)) % ts); \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + break; \ + } \ + if (end % ts) { \ + cshift = end % ts; \ + mask = ~((~(type) 0) << (ts - cshift)); \ + cmask = (type) __v << (ts - cshift); \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + __v = _bt_piecewise_rshift(__v, cshift); \ + end -= cshift; \ + this_unit--; \ + } \ + for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ + __ptr[this_unit] = (type) __v; \ + __v = _bt_piecewise_rshift(__v, ts); \ + end -= ts; \ + } \ + if (__start % ts) { \ + mask = (~(type) 0) << (ts - (__start % ts)); \ + cmask = (type) __v; \ + cmask &= ~mask; \ + __ptr[this_unit] &= mask; \ + __ptr[this_unit] |= cmask; \ + } else \ + __ptr[this_unit] = (type) __v; \ +} while (0) + +/* + * bt_bitfield_write - write integer to a bitfield in native endianness + * bt_bitfield_write_le - write integer to a bitfield in little endian + * bt_bitfield_write_be - write integer to a bitfield in big endian + */ + +#if (__BYTE_ORDER == __LITTLE_ENDIAN) + +#define bt_bitfield_write(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_le(ptr, type, _start, _length, _v) + +#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_le(ptr, type, _start, _length, _v) + +#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v) + +#elif (__BYTE_ORDER == __BIG_ENDIAN) + +#define bt_bitfield_write(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_be(ptr, type, _start, _length, _v) + +#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v) + +#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ + _bt_bitfield_write_be(ptr, type, _start, _length, _v) + +#else /* (BYTE_ORDER == PDP_ENDIAN) */ + +#error "Byte order not supported" + +#endif + +#define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ +do { \ + typeof(*(_vptr)) *__vptr = (_vptr); \ + typeof(*__vptr) __v; \ + type *__ptr = (void *) (_ptr); \ + unsigned long __start = (_start), __length = (_length); \ + type mask, cmask; \ + unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ + unsigned long start_unit, end_unit, this_unit; \ + unsigned long end, cshift; /* cshift is "complement shift" */ \ + \ + if (!__length) { \ + *__vptr = 0; \ + break; \ + } \ + \ + end = __start + __length; \ + start_unit = __start / ts; \ + end_unit = (end + (ts - 1)) / ts; \ + \ + this_unit = end_unit - 1; \ + if (_bt_is_signed_type(typeof(__v)) \ + && (__ptr[this_unit] & ((type) 1 << ((end % ts ? : ts) - 1)))) \ + __v = ~(typeof(__v)) 0; \ + else \ + __v = 0; \ + if (start_unit == end_unit - 1) { \ + cmask = __ptr[this_unit]; \ + cmask >>= (__start % ts); \ + if ((end - __start) % ts) { \ + mask = ~((~(type) 0) << (end - __start)); \ + cmask &= mask; \ + } \ + __v = _bt_piecewise_lshift(__v, end - __start); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + *__vptr = __v; \ + break; \ + } \ + if (end % ts) { \ + cshift = end % ts; \ + mask = ~((~(type) 0) << cshift); \ + cmask = __ptr[this_unit]; \ + cmask &= mask; \ + __v = _bt_piecewise_lshift(__v, cshift); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + end -= cshift; \ + this_unit--; \ + } \ + for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ + __v = _bt_piecewise_lshift(__v, ts); \ + __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ + end -= ts; \ + } \ + if (__start % ts) { \ + mask = ~((~(type) 0) << (ts - (__start % ts))); \ + cmask = __ptr[this_unit]; \ + cmask >>= (__start % ts); \ + cmask &= mask; \ + __v = _bt_piecewise_lshift(__v, ts - (__start % ts)); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + } else { \ + __v = _bt_piecewise_lshift(__v, ts); \ + __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ + } \ + *__vptr = __v; \ +} while (0) + +#define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ +do { \ + typeof(*(_vptr)) *__vptr = (_vptr); \ + typeof(*__vptr) __v; \ + type *__ptr = (void *) (_ptr); \ + unsigned long __start = (_start), __length = (_length); \ + type mask, cmask; \ + unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ + unsigned long start_unit, end_unit, this_unit; \ + unsigned long end, cshift; /* cshift is "complement shift" */ \ + \ + if (!__length) { \ + *__vptr = 0; \ + break; \ + } \ + \ + end = __start + __length; \ + start_unit = __start / ts; \ + end_unit = (end + (ts - 1)) / ts; \ + \ + this_unit = start_unit; \ + if (_bt_is_signed_type(typeof(__v)) \ + && (__ptr[this_unit] & ((type) 1 << (ts - (__start % ts) - 1)))) \ + __v = ~(typeof(__v)) 0; \ + else \ + __v = 0; \ + if (start_unit == end_unit - 1) { \ + cmask = __ptr[this_unit]; \ + cmask >>= (ts - (end % ts)) % ts; \ + if ((end - __start) % ts) { \ + mask = ~((~(type) 0) << (end - __start)); \ + cmask &= mask; \ + } \ + __v = _bt_piecewise_lshift(__v, end - __start); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + *__vptr = __v; \ + break; \ + } \ + if (__start % ts) { \ + cshift = __start % ts; \ + mask = ~((~(type) 0) << (ts - cshift)); \ + cmask = __ptr[this_unit]; \ + cmask &= mask; \ + __v = _bt_piecewise_lshift(__v, ts - cshift); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + __start += ts - cshift; \ + this_unit++; \ + } \ + for (; this_unit < end_unit - 1; this_unit++) { \ + __v = _bt_piecewise_lshift(__v, ts); \ + __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ + __start += ts; \ + } \ + if (end % ts) { \ + mask = ~((~(type) 0) << (end % ts)); \ + cmask = __ptr[this_unit]; \ + cmask >>= ts - (end % ts); \ + cmask &= mask; \ + __v = _bt_piecewise_lshift(__v, end % ts); \ + __v |= _bt_unsigned_cast(typeof(__v), cmask); \ + } else { \ + __v = _bt_piecewise_lshift(__v, ts); \ + __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ + } \ + *__vptr = __v; \ +} while (0) + +/* + * bt_bitfield_read - read integer from a bitfield in native endianness + * bt_bitfield_read_le - read integer from a bitfield in little endian + * bt_bitfield_read_be - read integer from a bitfield in big endian + */ + +#if (__BYTE_ORDER == __LITTLE_ENDIAN) + +#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) + +#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) + +#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr) + +#elif (__BYTE_ORDER == __BIG_ENDIAN) + +#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) + +#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr) + +#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ + _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) + +#else /* (__BYTE_ORDER == __PDP_ENDIAN) */ + +#error "Byte order not supported" + +#endif + +#endif /* _BABELTRACE_BITFIELD_H */ diff --git a/lib/ringbuffer/frontend.h b/lib/ringbuffer/frontend.h index 7bb51a47..003c2e19 100644 --- a/lib/ringbuffer/frontend.h +++ b/lib/ringbuffer/frontend.h @@ -213,10 +213,4 @@ unsigned long lib_ring_buffer_get_records_read( return v_read(config, &buf->backend.records_read); } -static inline -void *channel_get_private(struct channel *chan) -{ - return chan->backend.priv; -} - #endif /* _LINUX_RING_BUFFER_FRONTEND_H */ diff --git a/lib/ringbuffer/frontend_types.h b/lib/ringbuffer/frontend_types.h index 0fa2dddf..e8c4c5ce 100644 --- a/lib/ringbuffer/frontend_types.h +++ b/lib/ringbuffer/frontend_types.h @@ -139,6 +139,12 @@ struct lib_ring_buffer { int read_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ }; +static inline +void *channel_get_private(struct channel *chan) +{ + return chan->backend.priv; +} + /* * Issue warnings and disable channels upon internal error. * Can receive struct lib_ring_buffer or struct lib_ring_buffer_backend diff --git a/ltt-endian.h b/ltt-endian.h new file mode 100644 index 00000000..29d75df6 --- /dev/null +++ b/ltt-endian.h @@ -0,0 +1,23 @@ +#ifndef _LTT_ENDIAN_H +#define _LTT_ENDIAN_H + +#ifdef __KERNEL__ +# include +# ifdef __BIG_ENDIAN +# define __BYTE_ORDER __BIG_ENDIAN +# elif defined(__LITTLE_ENDIAN) +# define __BYTE_ORDER __LITTLE_ENDIAN +# else +# error "unknown endianness" +# endif +#ifndef __BIG_ENDIAN +# define __BIG_ENDIAN 4321 +#endif +#ifndef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +#endif +#else +# include +#endif + +#endif /* _LTT_ENDIAN_H */ diff --git a/ltt-events.c b/ltt-events.c index 73ea08ea..703fd3d7 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -168,7 +168,7 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, goto nomem; chan->session = session; init_waitqueue_head(&chan->notify_wait); - chan->chan = transport->ops.channel_create("[lttng]", session, buf_addr, + chan->chan = transport->ops.channel_create("[lttng]", chan, buf_addr, subbuf_size, num_subbuf, switch_timer_interval, read_timer_interval); if (!chan->chan) @@ -491,8 +491,8 @@ int _ltt_event_metadata_statedump(struct ltt_session *session, * byte size. */ ret = lttng_metadata_printf(session, - " } aligned(%u);\n" - "};\n\n", ltt_get_header_alignment()); + " };\n" + "};\n\n"); if (ret) goto end; @@ -520,7 +520,8 @@ int _ltt_channel_metadata_statedump(struct ltt_session *session, ret = lttng_metadata_printf(session, "stream {\n" " id = %u;\n" - " event.header := %s;\n", + " event.header := %s;\n" + " packet.context := struct packet_context;\n" "};\n\n", chan->id, chan->header_type == 1 ? "struct event_header_compact" : @@ -533,6 +534,64 @@ end: return ret; } +static +int _ltt_stream_packet_context_declare(struct ltt_session *session) +{ + return lttng_metadata_printf(session, + "struct packet_context {\n" + " uint64_t timestamp_begin;\n" + " uint64_t timestamp_end;\n" + " uint32_t events_discarded;\n" + " uint32_t content_size;\n" + " uint32_t packet_size;\n" + " uint32_t cpu_id;\n" + "};\n" + ); +} + +/* + * Compact header: + * id: range: 0 - 30. + * id 31 is reserved to indicate an extended header. + * + * Large header: + * id: range: 0 - 65534. + * id 65535 is reserved to indicate an extended header. + */ +static +int _ltt_event_header_declare(struct ltt_session *session) +{ + return lttng_metadata_printf(session, + "struct event_header_compact {\n" + " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" + " variant {\n" + " struct {\n" + " uint27_t timestamp;\n" + " } compact;\n" + " struct {\n" + " uint32_t id;\n" + " uint64_t timestamp;\n" + " } extended;\n" + " } v;\n" + "} align(%u);\n" + "\n" + "struct event_header_large {\n" + " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" + " variant {\n" + " struct {\n" + " uint32_t timestamp;\n" + " } compact;\n" + " struct {\n" + " uint32_t id;\n" + " uint64_t timestamp;\n" + " } extended;\n" + " } v;\n" + "} align(%u);\n\n", + ltt_alignof(uint32_t) * CHAR_BIT, + ltt_alignof(uint16_t) * CHAR_BIT + ); +} + /* * Output metadata into this session's metadata buffers. */ @@ -561,9 +620,12 @@ int _ltt_session_metadata_statedump(struct ltt_session *session) 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" + "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" + "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" + "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" + "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" + "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" + "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" "\n" "trace {\n" " major = %u;\n" @@ -574,11 +636,6 @@ int _ltt_session_metadata_statedump(struct ltt_session *session) " uint32_t magic;\n" " uint8_t 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, @@ -596,6 +653,14 @@ int _ltt_session_metadata_statedump(struct ltt_session *session) if (ret) goto end; + ret = _ltt_stream_packet_context_declare(session); + if (ret) + goto end; + + ret = _ltt_event_header_declare(session); + 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 0911a5ef..bf0ac599 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -135,7 +135,7 @@ struct ltt_event { struct ltt_channel_ops { struct channel *(*channel_create)(const char *name, - struct ltt_session *session, + struct ltt_channel *ltt_chan, void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, @@ -166,8 +166,8 @@ struct ltt_channel { struct list_head list; /* Channel list */ wait_queue_head_t notify_wait; /* Channel addition notif. waitqueue */ struct ltt_channel_ops *ops; + int header_type; /* 0: unset, 1: compact, 2: large */ int metadata_dumped:1; - int header_type:2; /* 0: unset, 1: compact, 2: large */ }; struct ltt_session { diff --git a/ltt-ring-buffer-client.h b/ltt-ring-buffer-client.h index 8bb66af8..caf949cd 100644 --- a/ltt-ring-buffer-client.h +++ b/ltt-ring-buffer-client.h @@ -10,10 +10,12 @@ #include #include +#include "lib/bitfield.h" #include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ #include "wrapper/trace-clock.h" #include "ltt-events.h" #include "ltt-tracer.h" +#include "wrapper/ringbuffer/frontend_types.h" /* * Keep the natural field alignment for _each field_ within this structure if @@ -21,32 +23,30 @@ * 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 { + /* Trace packet header */ uint32_t magic; /* * Trace magic number. * contains endianness information. */ uint8_t 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 */ + + struct { + /* Stream packet context */ + uint64_t timestamp_begin; /* Cycle count at subbuffer start */ + uint64_t timestamp_end; /* Cycle count at subbuffer end */ + uint32_t events_discarded; /* + * Events lost in this subbuffer since + * the beginning of the trace. + * (may overflow) + */ + uint32_t content_size; /* Size of data in subbuffer */ + uint32_t packet_size; /* Subbuffer size (include padding) */ + uint32_t cpu_id; /* CPU id associated with stream */ + uint8_t header_end; /* End of header */ + } ctx; }; @@ -67,17 +67,6 @@ static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan) * * Returns the event header size (including padding). * - * Important note : - * The event header must be 32-bits. The total offset calculated here : - * - * Alignment of header struct on 32 bits (min arch size, header size) - * + sizeof(header struct) (32-bits) - * + (opt) u16 (ext. event id) - * + (opt) u16 (event_size) - * (if event_size == LTT_MAX_SMALL_SIZE, has ext. event size) - * + (opt) u32 (ext. event size) - * + (opt) u64 full TSC (aligned on min(64-bits, arch size)) - * * The payload must itself determine its own alignment from the biggest type it * contains. */ @@ -88,34 +77,44 @@ unsigned char record_header_size(const struct lib_ring_buffer_config *config, unsigned int rflags, struct lib_ring_buffer_ctx *ctx) { + struct ltt_channel *ltt_chan = channel_get_private(chan); size_t orig_offset = offset; size_t padding; - BUILD_BUG_ON(sizeof(struct event_header) != sizeof(u32)); - - padding = lib_ring_buffer_align(offset, - sizeof(struct event_header)); - offset += padding; - offset += sizeof(struct event_header); - - if (unlikely(rflags)) { - switch (rflags) { - case LTT_RFLAG_ID_SIZE_TSC: - offset += sizeof(u16) + sizeof(u16); - if (data_size >= LTT_MAX_SMALL_SIZE) - offset += sizeof(u32); - offset += lib_ring_buffer_align(offset, sizeof(u64)); - offset += sizeof(u64); - break; - case LTT_RFLAG_ID_SIZE: - offset += sizeof(u16) + sizeof(u16); - if (data_size >= LTT_MAX_SMALL_SIZE) - offset += sizeof(u32); - break; - case LTT_RFLAG_ID: - offset += sizeof(u16); - break; + switch (ltt_chan->header_type) { + case 1: /* compact */ + padding = lib_ring_buffer_align(offset, ltt_alignof(uint32_t)); + offset += padding; + if (!(rflags & RING_BUFFER_RFLAG_FULL_TSC)) { + offset += sizeof(uint32_t); /* id and timestamp */ + } else { + /* Minimum space taken by 5-bit id */ + offset += sizeof(uint8_t); + /* Align extended struct on largest member */ + offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); + offset += sizeof(uint32_t); /* id */ + offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); + offset += sizeof(uint64_t); /* timestamp */ + } + break; + case 2: /* large */ + padding = lib_ring_buffer_align(offset, ltt_alignof(uint16_t)); + offset += padding; + offset += sizeof(uint16_t); + if (!(rflags & RING_BUFFER_RFLAG_FULL_TSC)) { + offset += lib_ring_buffer_align(offset, ltt_alignof(uint32_t)); + offset += sizeof(uint32_t); /* timestamp */ + } else { + /* Align extended struct on largest member */ + offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); + offset += sizeof(uint32_t); /* id */ + offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); + offset += sizeof(uint64_t); /* timestamp */ + } + break; + default: + WARN_ON(1); } *pre_header_padding = padding; @@ -144,66 +143,96 @@ void ltt_write_event_header(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_ctx *ctx, u16 eID, u32 event_size) { - struct event_header header; + struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); if (unlikely(ctx->rflags)) goto slow_path; - header.id_time = eID << LTT_TSC_BITS; - header.id_time |= (u32)ctx->tsc & LTT_TSC_MASK; - lib_ring_buffer_write(config, ctx, &header, sizeof(header)); + switch (ltt_chan->header_type) { + case 1: /* compact */ + { + uint32_t id_time = 0; + + bt_bitfield_write(&id_time, uint32_t, 0, 5, eID); + bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc); + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); + break; + } + case 2: /* large */ + { + uint16_t event_id = eID; + uint32_t timestamp = (uint32_t) ctx->tsc; + + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint32_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + break; + } + default: + WARN_ON(1); + } + return; slow_path: ltt_write_event_header_slow(config, ctx, eID, event_size); } +/* + * TODO: For now, we only support 65536 event ids per channel. + */ void ltt_write_event_header_slow(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_ctx *ctx, u16 eID, u32 event_size) { - struct event_header header; - u16 small_size; - - switch (ctx->rflags) { - case LTT_RFLAG_ID_SIZE_TSC: - header.id_time = 29 << LTT_TSC_BITS; - break; - case LTT_RFLAG_ID_SIZE: - header.id_time = 30 << LTT_TSC_BITS; + struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); + + switch (ltt_chan->header_type) { + case 1: /* compact */ + if (!(ctx->rflags & RING_BUFFER_RFLAG_FULL_TSC)) { + uint32_t id_time = 0; + + bt_bitfield_write(&id_time, uint32_t, 0, 5, eID); + bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc); + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); + } else { + uint8_t id = 0; + uint32_t event_id = (uint32_t) eID; + uint64_t timestamp = ctx->tsc; + + bt_bitfield_write(&id, uint8_t, 0, 5, 31); + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); + /* Align extended struct on largest member */ + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } break; - case LTT_RFLAG_ID: - header.id_time = 31 << LTT_TSC_BITS; + case 2: /* large */ + { + if (!(ctx->rflags & RING_BUFFER_RFLAG_FULL_TSC)) { + uint16_t event_id = eID; + uint32_t timestamp = (uint32_t) ctx->tsc; + + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint32_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } else { + uint16_t event_id = 65535; + uint32_t event_id_ext = (uint32_t) eID; + uint64_t timestamp = ctx->tsc; + + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); + /* Align extended struct on largest member */ + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, &event_id_ext, sizeof(event_id_ext)); + lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); + } break; - default: - WARN_ON_ONCE(1); - header.id_time = 0; } - - header.id_time |= (u32)ctx->tsc & LTT_TSC_MASK; - lib_ring_buffer_write(config, ctx, &header, sizeof(header)); - - switch (ctx->rflags) { - case LTT_RFLAG_ID_SIZE_TSC: - small_size = (u16)min_t(u32, event_size, LTT_MAX_SMALL_SIZE); - lib_ring_buffer_write(config, ctx, &eID, sizeof(u16)); - lib_ring_buffer_write(config, ctx, &small_size, sizeof(u16)); - if (small_size == LTT_MAX_SMALL_SIZE) - lib_ring_buffer_write(config, ctx, &event_size, - sizeof(u32)); - lib_ring_buffer_align_ctx(ctx, sizeof(u64)); - lib_ring_buffer_write(config, ctx, &ctx->tsc, sizeof(u64)); - break; - case LTT_RFLAG_ID_SIZE: - small_size = (u16)min_t(u32, event_size, LTT_MAX_SMALL_SIZE); - lib_ring_buffer_write(config, ctx, &eID, sizeof(u16)); - lib_ring_buffer_write(config, ctx, &small_size, sizeof(u16)); - if (small_size == LTT_MAX_SMALL_SIZE) - lib_ring_buffer_write(config, ctx, &event_size, - sizeof(u32)); - break; - case LTT_RFLAG_ID: - lib_ring_buffer_write(config, ctx, &eID, sizeof(u16)); - break; + default: + WARN_ON(1); } } @@ -235,7 +264,7 @@ size_t client_record_header_size(const struct lib_ring_buffer_config *config, */ static size_t client_packet_header_size(void) { - return offsetof(struct packet_header, header_end); + return offsetof(struct packet_header, ctx.header_end); } static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, @@ -246,21 +275,18 @@ 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); + struct ltt_channel *ltt_chan = channel_get_private(chan); + struct ltt_session *session = ltt_chan->session; header->magic = CTF_MAGIC_NUMBER; memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); - header->timestamp_begin = tsc; - header->timestamp_end = 0; - header->content_size = 0xFFFFFFFF; /* for debugging */ - 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 + header->stream_id = ltt_chan->id; + header->ctx.timestamp_begin = tsc; + header->ctx.timestamp_end = 0; + header->ctx.events_discarded = 0; + header->ctx.content_size = 0xFFFFFFFF; /* for debugging */ + header->ctx.packet_size = 0xFFFFFFFF; + header->ctx.cpu_id = buf->backend.cpu; } /* @@ -277,13 +303,13 @@ 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->ctx.timestamp_end = tsc; + header->ctx.content_size = data_size; + header->ctx.packet_size = PAGE_ALIGN(data_size); 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); - header->events_lost = records_lost; + header->ctx.events_discarded = records_lost; } static int client_buffer_create(struct lib_ring_buffer *buf, void *priv, @@ -318,12 +344,12 @@ static const struct lib_ring_buffer_config client_config = { static struct channel *_channel_create(const char *name, - struct ltt_session *session, void *buf_addr, + struct ltt_channel *ltt_chan, void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, unsigned int read_timer_interval) { - return channel_create(&client_config, name, session, buf_addr, + return channel_create(&client_config, name, ltt_chan, buf_addr, subbuf_size, num_subbuf, switch_timer_interval, read_timer_interval); } diff --git a/ltt-ring-buffer-metadata-client.h b/ltt-ring-buffer-metadata-client.h index bde712e6..9456d54e 100644 --- a/ltt-ring-buffer-metadata-client.h +++ b/ltt-ring-buffer-metadata-client.h @@ -86,7 +86,8 @@ 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); + struct ltt_channel *ltt_chan = channel_get_private(chan); + struct ltt_session *session = ltt_chan->session; header->magic = TSDL_MAGIC_NUMBER; memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); diff --git a/ltt-tracer.h b/ltt-tracer.h index f1cd2d90..aa9db46a 100644 --- a/ltt-tracer.h +++ b/ltt-tracer.h @@ -96,38 +96,11 @@ enum ltt_channels { * concerns. */ -#define LTT_RESERVED_EVENTS 3 -#define LTT_EVENT_BITS 5 -#define LTT_FREE_EVENTS ((1 << LTT_EVENT_BITS) - LTT_RESERVED_EVENTS) -#define LTT_TSC_BITS 27 -#define LTT_TSC_MASK ((1 << LTT_TSC_BITS) - 1) - -struct event_header { - u32 id_time; /* 5 bits event id (MSB); 27 bits time (LSB) */ -}; - -/* Reservation flags */ -#define LTT_RFLAG_ID (1 << 0) -#define LTT_RFLAG_ID_SIZE (1 << 1) -#define LTT_RFLAG_ID_SIZE_TSC (1 << 2) - #define LTT_MAX_SMALL_SIZE 0xFFFFU #ifdef RING_BUFFER_ALIGN -static inline -size_t ltt_get_header_alignment(void) -{ - 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; -} - #define ltt_alignof(type) 1 #endif diff --git a/probes/lttng-types.h b/probes/lttng-types.h index 5a7a6554..c435b4d3 100644 --- a/probes/lttng-types.h +++ b/probes/lttng-types.h @@ -9,29 +9,10 @@ #include "lttng.h" #include "../ltt-events.h" #include "../ltt-tracer.h" - -#ifdef __KERNEL__ -# include -# ifdef __BIG_ENDIAN -# define __BYTE_ORDER __BIG_ENDIAN -# elif defined(__LITTLE_ENDIAN) -# define __BYTE_ORDER __LITTLE_ENDIAN -# else -# error "unknown endianness" -# endif -#ifndef __BIG_ENDIAN -# define __BIG_ENDIAN 4321 -#endif -#ifndef __LITTLE_ENDIAN -# define __LITTLE_ENDIAN 1234 -#endif -#else -# include -#endif +#include "../ltt-endian.h" #endif /* _LTTNG_PROBES_LTTNG_TYPES_H */ - /* Export enumerations */ #ifdef STAGE_EXPORT_ENUMS -- 2.34.1