libust 2.0 + ringbuffer + TRACEPOINT_EVENT builds and runs
[lttng-ust.git] / libust / ltt-events.c
1 /*
2 * ltt-events.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Holds LTTng per-session event registry.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
11 #define _GNU_SOURCE
12 #include <stdio.h>
13 #include <urcu/list.h>
14 #include <pthread.h>
15 #include <urcu-bp.h>
16 #include <urcu/compiler.h>
17 #include <urcu/uatomic.h>
18 #include <uuid/uuid.h>
19 #include <ust/tracepoint.h>
20 #include <errno.h>
21 #include <sys/shm.h>
22 #include <sys/ipc.h>
23 #include <ust/lttng-events.h>
24 #include "usterr_signal_safe.h"
25 #include "ust/core.h"
26 #include "ltt-tracer.h"
27 #include "ust/wait.h"
28 #include "../libringbuffer/shm.h"
29
30 static CDS_LIST_HEAD(sessions);
31 static CDS_LIST_HEAD(ltt_transport_list);
32 static DEFINE_MUTEX(sessions_mutex);
33
34 static void _ltt_event_destroy(struct ltt_event *event);
35 static void _ltt_channel_destroy(struct ltt_channel *chan);
36 static int _ltt_event_unregister(struct ltt_event *event);
37 static
38 int _ltt_event_metadata_statedump(struct ltt_session *session,
39 struct ltt_channel *chan,
40 struct ltt_event *event);
41 static
42 int _ltt_session_metadata_statedump(struct ltt_session *session);
43
44 void synchronize_trace(void)
45 {
46 synchronize_rcu();
47 }
48
49 struct ltt_session *ltt_session_create(void)
50 {
51 struct ltt_session *session;
52
53 pthread_mutex_lock(&sessions_mutex);
54 session = zmalloc(sizeof(struct ltt_session));
55 if (!session)
56 return NULL;
57 CDS_INIT_LIST_HEAD(&session->chan);
58 CDS_INIT_LIST_HEAD(&session->events);
59 uuid_generate(session->uuid);
60 cds_list_add(&session->list, &sessions);
61 pthread_mutex_unlock(&sessions_mutex);
62 return session;
63 }
64
65 void ltt_session_destroy(struct ltt_session *session)
66 {
67 struct ltt_channel *chan, *tmpchan;
68 struct ltt_event *event, *tmpevent;
69 int ret;
70
71 pthread_mutex_lock(&sessions_mutex);
72 CMM_ACCESS_ONCE(session->active) = 0;
73 cds_list_for_each_entry(event, &session->events, list) {
74 ret = _ltt_event_unregister(event);
75 WARN_ON(ret);
76 }
77 synchronize_trace(); /* Wait for in-flight events to complete */
78 cds_list_for_each_entry_safe(event, tmpevent, &session->events, list)
79 _ltt_event_destroy(event);
80 cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
81 _ltt_channel_destroy(chan);
82 cds_list_del(&session->list);
83 pthread_mutex_unlock(&sessions_mutex);
84 free(session);
85 }
86
87 int ltt_session_enable(struct ltt_session *session)
88 {
89 int ret = 0;
90 struct ltt_channel *chan;
91
92 pthread_mutex_lock(&sessions_mutex);
93 if (session->active) {
94 ret = -EBUSY;
95 goto end;
96 }
97
98 /*
99 * Snapshot the number of events per channel to know the type of header
100 * we need to use.
101 */
102 cds_list_for_each_entry(chan, &session->chan, list) {
103 if (chan->header_type)
104 continue; /* don't change it if session stop/restart */
105 if (chan->free_event_id < 31)
106 chan->header_type = 1; /* compact */
107 else
108 chan->header_type = 2; /* large */
109 }
110
111 CMM_ACCESS_ONCE(session->active) = 1;
112 CMM_ACCESS_ONCE(session->been_active) = 1;
113 ret = _ltt_session_metadata_statedump(session);
114 if (ret)
115 CMM_ACCESS_ONCE(session->active) = 0;
116 end:
117 pthread_mutex_unlock(&sessions_mutex);
118 return ret;
119 }
120
121 int ltt_session_disable(struct ltt_session *session)
122 {
123 int ret = 0;
124
125 pthread_mutex_lock(&sessions_mutex);
126 if (!session->active) {
127 ret = -EBUSY;
128 goto end;
129 }
130 CMM_ACCESS_ONCE(session->active) = 0;
131 end:
132 pthread_mutex_unlock(&sessions_mutex);
133 return ret;
134 }
135
136 int ltt_channel_enable(struct ltt_channel *channel)
137 {
138 int old;
139
140 if (channel == channel->session->metadata)
141 return -EPERM;
142 old = uatomic_xchg(&channel->enabled, 1);
143 if (old)
144 return -EEXIST;
145 return 0;
146 }
147
148 int ltt_channel_disable(struct ltt_channel *channel)
149 {
150 int old;
151
152 if (channel == channel->session->metadata)
153 return -EPERM;
154 old = uatomic_xchg(&channel->enabled, 0);
155 if (!old)
156 return -EEXIST;
157 return 0;
158 }
159
160 int ltt_event_enable(struct ltt_event *event)
161 {
162 int old;
163
164 if (event->chan == event->chan->session->metadata)
165 return -EPERM;
166 old = uatomic_xchg(&event->enabled, 1);
167 if (old)
168 return -EEXIST;
169 return 0;
170 }
171
172 int ltt_event_disable(struct ltt_event *event)
173 {
174 int old;
175
176 if (event->chan == event->chan->session->metadata)
177 return -EPERM;
178 old = uatomic_xchg(&event->enabled, 0);
179 if (!old)
180 return -EEXIST;
181 return 0;
182 }
183
184 static struct ltt_transport *ltt_transport_find(const char *name)
185 {
186 struct ltt_transport *transport;
187
188 cds_list_for_each_entry(transport, &ltt_transport_list, node) {
189 if (!strcmp(transport->name, name))
190 return transport;
191 }
192 return NULL;
193 }
194
195 struct ltt_channel *ltt_channel_create(struct ltt_session *session,
196 const char *transport_name,
197 void *buf_addr,
198 size_t subbuf_size, size_t num_subbuf,
199 unsigned int switch_timer_interval,
200 unsigned int read_timer_interval)
201 {
202 struct ltt_channel *chan;
203 struct ltt_transport *transport;
204
205 pthread_mutex_lock(&sessions_mutex);
206 if (session->been_active)
207 goto active; /* Refuse to add channel to active session */
208 transport = ltt_transport_find(transport_name);
209 if (!transport) {
210 DBG("LTTng transport %s not found\n",
211 transport_name);
212 goto notransport;
213 }
214 chan = zmalloc(sizeof(struct ltt_channel));
215 if (!chan)
216 goto nomem;
217 chan->session = session;
218 chan->id = session->free_chan_id++;
219 /*
220 * Note: the channel creation op already writes into the packet
221 * headers. Therefore the "chan" information used as input
222 * should be already accessible.
223 */
224 chan->handle = transport->ops.channel_create("[lttng]", chan, buf_addr,
225 subbuf_size, num_subbuf, switch_timer_interval,
226 read_timer_interval);
227 chan->chan = shmp(chan->handle->header->chan);
228 if (!chan->chan)
229 goto create_error;
230 chan->enabled = 1;
231 chan->ops = &transport->ops;
232 cds_list_add(&chan->list, &session->chan);
233 pthread_mutex_unlock(&sessions_mutex);
234 return chan;
235
236 create_error:
237 free(chan);
238 nomem:
239 notransport:
240 active:
241 pthread_mutex_unlock(&sessions_mutex);
242 return NULL;
243 }
244
245 /*
246 * Only used internally at session destruction.
247 */
248 static
249 void _ltt_channel_destroy(struct ltt_channel *chan)
250 {
251 chan->ops->channel_destroy(chan->handle);
252 cds_list_del(&chan->list);
253 lttng_destroy_context(chan->ctx);
254 free(chan);
255 }
256
257 /*
258 * Supports event creation while tracing session is active.
259 */
260 struct ltt_event *ltt_event_create(struct ltt_channel *chan,
261 struct lttng_ust_event *event_param,
262 void *filter)
263 {
264 struct ltt_event *event;
265 int ret;
266
267 pthread_mutex_lock(&sessions_mutex);
268 if (chan->free_event_id == -1UL)
269 goto full;
270 /*
271 * This is O(n^2) (for each event, the loop is called at event
272 * creation). Might require a hash if we have lots of events.
273 */
274 cds_list_for_each_entry(event, &chan->session->events, list)
275 if (!strcmp(event->desc->name, event_param->name))
276 goto exist;
277 event = zmalloc(sizeof(struct ltt_event));
278 if (!event)
279 goto cache_error;
280 event->chan = chan;
281 event->filter = filter;
282 event->id = chan->free_event_id++;
283 event->enabled = 1;
284 event->instrumentation = event_param->instrumentation;
285 /* Populate ltt_event structure before tracepoint registration. */
286 cmm_smp_wmb();
287 switch (event_param->instrumentation) {
288 case LTTNG_UST_TRACEPOINT:
289 event->desc = ltt_event_get(event_param->name);
290 if (!event->desc)
291 goto register_error;
292 ret = __tracepoint_probe_register(event_param->name,
293 event->desc->probe_callback,
294 event);
295 if (ret)
296 goto register_error;
297 break;
298 default:
299 WARN_ON_ONCE(1);
300 }
301 ret = _ltt_event_metadata_statedump(chan->session, chan, event);
302 if (ret)
303 goto statedump_error;
304 cds_list_add(&event->list, &chan->session->events);
305 pthread_mutex_unlock(&sessions_mutex);
306 return event;
307
308 statedump_error:
309 WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name,
310 event->desc->probe_callback,
311 event));
312 ltt_event_put(event->desc);
313 register_error:
314 free(event);
315 cache_error:
316 exist:
317 full:
318 pthread_mutex_unlock(&sessions_mutex);
319 return NULL;
320 }
321
322 /*
323 * Only used internally at session destruction.
324 */
325 int _ltt_event_unregister(struct ltt_event *event)
326 {
327 int ret = -EINVAL;
328
329 switch (event->instrumentation) {
330 case LTTNG_UST_TRACEPOINT:
331 ret = __tracepoint_probe_unregister(event->desc->name,
332 event->desc->probe_callback,
333 event);
334 if (ret)
335 return ret;
336 break;
337 default:
338 WARN_ON_ONCE(1);
339 }
340 return ret;
341 }
342
343 /*
344 * Only used internally at session destruction.
345 */
346 static
347 void _ltt_event_destroy(struct ltt_event *event)
348 {
349 switch (event->instrumentation) {
350 case LTTNG_UST_TRACEPOINT:
351 ltt_event_put(event->desc);
352 break;
353 default:
354 WARN_ON_ONCE(1);
355 }
356 cds_list_del(&event->list);
357 lttng_destroy_context(event->ctx);
358 free(event);
359 }
360
361 /*
362 * We have exclusive access to our metadata buffer (protected by the
363 * sessions_mutex), so we can do racy operations such as looking for
364 * remaining space left in packet and write, since mutual exclusion
365 * protects us from concurrent writes.
366 */
367 int lttng_metadata_printf(struct ltt_session *session,
368 const char *fmt, ...)
369 {
370 struct lib_ring_buffer_ctx ctx;
371 struct ltt_channel *chan = session->metadata;
372 char *str = NULL;
373 int ret = 0, waitret;
374 size_t len, reserve_len, pos;
375 va_list ap;
376
377 WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active));
378
379 va_start(ap, fmt);
380 ret = vasprintf(&str, fmt, ap);
381 va_end(ap);
382 if (ret < 0)
383 return -ENOMEM;
384
385 len = strlen(str);
386 pos = 0;
387
388 for (pos = 0; pos < len; pos += reserve_len) {
389 reserve_len = min_t(size_t,
390 chan->ops->packet_avail_size(chan->chan),
391 len - pos);
392 lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
393 sizeof(char), -1);
394 /*
395 * We don't care about metadata buffer's records lost
396 * count, because we always retry here. Report error if
397 * we need to bail out after timeout or being
398 * interrupted.
399 */
400 waitret = wait_cond_interruptible_timeout(
401 ({
402 ret = chan->ops->event_reserve(&ctx, 0);
403 ret != -ENOBUFS || !ret;
404 }),
405 LTTNG_METADATA_TIMEOUT_MSEC);
406 if (!waitret || waitret == -EINTR || ret) {
407 DBG("LTTng: Failure to write metadata to buffers (%s)\n",
408 waitret == -EINTR ? "interrupted" :
409 (ret == -ENOBUFS ? "timeout" : "I/O error"));
410 if (waitret == -EINTR)
411 ret = waitret;
412 goto end;
413 }
414 chan->ops->event_write(&ctx, &str[pos], reserve_len);
415 chan->ops->event_commit(&ctx);
416 }
417 end:
418 free(str);
419 return ret;
420 }
421
422 static
423 int _ltt_field_statedump(struct ltt_session *session,
424 const struct lttng_event_field *field)
425 {
426 int ret = 0;
427
428 switch (field->type.atype) {
429 case atype_integer:
430 ret = lttng_metadata_printf(session,
431 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s;\n",
432 field->type.u.basic.integer.size,
433 field->type.u.basic.integer.alignment,
434 field->type.u.basic.integer.signedness,
435 (field->type.u.basic.integer.encoding == lttng_encode_none)
436 ? "none"
437 : (field->type.u.basic.integer.encoding == lttng_encode_UTF8)
438 ? "UTF8"
439 : "ASCII",
440 field->type.u.basic.integer.base,
441 #ifdef __BIG_ENDIAN
442 field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
443 #else
444 field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
445 #endif
446 field->name);
447 break;
448 case atype_float:
449 ret = lttng_metadata_printf(session,
450 " floating_point { exp_dig = %u; mant_dig = %u; align = %u; } %s;\n",
451 field->type.u.basic._float.exp_dig,
452 field->type.u.basic._float.mant_dig,
453 field->type.u.basic._float.alignment,
454 #ifdef __BIG_ENDIAN
455 field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
456 #else
457 field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
458 #endif
459 field->name);
460 break;
461 case atype_enum:
462 ret = lttng_metadata_printf(session,
463 " %s %s;\n",
464 field->type.u.basic.enumeration.name,
465 field->name);
466 break;
467 case atype_array:
468 {
469 const struct lttng_basic_type *elem_type;
470
471 elem_type = &field->type.u.array.elem_type;
472 ret = lttng_metadata_printf(session,
473 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s[%u];\n",
474 elem_type->u.basic.integer.size,
475 elem_type->u.basic.integer.alignment,
476 elem_type->u.basic.integer.signedness,
477 (elem_type->u.basic.integer.encoding == lttng_encode_none)
478 ? "none"
479 : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
480 ? "UTF8"
481 : "ASCII",
482 elem_type->u.basic.integer.base,
483 #ifdef __BIG_ENDIAN
484 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
485 #else
486 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
487 #endif
488 field->name, field->type.u.array.length);
489 break;
490 }
491 case atype_sequence:
492 {
493 const struct lttng_basic_type *elem_type;
494 const struct lttng_basic_type *length_type;
495
496 elem_type = &field->type.u.sequence.elem_type;
497 length_type = &field->type.u.sequence.length_type;
498 ret = lttng_metadata_printf(session,
499 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
500 length_type->u.basic.integer.size,
501 (unsigned int) length_type->u.basic.integer.alignment,
502 length_type->u.basic.integer.signedness,
503 (length_type->u.basic.integer.encoding == lttng_encode_none)
504 ? "none"
505 : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8)
506 ? "UTF8"
507 : "ASCII"),
508 length_type->u.basic.integer.base,
509 #ifdef __BIG_ENDIAN
510 length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
511 #else
512 length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
513 #endif
514 field->name);
515 if (ret)
516 return ret;
517
518 ret = lttng_metadata_printf(session,
519 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s[ __%s_length ];\n",
520 elem_type->u.basic.integer.size,
521 (unsigned int) elem_type->u.basic.integer.alignment,
522 elem_type->u.basic.integer.signedness,
523 (elem_type->u.basic.integer.encoding == lttng_encode_none)
524 ? "none"
525 : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
526 ? "UTF8"
527 : "ASCII"),
528 elem_type->u.basic.integer.base,
529 #ifdef __BIG_ENDIAN
530 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
531 #else
532 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
533 #endif
534 field->name,
535 field->name);
536 break;
537 }
538
539 case atype_string:
540 /* Default encoding is UTF8 */
541 ret = lttng_metadata_printf(session,
542 " string%s %s;\n",
543 field->type.u.basic.string.encoding == lttng_encode_ASCII ?
544 " { encoding = ASCII; }" : "",
545 field->name);
546 break;
547 default:
548 WARN_ON_ONCE(1);
549 return -EINVAL;
550 }
551 return ret;
552 }
553
554 static
555 int _ltt_context_metadata_statedump(struct ltt_session *session,
556 struct lttng_ctx *ctx)
557 {
558 int ret = 0;
559 int i;
560
561 if (!ctx)
562 return 0;
563 for (i = 0; i < ctx->nr_fields; i++) {
564 const struct lttng_ctx_field *field = &ctx->fields[i];
565
566 ret = _ltt_field_statedump(session, &field->event_field);
567 if (ret)
568 return ret;
569 }
570 return ret;
571 }
572
573 static
574 int _ltt_fields_metadata_statedump(struct ltt_session *session,
575 struct ltt_event *event)
576 {
577 const struct lttng_event_desc *desc = event->desc;
578 int ret = 0;
579 int i;
580
581 for (i = 0; i < desc->nr_fields; i++) {
582 const struct lttng_event_field *field = &desc->fields[i];
583
584 ret = _ltt_field_statedump(session, field);
585 if (ret)
586 return ret;
587 }
588 return ret;
589 }
590
591 static
592 int _ltt_event_metadata_statedump(struct ltt_session *session,
593 struct ltt_channel *chan,
594 struct ltt_event *event)
595 {
596 int ret = 0;
597
598 if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
599 return 0;
600 if (chan == session->metadata)
601 return 0;
602
603 ret = lttng_metadata_printf(session,
604 "event {\n"
605 " name = %s;\n"
606 " id = %u;\n"
607 " stream_id = %u;\n",
608 event->desc->name,
609 event->id,
610 event->chan->id);
611 if (ret)
612 goto end;
613
614 if (event->ctx) {
615 ret = lttng_metadata_printf(session,
616 " context := struct {\n");
617 if (ret)
618 goto end;
619 }
620 ret = _ltt_context_metadata_statedump(session, event->ctx);
621 if (ret)
622 goto end;
623 if (event->ctx) {
624 ret = lttng_metadata_printf(session,
625 " };\n");
626 if (ret)
627 goto end;
628 }
629
630 ret = lttng_metadata_printf(session,
631 " fields := struct {\n"
632 );
633 if (ret)
634 goto end;
635
636 ret = _ltt_fields_metadata_statedump(session, event);
637 if (ret)
638 goto end;
639
640 /*
641 * LTTng space reservation can only reserve multiples of the
642 * byte size.
643 */
644 ret = lttng_metadata_printf(session,
645 " };\n"
646 "};\n\n");
647 if (ret)
648 goto end;
649
650 event->metadata_dumped = 1;
651 end:
652 return ret;
653
654 }
655
656 static
657 int _ltt_channel_metadata_statedump(struct ltt_session *session,
658 struct ltt_channel *chan)
659 {
660 int ret = 0;
661
662 if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
663 return 0;
664 if (chan == session->metadata)
665 return 0;
666
667 WARN_ON_ONCE(!chan->header_type);
668 ret = lttng_metadata_printf(session,
669 "stream {\n"
670 " id = %u;\n"
671 " event.header := %s;\n"
672 " packet.context := struct packet_context;\n",
673 chan->id,
674 chan->header_type == 1 ? "struct event_header_compact" :
675 "struct event_header_large");
676 if (ret)
677 goto end;
678
679 if (chan->ctx) {
680 ret = lttng_metadata_printf(session,
681 " event.context := struct {\n");
682 if (ret)
683 goto end;
684 }
685 ret = _ltt_context_metadata_statedump(session, chan->ctx);
686 if (ret)
687 goto end;
688 if (chan->ctx) {
689 ret = lttng_metadata_printf(session,
690 " };\n");
691 if (ret)
692 goto end;
693 }
694
695 ret = lttng_metadata_printf(session,
696 "};\n\n");
697
698 chan->metadata_dumped = 1;
699 end:
700 return ret;
701 }
702
703 static
704 int _ltt_stream_packet_context_declare(struct ltt_session *session)
705 {
706 return lttng_metadata_printf(session,
707 "struct packet_context {\n"
708 " uint64_t timestamp_begin;\n"
709 " uint64_t timestamp_end;\n"
710 " uint32_t events_discarded;\n"
711 " uint32_t content_size;\n"
712 " uint32_t packet_size;\n"
713 " uint32_t cpu_id;\n"
714 "};\n\n"
715 );
716 }
717
718 /*
719 * Compact header:
720 * id: range: 0 - 30.
721 * id 31 is reserved to indicate an extended header.
722 *
723 * Large header:
724 * id: range: 0 - 65534.
725 * id 65535 is reserved to indicate an extended header.
726 */
727 static
728 int _ltt_event_header_declare(struct ltt_session *session)
729 {
730 return lttng_metadata_printf(session,
731 "struct event_header_compact {\n"
732 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
733 " variant <id> {\n"
734 " struct {\n"
735 " uint27_t timestamp;\n"
736 " } compact;\n"
737 " struct {\n"
738 " uint32_t id;\n"
739 " uint64_t timestamp;\n"
740 " } extended;\n"
741 " } v;\n"
742 "} align(%u);\n"
743 "\n"
744 "struct event_header_large {\n"
745 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
746 " variant <id> {\n"
747 " struct {\n"
748 " uint32_t timestamp;\n"
749 " } compact;\n"
750 " struct {\n"
751 " uint32_t id;\n"
752 " uint64_t timestamp;\n"
753 " } extended;\n"
754 " } v;\n"
755 "} align(%u);\n\n",
756 ltt_alignof(uint32_t) * CHAR_BIT,
757 ltt_alignof(uint16_t) * CHAR_BIT
758 );
759 }
760
761 /*
762 * Output metadata into this session's metadata buffers.
763 */
764 static
765 int _ltt_session_metadata_statedump(struct ltt_session *session)
766 {
767 unsigned char *uuid_c = session->uuid;
768 char uuid_s[37];
769 struct ltt_channel *chan;
770 struct ltt_event *event;
771 int ret = 0;
772
773 if (!CMM_ACCESS_ONCE(session->active))
774 return 0;
775 if (session->metadata_dumped)
776 goto skip_session;
777 if (!session->metadata) {
778 DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n");
779 return -EPERM;
780 }
781
782 snprintf(uuid_s, sizeof(uuid_s),
783 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
784 uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3],
785 uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7],
786 uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11],
787 uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]);
788
789 ret = lttng_metadata_printf(session,
790 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
791 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
792 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
793 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
794 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
795 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
796 "\n"
797 "trace {\n"
798 " major = %u;\n"
799 " minor = %u;\n"
800 " uuid = \"%s\";\n"
801 " byte_order = %s;\n"
802 " packet.header := struct {\n"
803 " uint32_t magic;\n"
804 " uint8_t uuid[16];\n"
805 " uint32_t stream_id;\n"
806 " };\n"
807 "};\n\n",
808 ltt_alignof(uint8_t) * CHAR_BIT,
809 ltt_alignof(uint16_t) * CHAR_BIT,
810 ltt_alignof(uint32_t) * CHAR_BIT,
811 ltt_alignof(uint64_t) * CHAR_BIT,
812 CTF_VERSION_MAJOR,
813 CTF_VERSION_MINOR,
814 uuid_s,
815 #ifdef __BIG_ENDIAN
816 "be"
817 #else
818 "le"
819 #endif
820 );
821 if (ret)
822 goto end;
823
824 ret = _ltt_stream_packet_context_declare(session);
825 if (ret)
826 goto end;
827
828 ret = _ltt_event_header_declare(session);
829 if (ret)
830 goto end;
831
832 skip_session:
833 cds_list_for_each_entry(chan, &session->chan, list) {
834 ret = _ltt_channel_metadata_statedump(session, chan);
835 if (ret)
836 goto end;
837 }
838
839 cds_list_for_each_entry(event, &session->events, list) {
840 ret = _ltt_event_metadata_statedump(session, event->chan, event);
841 if (ret)
842 goto end;
843 }
844 session->metadata_dumped = 1;
845 end:
846 return ret;
847 }
848
849 /**
850 * ltt_transport_register - LTT transport registration
851 * @transport: transport structure
852 *
853 * Registers a transport which can be used as output to extract the data out of
854 * LTTng.
855 */
856 void ltt_transport_register(struct ltt_transport *transport)
857 {
858 pthread_mutex_lock(&sessions_mutex);
859 cds_list_add_tail(&transport->node, &ltt_transport_list);
860 pthread_mutex_unlock(&sessions_mutex);
861 }
862
863 /**
864 * ltt_transport_unregister - LTT transport unregistration
865 * @transport: transport structure
866 */
867 void ltt_transport_unregister(struct ltt_transport *transport)
868 {
869 pthread_mutex_lock(&sessions_mutex);
870 cds_list_del(&transport->node);
871 pthread_mutex_unlock(&sessions_mutex);
872 }
873
874 static
875 void __attribute__((destructor)) ltt_events_exit(void)
876 {
877 struct ltt_session *session, *tmpsession;
878
879 cds_list_for_each_entry_safe(session, tmpsession, &sessions, list)
880 ltt_session_destroy(session);
881 }
This page took 0.050496 seconds and 4 git commands to generate.