--- /dev/null
+#ifndef _BABELTRACE_BITFIELD_H
+#define _BABELTRACE_BITFIELD_H
+
+/*
+ * BabelTrace
+ *
+ * Bitfields read/write functions.
+ *
+ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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 */
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 */
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
--- /dev/null
+#ifndef _LTT_ENDIAN_H
+#define _LTT_ENDIAN_H
+
+#ifdef __KERNEL__
+# include <asm/byteorder.h>
+# 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 <endian.h>
+#endif
+
+#endif /* _LTT_ENDIAN_H */
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)
* byte size.
*/
ret = lttng_metadata_printf(session,
- " } aligned(%u);\n"
- "};\n\n", ltt_get_header_alignment());
+ " };\n"
+ "};\n\n");
if (ret)
goto end;
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" :
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 <id> {\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 <id> {\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.
*/
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"
" 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,
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);
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,
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 {
#include <linux/module.h>
#include <linux/types.h>
+#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
* 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;
};
*
* 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.
*/
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;
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);
}
}
*/
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,
(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;
}
/*
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,
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);
}
(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));
* 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
#include "lttng.h"
#include "../ltt-events.h"
#include "../ltt-tracer.h"
-
-#ifdef __KERNEL__
-# include <asm/byteorder.h>
-# 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 <endian.h>
-#endif
+#include "../ltt-endian.h"
#endif /* _LTTNG_PROBES_LTTNG_TYPES_H */
-
/* Export enumerations */
#ifdef STAGE_EXPORT_ENUMS