e20f43f667580ebbc3cffab87338ea31944f5dbf
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.c
1 /*
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <stdint.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <limits.h>
14 #include <unistd.h>
15 #include <inttypes.h>
16 #include <common/common.h>
17 #include <common/time.h>
18
19 #include "ust-registry.h"
20 #include "ust-clock.h"
21 #include "ust-app.h"
22
23 #ifndef max_t
24 #define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b)))
25 #endif
26
27 #define NR_CLOCK_OFFSET_SAMPLES 10
28
29 struct offset_sample {
30 int64_t offset; /* correlation offset */
31 uint64_t measure_delta; /* lower is better */
32 };
33
34 static
35 int _lttng_field_statedump(struct ust_registry_session *session,
36 const struct ustctl_field *fields, size_t nr_fields,
37 size_t *iter_field, size_t nesting);
38
39 static inline
40 int fls(unsigned int x)
41 {
42 int r = 32;
43
44 if (!x)
45 return 0;
46 if (!(x & 0xFFFF0000U)) {
47 x <<= 16;
48 r -= 16;
49 }
50 if (!(x & 0xFF000000U)) {
51 x <<= 8;
52 r -= 8;
53 }
54 if (!(x & 0xF0000000U)) {
55 x <<= 4;
56 r -= 4;
57 }
58 if (!(x & 0xC0000000U)) {
59 x <<= 2;
60 r -= 2;
61 }
62 if (!(x & 0x80000000U)) {
63 r -= 1;
64 }
65 return r;
66 }
67
68 static inline
69 int get_count_order(unsigned int count)
70 {
71 int order;
72
73 order = fls(count) - 1;
74 if (count & (count - 1)) {
75 order++;
76 }
77 assert(order >= 0);
78 return order;
79 }
80
81 /*
82 * Returns offset where to write in metadata array, or negative error value on error.
83 */
84 static
85 ssize_t metadata_reserve(struct ust_registry_session *session, size_t len)
86 {
87 size_t new_len = session->metadata_len + len;
88 size_t new_alloc_len = new_len;
89 size_t old_alloc_len = session->metadata_alloc_len;
90 ssize_t ret;
91
92 if (new_alloc_len > (UINT32_MAX >> 1))
93 return -EINVAL;
94 if ((old_alloc_len << 1) > (UINT32_MAX >> 1))
95 return -EINVAL;
96
97 if (new_alloc_len > old_alloc_len) {
98 char *newptr;
99
100 new_alloc_len =
101 max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
102 newptr = realloc(session->metadata, new_alloc_len);
103 if (!newptr)
104 return -ENOMEM;
105 session->metadata = newptr;
106 /* We zero directly the memory from start of allocation. */
107 memset(&session->metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
108 session->metadata_alloc_len = new_alloc_len;
109 }
110 ret = session->metadata_len;
111 session->metadata_len += len;
112 return ret;
113 }
114
115 static
116 int metadata_file_append(struct ust_registry_session *session,
117 const char *str, size_t len)
118 {
119 ssize_t written;
120
121 if (session->metadata_fd < 0) {
122 return 0;
123 }
124 /* Write to metadata file */
125 written = lttng_write(session->metadata_fd, str, len);
126 if (written != len) {
127 return -1;
128 }
129 return 0;
130 }
131
132 /*
133 * We have exclusive access to our metadata buffer (protected by the
134 * ust_lock), so we can do racy operations such as looking for
135 * remaining space left in packet and write, since mutual exclusion
136 * protects us from concurrent writes.
137 */
138 static
139 int lttng_metadata_printf(struct ust_registry_session *session,
140 const char *fmt, ...)
141 {
142 char *str = NULL;
143 size_t len;
144 va_list ap;
145 ssize_t offset;
146 int ret;
147
148 va_start(ap, fmt);
149 ret = vasprintf(&str, fmt, ap);
150 va_end(ap);
151 if (ret < 0)
152 return -ENOMEM;
153
154 len = strlen(str);
155 offset = metadata_reserve(session, len);
156 if (offset < 0) {
157 ret = offset;
158 goto end;
159 }
160 memcpy(&session->metadata[offset], str, len);
161 ret = metadata_file_append(session, str, len);
162 if (ret) {
163 PERROR("Error appending to metadata file");
164 goto end;
165 }
166 DBG3("Append to metadata: \"%s\"", str);
167 ret = 0;
168
169 end:
170 free(str);
171 return ret;
172 }
173
174 static
175 int print_tabs(struct ust_registry_session *session, size_t nesting)
176 {
177 size_t i;
178
179 for (i = 0; i < nesting; i++) {
180 int ret;
181
182 ret = lttng_metadata_printf(session, " ");
183 if (ret) {
184 return ret;
185 }
186 }
187 return 0;
188 }
189
190 static
191 void sanitize_ctf_identifier(char *out, const char *in)
192 {
193 size_t i;
194
195 for (i = 0; i < LTTNG_UST_SYM_NAME_LEN; i++) {
196 switch (in[i]) {
197 case '.':
198 case '$':
199 case ':':
200 out[i] = '_';
201 break;
202 default:
203 out[i] = in[i];
204 }
205 }
206 }
207
208 static
209 int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
210 {
211 int ret = 0;
212 size_t i;
213 char cur;
214
215 i = 0;
216 cur = string[i];
217 while (cur != '\0') {
218 switch (cur) {
219 case '\n':
220 ret = lttng_metadata_printf(session, "%s", "\\n");
221 break;
222 case '\\':
223 case '"':
224 ret = lttng_metadata_printf(session, "%c", '\\');
225 if (ret) {
226 goto error;
227 }
228 /* We still print the current char */
229 /* Fallthrough */
230 default:
231 ret = lttng_metadata_printf(session, "%c", cur);
232 break;
233 }
234
235 if (ret) {
236 goto error;
237 }
238
239 cur = string[++i];
240 }
241 error:
242 return ret;
243 }
244
245 /* Called with session registry mutex held. */
246 static
247 int ust_metadata_enum_statedump(struct ust_registry_session *session,
248 const char *enum_name,
249 uint64_t enum_id,
250 const struct ustctl_integer_type *container_type,
251 const char *field_name, size_t *iter_field, size_t nesting)
252 {
253 struct ust_registry_enum *reg_enum;
254 const struct ustctl_enum_entry *entries;
255 size_t nr_entries;
256 int ret = 0;
257 size_t i;
258 char identifier[LTTNG_UST_SYM_NAME_LEN];
259
260 rcu_read_lock();
261 reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id);
262 rcu_read_unlock();
263 /* reg_enum can still be used because session registry mutex is held. */
264 if (!reg_enum) {
265 ret = -ENOENT;
266 goto end;
267 }
268 entries = reg_enum->entries;
269 nr_entries = reg_enum->nr_entries;
270
271 ret = print_tabs(session, nesting);
272 if (ret) {
273 goto end;
274 }
275 ret = lttng_metadata_printf(session,
276 "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
277 container_type->size,
278 container_type->alignment,
279 container_type->signedness,
280 (container_type->encoding == ustctl_encode_none)
281 ? "none"
282 : (container_type->encoding == ustctl_encode_UTF8)
283 ? "UTF8"
284 : "ASCII",
285 container_type->base);
286 if (ret) {
287 goto end;
288 }
289 nesting++;
290 /* Dump all entries */
291 for (i = 0; i < nr_entries; i++) {
292 const struct ustctl_enum_entry *entry = &entries[i];
293 int j, len;
294
295 ret = print_tabs(session, nesting);
296 if (ret) {
297 goto end;
298 }
299 ret = lttng_metadata_printf(session,
300 "\"");
301 if (ret) {
302 goto end;
303 }
304 len = strlen(entry->string);
305 /* Escape the character '"' */
306 for (j = 0; j < len; j++) {
307 char c = entry->string[j];
308
309 switch (c) {
310 case '"':
311 ret = lttng_metadata_printf(session,
312 "\\\"");
313 break;
314 case '\\':
315 ret = lttng_metadata_printf(session,
316 "\\\\");
317 break;
318 default:
319 ret = lttng_metadata_printf(session,
320 "%c", c);
321 break;
322 }
323 if (ret) {
324 goto end;
325 }
326 }
327 ret = lttng_metadata_printf(session, "\"");
328 if (ret) {
329 goto end;
330 }
331
332 if (entry->u.extra.options &
333 USTCTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
334 ret = lttng_metadata_printf(session, ",\n");
335 if (ret) {
336 goto end;
337 }
338 } else {
339 ret = lttng_metadata_printf(session,
340 " = ");
341 if (ret) {
342 goto end;
343 }
344
345 if (entry->start.signedness) {
346 ret = lttng_metadata_printf(session,
347 "%lld", (long long) entry->start.value);
348 } else {
349 ret = lttng_metadata_printf(session,
350 "%llu", entry->start.value);
351 }
352 if (ret) {
353 goto end;
354 }
355
356 if (entry->start.signedness == entry->end.signedness &&
357 entry->start.value ==
358 entry->end.value) {
359 ret = lttng_metadata_printf(session, ",\n");
360 } else {
361 if (entry->end.signedness) {
362 ret = lttng_metadata_printf(session,
363 " ... %lld,\n",
364 (long long) entry->end.value);
365 } else {
366 ret = lttng_metadata_printf(session,
367 " ... %llu,\n",
368 entry->end.value);
369 }
370 }
371 if (ret) {
372 goto end;
373 }
374 }
375 }
376 nesting--;
377 sanitize_ctf_identifier(identifier, field_name);
378 ret = print_tabs(session, nesting);
379 if (ret) {
380 goto end;
381 }
382 ret = lttng_metadata_printf(session, "} _%s;\n",
383 identifier);
384 end:
385 (*iter_field)++;
386 return ret;
387 }
388
389 static
390 int _lttng_variant_statedump(struct ust_registry_session *session,
391 const struct ustctl_field *fields, size_t nr_fields,
392 size_t *iter_field, size_t nesting)
393 {
394 const struct ustctl_field *variant = &fields[*iter_field];
395 uint32_t nr_choices, i;
396 int ret;
397 char identifier[LTTNG_UST_SYM_NAME_LEN];
398
399 if (variant->type.atype != ustctl_atype_variant) {
400 ret = -EINVAL;
401 goto end;
402 }
403 nr_choices = variant->type.u.variant.nr_choices;
404 (*iter_field)++;
405 sanitize_ctf_identifier(identifier, variant->type.u.variant.tag_name);
406 ret = print_tabs(session, nesting);
407 if (ret) {
408 goto end;
409 }
410 ret = lttng_metadata_printf(session,
411 "variant <_%s> {\n",
412 identifier);
413 if (ret) {
414 goto end;
415 }
416
417 for (i = 0; i < nr_choices; i++) {
418 if (*iter_field >= nr_fields) {
419 ret = -EOVERFLOW;
420 goto end;
421 }
422 ret = _lttng_field_statedump(session,
423 fields, nr_fields,
424 iter_field, nesting + 1);
425 if (ret) {
426 goto end;
427 }
428 }
429 sanitize_ctf_identifier(identifier, variant->name);
430 ret = print_tabs(session, nesting);
431 if (ret) {
432 goto end;
433 }
434 ret = lttng_metadata_printf(session,
435 "} _%s;\n",
436 identifier);
437 if (ret) {
438 goto end;
439 }
440 end:
441 return ret;
442 }
443
444 static
445 int _lttng_field_statedump(struct ust_registry_session *session,
446 const struct ustctl_field *fields, size_t nr_fields,
447 size_t *iter_field, size_t nesting)
448 {
449 int ret = 0;
450 const char *bo_be = " byte_order = be;";
451 const char *bo_le = " byte_order = le;";
452 const char *bo_native = "";
453 const char *bo_reverse;
454 const struct ustctl_field *field;
455
456 if (*iter_field >= nr_fields) {
457 ret = -EOVERFLOW;
458 goto end;
459 }
460 field = &fields[*iter_field];
461
462 if (session->byte_order == BIG_ENDIAN) {
463 bo_reverse = bo_le;
464 } else {
465 bo_reverse = bo_be;
466 }
467
468 switch (field->type.atype) {
469 case ustctl_atype_integer:
470 ret = print_tabs(session, nesting);
471 if (ret) {
472 goto end;
473 }
474 ret = lttng_metadata_printf(session,
475 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
476 field->type.u.basic.integer.size,
477 field->type.u.basic.integer.alignment,
478 field->type.u.basic.integer.signedness,
479 (field->type.u.basic.integer.encoding == ustctl_encode_none)
480 ? "none"
481 : (field->type.u.basic.integer.encoding == ustctl_encode_UTF8)
482 ? "UTF8"
483 : "ASCII",
484 field->type.u.basic.integer.base,
485 field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
486 field->name);
487 (*iter_field)++;
488 break;
489 case ustctl_atype_enum:
490 ret = ust_metadata_enum_statedump(session,
491 field->type.u.basic.enumeration.name,
492 field->type.u.basic.enumeration.id,
493 &field->type.u.basic.enumeration.container_type,
494 field->name, iter_field, nesting);
495 break;
496 case ustctl_atype_float:
497 ret = print_tabs(session, nesting);
498 if (ret) {
499 goto end;
500 }
501 ret = lttng_metadata_printf(session,
502 "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
503 field->type.u.basic._float.exp_dig,
504 field->type.u.basic._float.mant_dig,
505 field->type.u.basic._float.alignment,
506 field->type.u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
507 field->name);
508 (*iter_field)++;
509 break;
510 case ustctl_atype_array:
511 {
512 const struct ustctl_basic_type *elem_type;
513
514 ret = print_tabs(session, nesting);
515 if (ret) {
516 goto end;
517 }
518 elem_type = &field->type.u.array.elem_type;
519 ret = lttng_metadata_printf(session,
520 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
521 elem_type->u.basic.integer.size,
522 elem_type->u.basic.integer.alignment,
523 elem_type->u.basic.integer.signedness,
524 (elem_type->u.basic.integer.encoding == ustctl_encode_none)
525 ? "none"
526 : (elem_type->u.basic.integer.encoding == ustctl_encode_UTF8)
527 ? "UTF8"
528 : "ASCII",
529 elem_type->u.basic.integer.base,
530 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
531 field->name, field->type.u.array.length);
532 (*iter_field)++;
533 break;
534 }
535 case ustctl_atype_sequence:
536 {
537 const struct ustctl_basic_type *elem_type;
538 const struct ustctl_basic_type *length_type;
539
540 elem_type = &field->type.u.sequence.elem_type;
541 length_type = &field->type.u.sequence.length_type;
542 ret = print_tabs(session, nesting);
543 if (ret) {
544 goto end;
545 }
546 ret = lttng_metadata_printf(session,
547 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
548 length_type->u.basic.integer.size,
549 (unsigned int) length_type->u.basic.integer.alignment,
550 length_type->u.basic.integer.signedness,
551 (length_type->u.basic.integer.encoding == ustctl_encode_none)
552 ? "none"
553 : ((length_type->u.basic.integer.encoding == ustctl_encode_UTF8)
554 ? "UTF8"
555 : "ASCII"),
556 length_type->u.basic.integer.base,
557 length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
558 field->name);
559 if (ret) {
560 goto end;
561 }
562
563 ret = print_tabs(session, nesting);
564 if (ret) {
565 goto end;
566 }
567 ret = lttng_metadata_printf(session,
568 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
569 elem_type->u.basic.integer.size,
570 (unsigned int) elem_type->u.basic.integer.alignment,
571 elem_type->u.basic.integer.signedness,
572 (elem_type->u.basic.integer.encoding == ustctl_encode_none)
573 ? "none"
574 : ((elem_type->u.basic.integer.encoding == ustctl_encode_UTF8)
575 ? "UTF8"
576 : "ASCII"),
577 elem_type->u.basic.integer.base,
578 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
579 field->name,
580 field->name);
581 (*iter_field)++;
582 break;
583 }
584
585 case ustctl_atype_string:
586 /* Default encoding is UTF8 */
587 ret = print_tabs(session, nesting);
588 if (ret) {
589 goto end;
590 }
591 ret = lttng_metadata_printf(session,
592 "string%s _%s;\n",
593 field->type.u.basic.string.encoding == ustctl_encode_ASCII ?
594 " { encoding = ASCII; }" : "",
595 field->name);
596 (*iter_field)++;
597 break;
598 case ustctl_atype_variant:
599 ret = _lttng_variant_statedump(session, fields, nr_fields, iter_field, nesting);
600 if (ret) {
601 goto end;
602 }
603 break;
604 case ustctl_atype_struct:
605 ret = print_tabs(session, nesting);
606 if (ret) {
607 goto end;
608 }
609 ret = lttng_metadata_printf(session,
610 "struct {} _%s;\n",
611 field->name);
612 (*iter_field)++;
613 break;
614 default:
615 ret = -EINVAL;
616 }
617 end:
618 return ret;
619 }
620
621 static
622 int _lttng_context_metadata_statedump(struct ust_registry_session *session,
623 size_t nr_ctx_fields,
624 struct ustctl_field *ctx)
625 {
626 int ret = 0;
627 size_t i = 0;
628
629 if (!ctx)
630 return 0;
631 for (;;) {
632 if (i >= nr_ctx_fields) {
633 break;
634 }
635 ret = _lttng_field_statedump(session, ctx,
636 nr_ctx_fields, &i, 2);
637 if (ret) {
638 break;
639 }
640 }
641 return ret;
642 }
643
644 static
645 int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
646 struct ust_registry_event *event)
647 {
648 int ret = 0;
649 size_t i = 0;
650
651 for (;;) {
652 if (i >= event->nr_fields) {
653 break;
654 }
655 ret = _lttng_field_statedump(session, event->fields,
656 event->nr_fields, &i, 2);
657 if (ret) {
658 break;
659 }
660 }
661 return ret;
662 }
663
664 /*
665 * Should be called with session registry mutex held.
666 */
667 int ust_metadata_event_statedump(struct ust_registry_session *session,
668 struct ust_registry_channel *chan,
669 struct ust_registry_event *event)
670 {
671 int ret = 0;
672
673 /* Don't dump metadata events */
674 if (chan->chan_id == -1U)
675 return 0;
676
677 ret = lttng_metadata_printf(session,
678 "event {\n"
679 " name = \"%s\";\n"
680 " id = %u;\n"
681 " stream_id = %u;\n",
682 event->name,
683 event->id,
684 chan->chan_id);
685 if (ret)
686 goto end;
687
688 ret = lttng_metadata_printf(session,
689 " loglevel = %d;\n",
690 event->loglevel_value);
691 if (ret)
692 goto end;
693
694 if (event->model_emf_uri) {
695 ret = lttng_metadata_printf(session,
696 " model.emf.uri = \"%s\";\n",
697 event->model_emf_uri);
698 if (ret)
699 goto end;
700 }
701
702 ret = lttng_metadata_printf(session,
703 " fields := struct {\n"
704 );
705 if (ret)
706 goto end;
707
708 ret = _lttng_fields_metadata_statedump(session, event);
709 if (ret)
710 goto end;
711
712 ret = lttng_metadata_printf(session,
713 " };\n"
714 "};\n\n");
715 if (ret)
716 goto end;
717 event->metadata_dumped = 1;
718
719 end:
720 return ret;
721 }
722
723 /*
724 * Should be called with session registry mutex held.
725 */
726 int ust_metadata_channel_statedump(struct ust_registry_session *session,
727 struct ust_registry_channel *chan)
728 {
729 int ret = 0;
730
731 /* Don't dump metadata events */
732 if (chan->chan_id == -1U)
733 return 0;
734
735 if (!chan->header_type)
736 return -EINVAL;
737
738 ret = lttng_metadata_printf(session,
739 "stream {\n"
740 " id = %u;\n"
741 " event.header := %s;\n"
742 " packet.context := struct packet_context;\n",
743 chan->chan_id,
744 chan->header_type == USTCTL_CHANNEL_HEADER_COMPACT ?
745 "struct event_header_compact" :
746 "struct event_header_large");
747 if (ret)
748 goto end;
749
750 if (chan->ctx_fields) {
751 ret = lttng_metadata_printf(session,
752 " event.context := struct {\n");
753 if (ret)
754 goto end;
755 }
756 ret = _lttng_context_metadata_statedump(session,
757 chan->nr_ctx_fields,
758 chan->ctx_fields);
759 if (ret)
760 goto end;
761 if (chan->ctx_fields) {
762 ret = lttng_metadata_printf(session,
763 " };\n");
764 if (ret)
765 goto end;
766 }
767
768 ret = lttng_metadata_printf(session,
769 "};\n\n");
770 /* Flag success of metadata dump. */
771 chan->metadata_dumped = 1;
772
773 end:
774 return ret;
775 }
776
777 static
778 int _lttng_stream_packet_context_declare(struct ust_registry_session *session)
779 {
780 return lttng_metadata_printf(session,
781 "struct packet_context {\n"
782 " uint64_clock_monotonic_t timestamp_begin;\n"
783 " uint64_clock_monotonic_t timestamp_end;\n"
784 " uint64_t content_size;\n"
785 " uint64_t packet_size;\n"
786 " uint64_t packet_seq_num;\n"
787 " unsigned long events_discarded;\n"
788 " uint32_t cpu_id;\n"
789 "};\n\n"
790 );
791 }
792
793 /*
794 * Compact header:
795 * id: range: 0 - 30.
796 * id 31 is reserved to indicate an extended header.
797 *
798 * Large header:
799 * id: range: 0 - 65534.
800 * id 65535 is reserved to indicate an extended header.
801 */
802 static
803 int _lttng_event_header_declare(struct ust_registry_session *session)
804 {
805 return lttng_metadata_printf(session,
806 "struct event_header_compact {\n"
807 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
808 " variant <id> {\n"
809 " struct {\n"
810 " uint27_clock_monotonic_t timestamp;\n"
811 " } compact;\n"
812 " struct {\n"
813 " uint32_t id;\n"
814 " uint64_clock_monotonic_t timestamp;\n"
815 " } extended;\n"
816 " } v;\n"
817 "} align(%u);\n"
818 "\n"
819 "struct event_header_large {\n"
820 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
821 " variant <id> {\n"
822 " struct {\n"
823 " uint32_clock_monotonic_t timestamp;\n"
824 " } compact;\n"
825 " struct {\n"
826 " uint32_t id;\n"
827 " uint64_clock_monotonic_t timestamp;\n"
828 " } extended;\n"
829 " } v;\n"
830 "} align(%u);\n\n",
831 session->uint32_t_alignment,
832 session->uint16_t_alignment
833 );
834 }
835
836 /*
837 * The offset between monotonic and realtime clock can be negative if
838 * the system sets the REALTIME clock to 0 after boot.
839 */
840 static
841 int measure_single_clock_offset(struct offset_sample *sample)
842 {
843 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
844 uint64_t tcf = trace_clock_freq();
845 struct timespec rts = { 0, 0 };
846 int ret;
847
848 monotonic[0] = trace_clock_read64();
849 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
850 if (ret < 0) {
851 return ret;
852 }
853 monotonic[1] = trace_clock_read64();
854 measure_delta = monotonic[1] - monotonic[0];
855 if (measure_delta > sample->measure_delta) {
856 /*
857 * Discard value if it took longer to read than the best
858 * sample so far.
859 */
860 return 0;
861 }
862 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
863 realtime = (uint64_t) rts.tv_sec * tcf;
864 if (tcf == NSEC_PER_SEC) {
865 realtime += rts.tv_nsec;
866 } else {
867 realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC;
868 }
869 sample->offset = (int64_t) realtime - monotonic_avg;
870 sample->measure_delta = measure_delta;
871 return 0;
872 }
873
874 /*
875 * Approximation of NTP time of day to clock monotonic correlation,
876 * taken at start of trace. Keep the measurement that took the less time
877 * to complete, thus removing imprecision caused by preemption.
878 * May return a negative offset.
879 */
880 static
881 int64_t measure_clock_offset(void)
882 {
883 int i;
884 struct offset_sample offset_best_sample = {
885 .offset = 0,
886 .measure_delta = UINT64_MAX,
887 };
888
889 for (i = 0; i < NR_CLOCK_OFFSET_SAMPLES; i++) {
890 if (measure_single_clock_offset(&offset_best_sample)) {
891 return 0;
892 }
893 }
894 return offset_best_sample.offset;
895 }
896
897 static
898 int print_metadata_session_information(struct ust_registry_session *registry)
899 {
900 int ret;
901 struct ltt_session *session = NULL;
902 char creation_datetime[ISO8601_STR_LEN];
903
904 rcu_read_lock();
905 session = session_find_by_id(registry->tracing_id);
906 if (!session) {
907 ret = -1;
908 goto error;
909 }
910
911 /* Print the trace name */
912 ret = lttng_metadata_printf(registry, " trace_name = \"");
913 if (ret) {
914 goto error;
915 }
916
917 /*
918 * This is necessary since the creation time is present in the session
919 * name when it is generated.
920 */
921 if (session->has_auto_generated_name) {
922 ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME);
923 } else {
924 ret = print_escaped_ctf_string(registry, session->name);
925 }
926 if (ret) {
927 goto error;
928 }
929
930 ret = lttng_metadata_printf(registry, "\";\n");
931 if (ret) {
932 goto error;
933 }
934
935 /* Prepare creation time */
936 ret = time_to_iso8601_str(session->creation_time, creation_datetime,
937 sizeof(creation_datetime));
938 if (ret) {
939 goto error;
940 }
941
942 /* Output the reste of the information */
943 ret = lttng_metadata_printf(registry,
944 " trace_creation_datetime = \"%s\";\n"
945 " hostname = \"%s\";\n",
946 creation_datetime, session->hostname);
947 if (ret) {
948 goto error;
949 }
950
951 error:
952 if (session) {
953 session_put(session);
954 }
955 rcu_read_unlock();
956 return ret;
957 }
958
959 static
960 int print_metadata_app_information(struct ust_registry_session *registry,
961 struct ust_app *app)
962 {
963 int ret;
964 char datetime[ISO8601_STR_LEN];
965
966 if (!app) {
967 ret = 0;
968 goto end;
969 }
970
971 ret = time_to_iso8601_str(
972 app->registration_time, datetime, sizeof(datetime));
973 if (ret) {
974 goto end;
975 }
976
977 ret = lttng_metadata_printf(registry,
978 " tracer_patchlevel = %u;\n"
979 " vpid = %d;\n"
980 " procname = \"%s\";\n"
981 " vpid_datetime = \"%s\";\n",
982 app->version.patchlevel, (int) app->pid, app->name,
983 datetime);
984
985 end:
986 return ret;
987 }
988
989 /*
990 * Should be called with session registry mutex held.
991 */
992 int ust_metadata_session_statedump(struct ust_registry_session *session,
993 struct ust_app *app,
994 uint32_t major,
995 uint32_t minor)
996 {
997 char uuid_s[LTTNG_UUID_STR_LEN],
998 clock_uuid_s[LTTNG_UUID_STR_LEN];
999 int ret = 0;
1000
1001 assert(session);
1002
1003 lttng_uuid_to_str(session->uuid, uuid_s);
1004
1005 /* For crash ABI */
1006 ret = lttng_metadata_printf(session,
1007 "/* CTF %u.%u */\n\n",
1008 CTF_SPEC_MAJOR,
1009 CTF_SPEC_MINOR);
1010 if (ret) {
1011 goto end;
1012 }
1013
1014 ret = lttng_metadata_printf(session,
1015 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
1016 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
1017 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
1018 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
1019 "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n"
1020 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
1021 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
1022 "\n"
1023 "trace {\n"
1024 " major = %u;\n"
1025 " minor = %u;\n"
1026 " uuid = \"%s\";\n"
1027 " byte_order = %s;\n"
1028 " packet.header := struct {\n"
1029 " uint32_t magic;\n"
1030 " uint8_t uuid[16];\n"
1031 " uint32_t stream_id;\n"
1032 " uint64_t stream_instance_id;\n"
1033 " };\n"
1034 "};\n\n",
1035 session->uint8_t_alignment,
1036 session->uint16_t_alignment,
1037 session->uint32_t_alignment,
1038 session->uint64_t_alignment,
1039 session->bits_per_long,
1040 session->long_alignment,
1041 CTF_SPEC_MAJOR,
1042 CTF_SPEC_MINOR,
1043 uuid_s,
1044 session->byte_order == BIG_ENDIAN ? "be" : "le"
1045 );
1046 if (ret)
1047 goto end;
1048
1049 ret = lttng_metadata_printf(session,
1050 "env {\n"
1051 " domain = \"ust\";\n"
1052 " tracer_name = \"lttng-ust\";\n"
1053 " tracer_major = %u;\n"
1054 " tracer_minor = %u;\n"
1055 " tracer_buffering_scheme = \"%s\";\n"
1056 " tracer_buffering_id = %u;\n"
1057 " architecture_bit_width = %u;\n",
1058 major,
1059 minor,
1060 app ? "pid" : "uid",
1061 app ? (int) app->pid : (int) session->tracing_uid,
1062 session->bits_per_long);
1063 if (ret) {
1064 goto end;
1065 }
1066
1067 ret = print_metadata_session_information(session);
1068 if (ret) {
1069 goto end;
1070 }
1071
1072 /*
1073 * If per-application registry, we can output extra information
1074 * about the application.
1075 */
1076 ret = print_metadata_app_information(session, app);
1077 if (ret) {
1078 goto end;
1079 }
1080
1081 ret = lttng_metadata_printf(session,
1082 "};\n\n"
1083 );
1084 if (ret)
1085 goto end;
1086
1087
1088 ret = lttng_metadata_printf(session,
1089 "clock {\n"
1090 " name = \"%s\";\n",
1091 trace_clock_name()
1092 );
1093 if (ret)
1094 goto end;
1095
1096 if (!trace_clock_uuid(clock_uuid_s)) {
1097 ret = lttng_metadata_printf(session,
1098 " uuid = \"%s\";\n",
1099 clock_uuid_s
1100 );
1101 if (ret)
1102 goto end;
1103 }
1104
1105 ret = lttng_metadata_printf(session,
1106 " description = \"%s\";\n"
1107 " freq = %" PRIu64 "; /* Frequency, in Hz */\n"
1108 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
1109 " offset = %" PRId64 ";\n"
1110 "};\n\n",
1111 trace_clock_description(),
1112 trace_clock_freq(),
1113 measure_clock_offset()
1114 );
1115 if (ret)
1116 goto end;
1117
1118 ret = lttng_metadata_printf(session,
1119 "typealias integer {\n"
1120 " size = 27; align = 1; signed = false;\n"
1121 " map = clock.%s.value;\n"
1122 "} := uint27_clock_monotonic_t;\n"
1123 "\n"
1124 "typealias integer {\n"
1125 " size = 32; align = %u; signed = false;\n"
1126 " map = clock.%s.value;\n"
1127 "} := uint32_clock_monotonic_t;\n"
1128 "\n"
1129 "typealias integer {\n"
1130 " size = 64; align = %u; signed = false;\n"
1131 " map = clock.%s.value;\n"
1132 "} := uint64_clock_monotonic_t;\n\n",
1133 trace_clock_name(),
1134 session->uint32_t_alignment,
1135 trace_clock_name(),
1136 session->uint64_t_alignment,
1137 trace_clock_name()
1138 );
1139 if (ret)
1140 goto end;
1141
1142 ret = _lttng_stream_packet_context_declare(session);
1143 if (ret)
1144 goto end;
1145
1146 ret = _lttng_event_header_declare(session);
1147 if (ret)
1148 goto end;
1149
1150 end:
1151 return ret;
1152 }
This page took 0.085173 seconds and 3 git commands to generate.