X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-metadata.c;h=e5d4944ed931ca9c2177cf124734a4dc0d3f6cf2;hb=4ce7709ba8d755049c81b5e112bce90129c0ea5a;hp=71bcf7e7d325f61764de8832b8877a0b5e7e30ed;hpb=890d8fe47755c3bad936389cf48ffa141cff41c9;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-metadata.c b/src/bin/lttng-sessiond/ust-metadata.c index 71bcf7e7d..e5d4944ed 100644 --- a/src/bin/lttng-sessiond/ust-metadata.c +++ b/src/bin/lttng-sessiond/ust-metadata.c @@ -41,7 +41,7 @@ #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 */ }; @@ -179,6 +179,102 @@ end: return ret; } +/* 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) +{ + struct ust_registry_enum *reg_enum; + const struct ustctl_enum_entry *entries; + size_t nr_entries; + int ret = 0; + size_t i; + + rcu_read_lock(); + reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id); + rcu_read_unlock(); + /* reg_enum can still be used because session registry mutex is held. */ + if (!reg_enum) { + ret = -ENOENT; + goto end; + } + entries = reg_enum->entries; + nr_entries = reg_enum->nr_entries; + + ret = lttng_metadata_printf(session, + " enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n", + container_type->size, + container_type->alignment, + container_type->signedness, + (container_type->encoding == ustctl_encode_none) + ? "none" + : (container_type->encoding == ustctl_encode_UTF8) + ? "UTF8" + : "ASCII", + container_type->base); + if (ret) { + goto end; + } + /* Dump all entries */ + for (i = 0; i < nr_entries; i++) { + const struct ustctl_enum_entry *entry = &entries[i]; + int j, len; + + ret = lttng_metadata_printf(session, + " \""); + if (ret) { + goto end; + } + len = strlen(entry->string); + /* Escape the character '"' */ + for (j = 0; j < len; j++) { + char c = entry->string[j]; + + switch (c) { + case '"': + ret = lttng_metadata_printf(session, + "\\\""); + break; + case '\\': + ret = lttng_metadata_printf(session, + "\\\\"); + break; + default: + ret = lttng_metadata_printf(session, + "%c", c); + break; + } + if (ret) { + goto end; + } + } + ret = lttng_metadata_printf(session, + "\" = "); + if (ret) { + goto end; + } + if (entry->start == entry->end) { + ret = lttng_metadata_printf(session, + "%d,\n", + entry->start); + } else { + ret = lttng_metadata_printf(session, + "%d ... %d,\n", + entry->start, entry->end); + } + if (ret) { + goto end; + } + } + ret = lttng_metadata_printf(session, " } _%s;\n", + field_name); +end: + return ret; +} + static int _lttng_field_statedump(struct ust_registry_session *session, const struct ustctl_field *field) @@ -210,6 +306,13 @@ int _lttng_field_statedump(struct ust_registry_session *session, field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name); 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); + break; case ustctl_atype_float: ret = lttng_metadata_printf(session, " floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n", @@ -219,8 +322,6 @@ int _lttng_field_statedump(struct ust_registry_session *session, field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native, field->name); break; - case ustctl_atype_enum: - return -EINVAL; case ustctl_atype_array: { const struct ustctl_basic_type *elem_type; @@ -503,10 +604,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; @@ -525,15 +630,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; } @@ -542,9 +646,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 = { @@ -692,7 +797,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(),