A common use-case for sequences and variants is to use the field located
immediately prior to the type as length/tag.
The fact that those types need to explicitly contain their length/tag
name ties the sequence/variant type to where it is placed within the
structure fields, preventing re-use of the sequence/variant type.
In order to reduce the memory footprint of the field descriptions and
allow re-use of common field types, special-case the NULL length name
and tag name to use the field prior to the sequence/variant as length.
This allows more efficient type descriptions without reducing the
overall flexibility of sequence/variant layout.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I27053e8541beb4f8f8226e411c71595f7527f533
false, false, false),
[12] = lttng_kernel_static_event_field("transport_header",
lttng_kernel_static_type_variant(ARRAY_SIZE(transport_fields), transport_fields,
false, false, false),
[12] = lttng_kernel_static_event_field("transport_header",
lttng_kernel_static_type_variant(ARRAY_SIZE(transport_fields), transport_fields,
- "transport_header_type", 0),
+ NULL, 0), /* Previous field as tag. */
false, false, false),
[9] = lttng_kernel_static_event_field("transport_header",
lttng_kernel_static_type_variant(ARRAY_SIZE(transport_fields),
false, false, false),
[9] = lttng_kernel_static_event_field("transport_header",
lttng_kernel_static_type_variant(ARRAY_SIZE(transport_fields),
- transport_fields, "transport_header_type", 0),
+ transport_fields, NULL, 0), /* Previous field as tag. */
ctf_custom_field(
ctf_custom_type(
lttng_kernel_static_type_variant(ARRAY_SIZE(network_fields),
ctf_custom_field(
ctf_custom_type(
lttng_kernel_static_type_variant(ARRAY_SIZE(network_fields),
- network_fields, "network_header_type", 0)
+ network_fields, NULL, 0) /* Previous field as tag. */
),
network_header,
ctf_custom_code(
),
network_header,
ctf_custom_code(
) \
ctf_custom_field( \
ctf_custom_type( \
) \
ctf_custom_field( \
ctf_custom_type( \
- lttng_kernel_static_type_sequence( \
- "_" #name "_length", \
+ lttng_kernel_static_type_sequence(NULL, \
lttng_kernel_static_type_integer_from_type(uint8_t, __BYTE_ORDER, 16), \
0, \
none) \
lttng_kernel_static_type_integer_from_type(uint8_t, __BYTE_ORDER, 16), \
0, \
none) \
) \
ctf_custom_field( \
ctf_custom_type( \
) \
ctf_custom_field( \
ctf_custom_type( \
- lttng_kernel_static_type_sequence("_" #name "_length", \
+ lttng_kernel_static_type_sequence(NULL, \
lttng_kernel_static_type_integer_from_type(uint8_t, __BYTE_ORDER, 16), \
0, \
none) \
lttng_kernel_static_type_integer_from_type(uint8_t, __BYTE_ORDER, 16), \
0, \
none) \
struct lttng_kernel_type_sequence {
struct lttng_kernel_type_common parent;
struct lttng_kernel_type_sequence {
struct lttng_kernel_type_common parent;
- const char *length_name; /* Length field name. */
+ const char *length_name; /* Length field name. If NULL, use previous field. */
const struct lttng_kernel_type_common *elem_type;
unsigned int alignment; /* Alignment before elements. */
enum lttng_kernel_string_encoding encoding;
const struct lttng_kernel_type_common *elem_type;
unsigned int alignment; /* Alignment before elements. */
enum lttng_kernel_string_encoding encoding;
struct lttng_kernel_type_variant {
struct lttng_kernel_type_common parent;
struct lttng_kernel_type_variant {
struct lttng_kernel_type_common parent;
+ const char *tag_name; /* Tag field name. If NULL, use previous field. */
const struct lttng_kernel_event_field **choices; /* Array of pointers to fields. */
unsigned int nr_choices;
unsigned int alignment;
const struct lttng_kernel_event_field **choices; /* Array of pointers to fields. */
unsigned int nr_choices;
unsigned int alignment;
lttng_kernel_static_type_integer_from_type(_length_type, __BYTE_ORDER, 10), \
_nowrite, 0, 1), \
lttng_kernel_static_event_field(#_item, \
lttng_kernel_static_type_integer_from_type(_length_type, __BYTE_ORDER, 10), \
_nowrite, 0, 1), \
lttng_kernel_static_event_field(#_item, \
- lttng_kernel_static_type_sequence("_" #_item "_length", \
+ lttng_kernel_static_type_sequence(NULL, /* Use previous field. */ \
lttng_kernel_static_type_integer_from_type(_type, _byte_order, _elem_type_base), \
0, \
_encoding), \
lttng_kernel_static_type_integer_from_type(_type, _byte_order, _elem_type_base), \
0, \
_encoding), \
lttng_kernel_static_type_integer_from_type(_length_type, __BYTE_ORDER, 10), \
_nowrite, 0, 1), \
lttng_kernel_static_event_field(#_item, \
lttng_kernel_static_type_integer_from_type(_length_type, __BYTE_ORDER, 10), \
_nowrite, 0, 1), \
lttng_kernel_static_event_field(#_item, \
- lttng_kernel_static_type_sequence("_" #_item "_length", \
+ lttng_kernel_static_type_sequence(NULL, /* Use previous field. */ \
lttng_kernel_static_type_integer(1, 1, 0, __LITTLE_ENDIAN, 10), \
lttng_alignof(_type), \
none), \
lttng_kernel_static_type_integer(1, 1, 0, __LITTLE_ENDIAN, 10), \
lttng_alignof(_type), \
none), \
lttng_kernel_static_type_integer_from_type(unsigned int, __BYTE_ORDER, 10),
false, false, false),
lttng_kernel_static_event_field("callstack_kernel",
lttng_kernel_static_type_integer_from_type(unsigned int, __BYTE_ORDER, 10),
false, false, false),
lttng_kernel_static_event_field("callstack_kernel",
- lttng_kernel_static_type_sequence("_callstack_kernel_length",
+ lttng_kernel_static_type_sequence(NULL,
lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16),
0, none),
false, false, false),
lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16),
0, none),
false, false, false),
lttng_kernel_static_type_integer_from_type(unsigned int, __BYTE_ORDER, 10),
false, false, false),
lttng_kernel_static_event_field("callstack_user",
lttng_kernel_static_type_integer_from_type(unsigned int, __BYTE_ORDER, 10),
false, false, false),
lttng_kernel_static_event_field("callstack_user",
- lttng_kernel_static_type_sequence("_callstack_user_length",
+ lttng_kernel_static_type_sequence(NULL,
lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16),
0, none),
false, false, false),
lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16),
0, none),
false, false, false),
static
int _lttng_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
static
int _lttng_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
+ size_t nesting, const char **prev_field_name_p);
void synchronize_trace(void)
{
void synchronize_trace(void)
{
const struct lttng_kernel_type_struct *type,
size_t nesting)
{
const struct lttng_kernel_type_struct *type,
size_t nesting)
{
+ const char *prev_field_name = NULL;
int ret;
uint32_t i, nr_fields;
unsigned int alignment;
int ret;
uint32_t i, nr_fields;
unsigned int alignment;
const struct lttng_kernel_event_field *iter_field;
iter_field = type->fields[i];
const struct lttng_kernel_event_field *iter_field;
iter_field = type->fields[i];
- ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+ ret = _lttng_field_statedump(session, iter_field, nesting + 1, &prev_field_name);
static
int _lttng_variant_type_statedump(struct lttng_session *session,
const struct lttng_kernel_type_variant *type,
static
int _lttng_variant_type_statedump(struct lttng_session *session,
const struct lttng_kernel_type_variant *type,
+ size_t nesting,
+ const char *prev_field_name)
int ret;
uint32_t i, nr_choices;
int ret;
uint32_t i, nr_choices;
+ tag_name = type->tag_name;
+ if (!tag_name)
+ tag_name = prev_field_name;
+ if (!tag_name)
+ return -EINVAL;
/*
* CTF 1.8 does not allow expressing nonzero variant alignment in a nestable way.
*/
/*
* CTF 1.8 does not allow expressing nonzero variant alignment in a nestable way.
*/
return ret;
ret = lttng_metadata_printf(session,
"variant <_%s> {\n",
return ret;
ret = lttng_metadata_printf(session,
"variant <_%s> {\n",
if (ret)
return ret;
nr_choices = type->nr_choices;
if (ret)
return ret;
nr_choices = type->nr_choices;
const struct lttng_kernel_event_field *iter_field;
iter_field = type->choices[i];
const struct lttng_kernel_event_field *iter_field;
iter_field = type->choices[i];
- ret = _lttng_field_statedump(session, iter_field, nesting + 1);
+ ret = _lttng_field_statedump(session, iter_field, nesting + 1, NULL);
static
int _lttng_variant_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
static
int _lttng_variant_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
+ size_t nesting,
+ const char *prev_field_name)
{
int ret;
ret = _lttng_variant_type_statedump(session,
{
int ret;
ret = _lttng_variant_type_statedump(session,
- lttng_kernel_get_type_variant(field->type), nesting);
+ lttng_kernel_get_type_variant(field->type), nesting,
+ prev_field_name);
if (ret)
return ret;
return lttng_field_name_statedump(session, field, nesting);
if (ret)
return ret;
return lttng_field_name_statedump(session, field, nesting);
static
int _lttng_sequence_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
static
int _lttng_sequence_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
+ size_t nesting,
+ const char *prev_field_name)
{
int ret;
const char *length_name;
{
int ret;
const char *length_name;
WARN_ON_ONCE(!sequence_type);
length_name = sequence_type->length_name;
WARN_ON_ONCE(!sequence_type);
length_name = sequence_type->length_name;
+ if (!length_name)
+ length_name = prev_field_name;
+ if (!length_name)
+ return -EINVAL;
if (sequence_type->alignment) {
ret = print_tabs(session, nesting);
if (sequence_type->alignment) {
ret = print_tabs(session, nesting);
ret = lttng_metadata_printf(session,
" _%s[ _%s ];\n",
field->name,
ret = lttng_metadata_printf(session,
" _%s[ _%s ];\n",
field->name,
- sequence_type->length_name);
case lttng_kernel_type_variant:
ret = _lttng_variant_type_statedump(session,
lttng_kernel_get_type_variant(type),
case lttng_kernel_type_variant:
ret = _lttng_variant_type_statedump(session,
lttng_kernel_get_type_variant(type),
break;
/* Nested arrays and sequences are not supported yet. */
break;
/* Nested arrays and sequences are not supported yet. */
static
int _lttng_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
static
int _lttng_field_statedump(struct lttng_session *session,
const struct lttng_kernel_event_field *field,
+ size_t nesting,
+ const char **prev_field_name_p)
+ const char *prev_field_name = NULL;
+ if (prev_field_name_p)
+ prev_field_name = *prev_field_name_p;
switch (field->type->type) {
case lttng_kernel_type_integer:
ret = _lttng_integer_field_statedump(session, field, nesting);
switch (field->type->type) {
case lttng_kernel_type_integer:
ret = _lttng_integer_field_statedump(session, field, nesting);
ret = _lttng_array_field_statedump(session, field, nesting);
break;
case lttng_kernel_type_sequence:
ret = _lttng_array_field_statedump(session, field, nesting);
break;
case lttng_kernel_type_sequence:
- ret = _lttng_sequence_field_statedump(session, field, nesting);
+ ret = _lttng_sequence_field_statedump(session, field, nesting, prev_field_name);
break;
case lttng_kernel_type_variant:
break;
case lttng_kernel_type_variant:
- ret = _lttng_variant_field_statedump(session, field, nesting);
+ ret = _lttng_variant_field_statedump(session, field, nesting, prev_field_name);
break;
default:
WARN_ON_ONCE(1);
return -EINVAL;
}
break;
default:
WARN_ON_ONCE(1);
return -EINVAL;
}
+ if (prev_field_name_p)
+ *prev_field_name_p = field->name;
int _lttng_context_metadata_statedump(struct lttng_session *session,
struct lttng_kernel_ctx *ctx)
{
int _lttng_context_metadata_statedump(struct lttng_session *session,
struct lttng_kernel_ctx *ctx)
{
+ const char *prev_field_name = NULL;
for (i = 0; i < ctx->nr_fields; i++) {
const struct lttng_kernel_ctx_field *field = &ctx->fields[i];
for (i = 0; i < ctx->nr_fields; i++) {
const struct lttng_kernel_ctx_field *field = &ctx->fields[i];
- ret = _lttng_field_statedump(session, field->event_field, 2);
+ ret = _lttng_field_statedump(session, field->event_field, 2, &prev_field_name);
int _lttng_fields_metadata_statedump(struct lttng_session *session,
struct lttng_kernel_event_recorder *event_recorder)
{
int _lttng_fields_metadata_statedump(struct lttng_session *session,
struct lttng_kernel_event_recorder *event_recorder)
{
+ const char *prev_field_name = NULL;
const struct lttng_kernel_event_desc *desc = event_recorder->priv->parent.desc;
int ret = 0;
int i;
const struct lttng_kernel_event_desc *desc = event_recorder->priv->parent.desc;
int ret = 0;
int i;
for (i = 0; i < desc->nr_fields; i++) {
const struct lttng_kernel_event_field *field = desc->fields[i];
for (i = 0; i < desc->nr_fields; i++) {
const struct lttng_kernel_event_field *field = desc->fields[i];
- ret = _lttng_field_statedump(session, field, 2);
+ ret = _lttng_field_statedump(session, field, 2, &prev_field_name);