clock offset: print negative value in metadata for lttng-ust metadata
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.c
index 71bcf7e7d325f61764de8832b8877a0b5e7e30ed..e5d4944ed931ca9c2177cf124734a4dc0d3f6cf2 100644 (file)
@@ -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(),
This page took 0.026475 seconds and 4 git commands to generate.