X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-metadata.c;h=c97013f438a88df9b9d7ccf1205761731261860b;hp=984d5f813ccf9277e6e221b7299f8f80a7d50954;hb=1ddb0e8a8122350b882848286a1ff5169613030b;hpb=10b56aefc3e1de5cee607994f64c3b8a7d85c391 diff --git a/src/bin/lttng-sessiond/ust-metadata.c b/src/bin/lttng-sessiond/ust-metadata.c index 984d5f813..c97013f43 100644 --- a/src/bin/lttng-sessiond/ust-metadata.c +++ b/src/bin/lttng-sessiond/ust-metadata.c @@ -41,10 +41,15 @@ #define NR_CLOCK_OFFSET_SAMPLES 10 struct offset_sample { - uint64_t offset; /* correlation offset */ + int64_t offset; /* correlation offset */ uint64_t measure_delta; /* lower is better */ }; +static +int _lttng_field_statedump(struct ust_registry_session *session, + const struct ustctl_field *fields, size_t nr_fields, + size_t *iter_field, size_t nesting); + static inline int fls(unsigned int x) { @@ -179,19 +184,54 @@ end: return ret; } +static +int print_tabs(struct ust_registry_session *session, size_t nesting) +{ + size_t i; + + for (i = 0; i < nesting; i++) { + int ret; + + ret = lttng_metadata_printf(session, " "); + if (ret) { + return ret; + } + } + return 0; +} + +static +void sanitize_ctf_identifier(char *out, const char *in) +{ + size_t i; + + for (i = 0; i < LTTNG_UST_SYM_NAME_LEN; i++) { + switch (in[i]) { + case '.': + case '$': + case ':': + out[i] = '_'; + break; + default: + out[i] = in[i]; + } + } +} + /* Called with session registry mutex held. */ static int ust_metadata_enum_statedump(struct ust_registry_session *session, const char *enum_name, uint64_t enum_id, const struct ustctl_integer_type *container_type, - const char *field_name) + const char *field_name, size_t *iter_field, size_t nesting) { struct ust_registry_enum *reg_enum; const struct ustctl_enum_entry *entries; size_t nr_entries; int ret = 0; size_t i; + char identifier[LTTNG_UST_SYM_NAME_LEN]; rcu_read_lock(); reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id); @@ -204,8 +244,12 @@ int ust_metadata_enum_statedump(struct ust_registry_session *session, entries = reg_enum->entries; nr_entries = reg_enum->nr_entries; + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n", + "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n", container_type->size, container_type->alignment, container_type->signedness, @@ -218,13 +262,18 @@ int ust_metadata_enum_statedump(struct ust_registry_session *session, if (ret) { goto end; } + nesting++; /* Dump all entries */ for (i = 0; i < nr_entries; i++) { const struct ustctl_enum_entry *entry = &entries[i]; int j, len; + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " \""); + "\""); if (ret) { goto end; } @@ -256,44 +305,132 @@ int ust_metadata_enum_statedump(struct ust_registry_session *session, if (ret) { goto end; } - if (entry->start == entry->end) { + + if (entry->start.signedness) { ret = lttng_metadata_printf(session, - "%d,\n", - entry->start); + "%lld", (long long) entry->start.value); } else { ret = lttng_metadata_printf(session, - "%d ... %d,\n", - entry->start, entry->end); + "%llu", entry->start.value); + } + if (ret) { + goto end; + } + + if (entry->start.signedness == entry->end.signedness && + entry->start.value == entry->end.value) { + ret = lttng_metadata_printf(session, + ",\n"); + } else { + if (entry->end.signedness) { + ret = lttng_metadata_printf(session, + " ... %lld,\n", (long long) entry->end.value); + } else { + ret = lttng_metadata_printf(session, + " ... %llu,\n", entry->end.value); + } + } + if (ret) { + goto end; + } + } + nesting--; + sanitize_ctf_identifier(identifier, field_name); + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } + ret = lttng_metadata_printf(session, "} _%s;\n", + identifier); +end: + (*iter_field)++; + return ret; +} + +static +int _lttng_variant_statedump(struct ust_registry_session *session, + const struct ustctl_field *fields, size_t nr_fields, + size_t *iter_field, size_t nesting) +{ + const struct ustctl_field *variant = &fields[*iter_field]; + uint32_t nr_choices, i; + int ret; + char identifier[LTTNG_UST_SYM_NAME_LEN]; + + if (variant->type.atype != ustctl_atype_variant) { + ret = -EINVAL; + goto end; + } + nr_choices = variant->type.u.variant.nr_choices; + (*iter_field)++; + sanitize_ctf_identifier(identifier, variant->type.u.variant.tag_name); + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } + ret = lttng_metadata_printf(session, + "variant <_%s> {\n", + identifier); + if (ret) { + goto end; + } + + for (i = 0; i < nr_choices; i++) { + if (*iter_field >= nr_fields) { + ret = -EOVERFLOW; + goto end; } + ret = _lttng_field_statedump(session, + fields, nr_fields, + iter_field, nesting + 1); if (ret) { goto end; } } - ret = lttng_metadata_printf(session, " } _%s;\n", - field_name); + sanitize_ctf_identifier(identifier, variant->name); + ret = print_tabs(session, nesting); + ret = lttng_metadata_printf(session, + "} _%s;\n", + identifier); + if (ret) { + goto end; + } end: return ret; } static int _lttng_field_statedump(struct ust_registry_session *session, - const struct ustctl_field *field) + const struct ustctl_field *fields, size_t nr_fields, + size_t *iter_field, size_t nesting) { int ret = 0; const char *bo_be = " byte_order = be;"; const char *bo_le = " byte_order = le;"; const char *bo_native = ""; const char *bo_reverse; + const struct ustctl_field *field; + + if (*iter_field >= nr_fields) { + ret = -EOVERFLOW; + goto end; + } + field = &fields[*iter_field]; - if (session->byte_order == BIG_ENDIAN) + if (session->byte_order == BIG_ENDIAN) { bo_reverse = bo_le; - else + } else { bo_reverse = bo_be; + } switch (field->type.atype) { case ustctl_atype_integer: + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", + "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", field->type.u.basic.integer.size, field->type.u.basic.integer.alignment, field->type.u.basic.integer.signedness, @@ -305,30 +442,40 @@ int _lttng_field_statedump(struct ust_registry_session *session, field->type.u.basic.integer.base, field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name); + (*iter_field)++; break; case ustctl_atype_enum: ret = ust_metadata_enum_statedump(session, field->type.u.basic.enumeration.name, field->type.u.basic.enumeration.id, &field->type.u.basic.enumeration.container_type, - field->name); + field->name, iter_field, nesting); break; case ustctl_atype_float: + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", + "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", field->type.u.basic._float.exp_dig, field->type.u.basic._float.mant_dig, field->type.u.basic._float.alignment, field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name); + (*iter_field)++; break; case ustctl_atype_array: { const struct ustctl_basic_type *elem_type; + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } elem_type = &field->type.u.array.elem_type; ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", + "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", elem_type->u.basic.integer.size, elem_type->u.basic.integer.alignment, elem_type->u.basic.integer.signedness, @@ -340,6 +487,7 @@ int _lttng_field_statedump(struct ust_registry_session *session, elem_type->u.basic.integer.base, elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name, field->type.u.array.length); + (*iter_field)++; break; } case ustctl_atype_sequence: @@ -349,8 +497,12 @@ int _lttng_field_statedump(struct ust_registry_session *session, elem_type = &field->type.u.sequence.elem_type; length_type = &field->type.u.sequence.length_type; + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", + "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", length_type->u.basic.integer.size, (unsigned int) length_type->u.basic.integer.alignment, length_type->u.basic.integer.signedness, @@ -362,11 +514,16 @@ int _lttng_field_statedump(struct ust_registry_session *session, length_type->u.basic.integer.base, length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name); - if (ret) - return ret; + if (ret) { + goto end; + } + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", + "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", elem_type->u.basic.integer.size, (unsigned int) elem_type->u.basic.integer.alignment, elem_type->u.basic.integer.signedness, @@ -379,20 +536,43 @@ int _lttng_field_statedump(struct ust_registry_session *session, elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name, field->name); + (*iter_field)++; break; } case ustctl_atype_string: /* Default encoding is UTF8 */ + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } ret = lttng_metadata_printf(session, - " string%s _%s;\n", + "string%s _%s;\n", field->type.u.basic.string.encoding == ustctl_encode_ASCII ? " { encoding = ASCII; }" : "", field->name); + (*iter_field)++; + break; + case ustctl_atype_variant: + ret = _lttng_variant_statedump(session, fields, nr_fields, iter_field, nesting); + if (ret) { + goto end; + } + break; + case ustctl_atype_struct: + ret = print_tabs(session, nesting); + if (ret) { + goto end; + } + ret = lttng_metadata_printf(session, + "struct {} _%s;\n", + field->name); + (*iter_field)++; break; default: - return -EINVAL; + ret = -EINVAL; } +end: return ret; } @@ -402,16 +582,19 @@ int _lttng_context_metadata_statedump(struct ust_registry_session *session, struct ustctl_field *ctx) { int ret = 0; - int i; + size_t i = 0; if (!ctx) return 0; - for (i = 0; i < nr_ctx_fields; i++) { - const struct ustctl_field *field = &ctx[i]; - - ret = _lttng_field_statedump(session, field); - if (ret) - return ret; + for (;;) { + if (i >= nr_ctx_fields) { + break; + } + ret = _lttng_field_statedump(session, ctx, + nr_ctx_fields, &i, 2); + if (ret) { + break; + } } return ret; } @@ -421,14 +604,17 @@ int _lttng_fields_metadata_statedump(struct ust_registry_session *session, struct ust_registry_event *event) { int ret = 0; - int i; + size_t i = 0; - for (i = 0; i < event->nr_fields; i++) { - const struct ustctl_field *field = &event->fields[i]; - - ret = _lttng_field_statedump(session, field); - if (ret) - return ret; + for (;;) { + if (i >= event->nr_fields) { + break; + } + ret = _lttng_field_statedump(session, event->fields, + event->nr_fields, &i, 2); + if (ret) { + break; + } } return ret; } @@ -555,6 +741,7 @@ int _lttng_stream_packet_context_declare(struct ust_registry_session *session) " uint64_clock_monotonic_t timestamp_end;\n" " uint64_t content_size;\n" " uint64_t packet_size;\n" + " uint64_t packet_seq_num;\n" " unsigned long events_discarded;\n" " uint32_t cpu_id;\n" "};\n\n" @@ -604,10 +791,14 @@ int _lttng_event_header_declare(struct ust_registry_session *session) ); } +/* + * The offset between monotonic and realtime clock can be negative if + * the system sets the REALTIME clock to 0 after boot. + */ static int measure_single_clock_offset(struct offset_sample *sample) { - uint64_t offset, monotonic[2], measure_delta, realtime; + uint64_t monotonic_avg, monotonic[2], measure_delta, realtime; uint64_t tcf = trace_clock_freq(); struct timespec rts = { 0, 0 }; int ret; @@ -626,15 +817,14 @@ int measure_single_clock_offset(struct offset_sample *sample) */ return 0; } - offset = (monotonic[0] + monotonic[1]) >> 1; + monotonic_avg = (monotonic[0] + monotonic[1]) >> 1; realtime = (uint64_t) rts.tv_sec * tcf; if (tcf == NSEC_PER_SEC) { realtime += rts.tv_nsec; } else { realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC; } - offset = realtime - offset; - sample->offset = offset; + sample->offset = (int64_t) realtime - monotonic_avg; sample->measure_delta = measure_delta; return 0; } @@ -643,9 +833,10 @@ int measure_single_clock_offset(struct offset_sample *sample) * Approximation of NTP time of day to clock monotonic correlation, * taken at start of trace. Keep the measurement that took the less time * to complete, thus removing imprecision caused by preemption. + * May return a negative offset. */ static -uint64_t measure_clock_offset(void) +int64_t measure_clock_offset(void) { int i; struct offset_sample offset_best_sample = { @@ -713,6 +904,7 @@ int ust_metadata_session_statedump(struct ust_registry_session *session, " uint32_t magic;\n" " uint8_t uuid[16];\n" " uint32_t stream_id;\n" + " uint64_t stream_instance_id;\n" " };\n" "};\n\n", session->uint8_t_alignment, @@ -793,7 +985,7 @@ int ust_metadata_session_statedump(struct ust_registry_session *session, " description = \"%s\";\n" " freq = %" PRIu64 "; /* Frequency, in Hz */\n" " /* clock value offset from Epoch is: offset * (1/freq) */\n" - " offset = %" PRIu64 ";\n" + " offset = %" PRId64 ";\n" "};\n\n", trace_clock_description(), trace_clock_freq(),