Add sock flush buffer ctl API
[lttng-ust.git] / liblttng-ust / ltt-events.c
CommitLineData
8020ceb5
MD
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
b5234c06
MD
11#define _GNU_SOURCE
12#include <stdio.h>
8a98a75d 13#include <endian.h>
b5234c06 14#include <urcu/list.h>
8165c8da 15#include <urcu/hlist.h>
b5234c06 16#include <pthread.h>
b5234c06 17#include <uuid/uuid.h>
b5234c06 18#include <errno.h>
f4681817
MD
19#include <sys/shm.h>
20#include <sys/ipc.h>
44c72f10
MD
21#include <stdint.h>
22#include <stddef.h>
23
24#include <urcu-bp.h>
25#include <urcu/compiler.h>
26#include <urcu/uatomic.h>
27#include <urcu/arch.h>
28
29#include <lttng/tracepoint.h>
4318ae1b 30#include <lttng/ust-events.h>
44c72f10
MD
31
32#include <usterr-signal-safe.h>
33#include <helper.h>
1f18504e 34#include "error.h"
44c72f10 35
8020ceb5 36#include "ltt-tracer.h"
8165c8da 37#include "ltt-tracer-core.h"
b728d87e 38#include "wait.h"
8d8a24c8 39#include "../libringbuffer/shm.h"
596c4223 40#include "jhash.h"
8165c8da
MD
41
42/*
43 * The sessions mutex is the centralized mutex across UST tracing
17dfb34b
MD
44 * control and probe registration. All operations within this file are
45 * called by the communication thread, under ust_lock protection.
8165c8da 46 */
2b2d6ff7 47static pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER;
8165c8da 48
17dfb34b 49void ust_lock(void)
8165c8da
MD
50{
51 pthread_mutex_lock(&sessions_mutex);
52}
53
17dfb34b 54void ust_unlock(void)
8165c8da
MD
55{
56 pthread_mutex_unlock(&sessions_mutex);
57}
58
b5234c06 59static CDS_LIST_HEAD(sessions);
8165c8da
MD
60
61/*
62 * Pending probes hash table, containing the registered ltt events for
63 * which tracepoint probes are still missing. Protected by the sessions
64 * mutex.
65 */
66#define PENDING_PROBE_HASH_BITS 6
67#define PENDING_PROBE_HASH_SIZE (1 << PENDING_PROBE_HASH_BITS)
68static struct cds_hlist_head pending_probe_table[PENDING_PROBE_HASH_SIZE];
69
70struct ust_pending_probe {
71 struct ltt_event *event;
72 struct cds_hlist_node node;
73 char name[];
74};
8020ceb5
MD
75
76static void _ltt_event_destroy(struct ltt_event *event);
574a6217 77static void _ltt_loglevel_destroy(struct session_loglevel *sl);
e6c12e3d 78static void _ltt_wildcard_destroy(struct session_wildcard *sw);
8020ceb5
MD
79static void _ltt_channel_destroy(struct ltt_channel *chan);
80static int _ltt_event_unregister(struct ltt_event *event);
81static
82int _ltt_event_metadata_statedump(struct ltt_session *session,
83 struct ltt_channel *chan,
84 struct ltt_event *event);
85static
86int _ltt_session_metadata_statedump(struct ltt_session *session);
87
8165c8da
MD
88/*
89 * called at event creation if probe is missing.
90 * called with session mutex held.
91 */
92static
93int add_pending_probe(struct ltt_event *event, const char *name)
94{
95 struct cds_hlist_head *head;
8165c8da
MD
96 struct ust_pending_probe *e;
97 size_t name_len = strlen(name) + 1;
23c8854a 98 uint32_t hash = jhash(name, name_len - 1, 0);
8165c8da
MD
99
100 head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
101 e = zmalloc(sizeof(struct ust_pending_probe) + name_len);
102 if (!e)
103 return -ENOMEM;
104 memcpy(&e->name[0], name, name_len);
105 cds_hlist_add_head(&e->node, head);
106 e->event = event;
107 event->pending_probe = e;
108 return 0;
109}
110
111/*
112 * remove a pending probe. called when at event teardown and when an
113 * event is fixed (probe is loaded).
114 * called with session mutex held.
115 */
116static
117void remove_pending_probe(struct ust_pending_probe *e)
118{
119 if (!e)
120 return;
121 cds_hlist_del(&e->node);
122 free(e);
123}
124
125/*
126 * Called at library load: connect the probe on the events pending on
127 * probe load.
128 * called with session mutex held.
129 */
130int pending_probe_fix_events(const struct lttng_event_desc *desc)
131{
132 struct cds_hlist_head *head;
133 struct cds_hlist_node *node, *p;
134 struct ust_pending_probe *e;
135 const char *name = desc->name;
136 size_t name_len = strlen(name) + 1;
23c8854a 137 uint32_t hash = jhash(name, name_len - 1, 0);
8165c8da 138 int ret = 0;
7ee3cc56 139 struct lttng_ust_event event_param;
8165c8da 140
574a6217 141 /*
1f18504e
MD
142 * For this event, we need to lookup the loglevel. If active (in
143 * the active loglevels hash table), we must create the event.
144 */
574a6217
MD
145 if (desc->loglevel) {
146 const struct tracepoint_loglevel_entry *ev_ll;
147 struct loglevel_entry *loglevel;
148
149 ev_ll = *desc->loglevel;
150 loglevel = get_loglevel(ev_ll->identifier);
48740cab
MD
151 if (!loglevel)
152 loglevel = get_loglevel_value(ev_ll->value);
574a6217
MD
153 if (loglevel) {
154 struct session_loglevel *sl;
155
156 cds_list_for_each_entry(sl, &loglevel->session_list,
157 session_list) {
158 struct ltt_event *ev;
159 int ret;
160
7ee3cc56
MD
161 memcpy(&event_param, &sl->event_param,
162 sizeof(event_param));
163 memcpy(event_param.name,
164 desc->name,
165 sizeof(event_param.name));
574a6217
MD
166 /* create event */
167 ret = ltt_event_create(sl->chan,
7ee3cc56 168 &event_param, NULL,
574a6217 169 &ev);
7ee3cc56
MD
170 if (ret) {
171 DBG("Error creating event");
574a6217 172 continue;
7ee3cc56 173 }
574a6217
MD
174 cds_list_add(&ev->loglevel_list,
175 &sl->events);
176 }
177 }
178 }
1f18504e 179
e6c12e3d
MD
180 /* Wildcard */
181 {
182 struct wildcard_entry *wildcard;
183
184 wildcard = match_wildcard(desc->name);
185 if (strcmp(desc->name, "lttng_ust:metadata") && wildcard) {
186 struct session_wildcard *sw;
187
188 cds_list_for_each_entry(sw, &wildcard->session_list,
189 session_list) {
190 struct ltt_event *ev;
191 int ret;
192
193 memcpy(&event_param, &sw->event_param,
194 sizeof(event_param));
195 memcpy(event_param.name,
196 desc->name,
197 sizeof(event_param.name));
198 /* create event */
199 ret = ltt_event_create(sw->chan,
200 &event_param, NULL,
201 &ev);
202 if (ret) {
203 DBG("Error creating event");
204 continue;
205 }
206 cds_list_add(&ev->wildcard_list,
207 &sw->events);
208 }
209 }
210 }
211
8165c8da
MD
212 head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
213 cds_hlist_for_each_entry_safe(e, node, p, head, node) {
214 struct ltt_event *event;
215 struct ltt_channel *chan;
216
217 if (strcmp(name, e->name))
218 continue;
219 event = e->event;
220 chan = event->chan;
221 assert(!event->desc);
222 event->desc = desc;
223 event->pending_probe = NULL;
224 remove_pending_probe(e);
225 ret |= __tracepoint_probe_register(name,
226 event->desc->probe_callback,
227 event);
636c5aa4
MD
228 if (ret)
229 continue;
230 event->id = chan->free_event_id++;
8165c8da
MD
231 ret |= _ltt_event_metadata_statedump(chan->session, chan,
232 event);
233 }
234 return ret;
235}
236
8020ceb5
MD
237void synchronize_trace(void)
238{
8020ceb5 239 synchronize_rcu();
8020ceb5
MD
240}
241
242struct ltt_session *ltt_session_create(void)
243{
244 struct ltt_session *session;
245
b5234c06 246 session = zmalloc(sizeof(struct ltt_session));
8020ceb5
MD
247 if (!session)
248 return NULL;
b5234c06
MD
249 CDS_INIT_LIST_HEAD(&session->chan);
250 CDS_INIT_LIST_HEAD(&session->events);
1f18504e 251 CDS_INIT_LIST_HEAD(&session->loglevels);
e6c12e3d 252 CDS_INIT_LIST_HEAD(&session->wildcards);
b5234c06
MD
253 uuid_generate(session->uuid);
254 cds_list_add(&session->list, &sessions);
8020ceb5
MD
255 return session;
256}
257
258void ltt_session_destroy(struct ltt_session *session)
259{
260 struct ltt_channel *chan, *tmpchan;
261 struct ltt_event *event, *tmpevent;
574a6217 262 struct session_loglevel *loglevel, *tmploglevel;
e6c12e3d 263 struct session_wildcard *wildcard, *tmpwildcard;
8020ceb5
MD
264 int ret;
265
b5234c06
MD
266 CMM_ACCESS_ONCE(session->active) = 0;
267 cds_list_for_each_entry(event, &session->events, list) {
8020ceb5
MD
268 ret = _ltt_event_unregister(event);
269 WARN_ON(ret);
270 }
271 synchronize_trace(); /* Wait for in-flight events to complete */
1f18504e
MD
272 cds_list_for_each_entry_safe(loglevel, tmploglevel, &session->loglevels, list)
273 _ltt_loglevel_destroy(loglevel);
e6c12e3d
MD
274 cds_list_for_each_entry_safe(wildcard, tmpwildcard, &session->wildcards, list)
275 _ltt_wildcard_destroy(wildcard);
b5234c06 276 cds_list_for_each_entry_safe(event, tmpevent, &session->events, list)
8020ceb5 277 _ltt_event_destroy(event);
b5234c06 278 cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
8020ceb5 279 _ltt_channel_destroy(chan);
b5234c06 280 cds_list_del(&session->list);
b5234c06 281 free(session);
8020ceb5
MD
282}
283
976fe9ea 284int ltt_session_enable(struct ltt_session *session)
8020ceb5
MD
285{
286 int ret = 0;
287 struct ltt_channel *chan;
288
8020ceb5
MD
289 if (session->active) {
290 ret = -EBUSY;
291 goto end;
292 }
293
294 /*
295 * Snapshot the number of events per channel to know the type of header
296 * we need to use.
297 */
b5234c06 298 cds_list_for_each_entry(chan, &session->chan, list) {
8020ceb5
MD
299 if (chan->header_type)
300 continue; /* don't change it if session stop/restart */
301 if (chan->free_event_id < 31)
302 chan->header_type = 1; /* compact */
303 else
304 chan->header_type = 2; /* large */
305 }
306
b5234c06
MD
307 CMM_ACCESS_ONCE(session->active) = 1;
308 CMM_ACCESS_ONCE(session->been_active) = 1;
8020ceb5 309 ret = _ltt_session_metadata_statedump(session);
4b4de73e 310 if (ret)
b5234c06 311 CMM_ACCESS_ONCE(session->active) = 0;
8020ceb5 312end:
8020ceb5
MD
313 return ret;
314}
315
976fe9ea 316int ltt_session_disable(struct ltt_session *session)
8020ceb5
MD
317{
318 int ret = 0;
319
8020ceb5
MD
320 if (!session->active) {
321 ret = -EBUSY;
322 goto end;
323 }
b5234c06 324 CMM_ACCESS_ONCE(session->active) = 0;
8020ceb5 325end:
8020ceb5
MD
326 return ret;
327}
328
976fe9ea
MD
329int ltt_channel_enable(struct ltt_channel *channel)
330{
331 int old;
332
9beb36ba
MD
333 if (channel == channel->session->metadata)
334 return -EPERM;
b5234c06 335 old = uatomic_xchg(&channel->enabled, 1);
976fe9ea
MD
336 if (old)
337 return -EEXIST;
338 return 0;
339}
340
341int ltt_channel_disable(struct ltt_channel *channel)
342{
343 int old;
344
9beb36ba
MD
345 if (channel == channel->session->metadata)
346 return -EPERM;
b5234c06 347 old = uatomic_xchg(&channel->enabled, 0);
976fe9ea
MD
348 if (!old)
349 return -EEXIST;
350 return 0;
351}
352
353int ltt_event_enable(struct ltt_event *event)
354{
355 int old;
356
9beb36ba
MD
357 if (event->chan == event->chan->session->metadata)
358 return -EPERM;
b5234c06 359 old = uatomic_xchg(&event->enabled, 1);
976fe9ea
MD
360 if (old)
361 return -EEXIST;
362 return 0;
363}
364
365int ltt_event_disable(struct ltt_event *event)
366{
367 int old;
368
9beb36ba
MD
369 if (event->chan == event->chan->session->metadata)
370 return -EPERM;
b5234c06 371 old = uatomic_xchg(&event->enabled, 0);
976fe9ea
MD
372 if (!old)
373 return -EEXIST;
374 return 0;
375}
376
8020ceb5
MD
377struct ltt_channel *ltt_channel_create(struct ltt_session *session,
378 const char *transport_name,
379 void *buf_addr,
380 size_t subbuf_size, size_t num_subbuf,
381 unsigned int switch_timer_interval,
193183fb
MD
382 unsigned int read_timer_interval,
383 int *shm_fd, int *wait_fd,
d028eddb
MD
384 uint64_t *memory_map_size,
385 struct ltt_channel *chan_priv_init)
8020ceb5 386{
a3f61e7f 387 struct ltt_channel *chan = NULL;
8020ceb5
MD
388 struct ltt_transport *transport;
389
8020ceb5
MD
390 if (session->been_active)
391 goto active; /* Refuse to add channel to active session */
392 transport = ltt_transport_find(transport_name);
393 if (!transport) {
b5234c06 394 DBG("LTTng transport %s not found\n",
8020ceb5
MD
395 transport_name);
396 goto notransport;
397 }
d028eddb
MD
398 chan_priv_init->id = session->free_chan_id++;
399 chan_priv_init->session = session;
8020ceb5
MD
400 /*
401 * Note: the channel creation op already writes into the packet
402 * headers. Therefore the "chan" information used as input
403 * should be already accessible.
404 */
a3f61e7f 405 chan = transport->ops.channel_create("[lttng]", buf_addr,
8020ceb5 406 subbuf_size, num_subbuf, switch_timer_interval,
193183fb 407 read_timer_interval, shm_fd, wait_fd,
d028eddb 408 memory_map_size, chan_priv_init);
a3f61e7f 409 if (!chan)
8020ceb5 410 goto create_error;
976fe9ea 411 chan->enabled = 1;
8020ceb5 412 chan->ops = &transport->ops;
b5234c06 413 cds_list_add(&chan->list, &session->chan);
8020ceb5
MD
414 return chan;
415
416create_error:
8020ceb5
MD
417notransport:
418active:
8020ceb5
MD
419 return NULL;
420}
421
422/*
423 * Only used internally at session destruction.
424 */
425static
426void _ltt_channel_destroy(struct ltt_channel *chan)
427{
b5234c06 428 cds_list_del(&chan->list);
8020ceb5 429 lttng_destroy_context(chan->ctx);
a3f61e7f 430 chan->ops->channel_destroy(chan);
8020ceb5
MD
431}
432
1f18504e
MD
433int ltt_loglevel_create(struct ltt_channel *chan,
434 struct lttng_ust_event *event_param,
574a6217 435 struct session_loglevel **_sl)
1f18504e 436{
574a6217 437 struct session_loglevel *sl;
1f18504e 438
574a6217
MD
439 sl = add_loglevel(event_param->name, chan, event_param);
440 if (!sl || IS_ERR(sl)) {
441 return PTR_ERR(sl);
1f18504e 442 }
574a6217 443 *_sl = sl;
1f18504e
MD
444 return 0;
445}
446
447static
574a6217 448void _ltt_loglevel_destroy(struct session_loglevel *sl)
1f18504e 449{
574a6217 450 _remove_loglevel(sl);
1f18504e
MD
451}
452
e6c12e3d
MD
453int ltt_wildcard_create(struct ltt_channel *chan,
454 struct lttng_ust_event *event_param,
455 struct session_wildcard **_sw)
456{
457 struct session_wildcard *sw;
458
459 sw = add_wildcard(event_param->name, chan, event_param);
460 if (!sw || IS_ERR(sw)) {
461 return PTR_ERR(sw);
462 }
463 *_sw = sw;
464 return 0;
465}
466
467static
468void _ltt_wildcard_destroy(struct session_wildcard *sw)
469{
470 _remove_wildcard(sw);
471}
472
8020ceb5
MD
473/*
474 * Supports event creation while tracing session is active.
475 */
576599a0
MD
476int ltt_event_create(struct ltt_channel *chan,
477 struct lttng_ust_event *event_param,
478 void *filter,
479 struct ltt_event **_event)
8020ceb5
MD
480{
481 struct ltt_event *event;
576599a0 482 int ret = 0;
8020ceb5 483
576599a0
MD
484 if (chan->used_event_id == -1UL) {
485 ret = -ENOMEM;
8020ceb5 486 goto full;
576599a0 487 }
8020ceb5
MD
488 /*
489 * This is O(n^2) (for each event, the loop is called at event
490 * creation). Might require a hash if we have lots of events.
491 */
576599a0
MD
492 cds_list_for_each_entry(event, &chan->session->events, list) {
493 if (event->desc && !strcmp(event->desc->name, event_param->name)) {
494 ret = -EEXIST;
8020ceb5 495 goto exist;
576599a0
MD
496 }
497 }
b5234c06 498 event = zmalloc(sizeof(struct ltt_event));
576599a0
MD
499 if (!event) {
500 ret = -ENOMEM;
8020ceb5 501 goto cache_error;
576599a0 502 }
8020ceb5
MD
503 event->chan = chan;
504 event->filter = filter;
8165c8da
MD
505 /*
506 * used_event_id counts the maximum number of event IDs that can
507 * register if all probes register.
508 */
509 chan->used_event_id++;
976fe9ea 510 event->enabled = 1;
8020ceb5
MD
511 event->instrumentation = event_param->instrumentation;
512 /* Populate ltt_event structure before tracepoint registration. */
b5234c06 513 cmm_smp_wmb();
8020ceb5 514 switch (event_param->instrumentation) {
b5234c06 515 case LTTNG_UST_TRACEPOINT:
8020ceb5 516 event->desc = ltt_event_get(event_param->name);
8165c8da
MD
517 if (event->desc) {
518 ret = __tracepoint_probe_register(event_param->name,
519 event->desc->probe_callback,
520 event);
521 if (ret)
522 goto register_error;
523 event->id = chan->free_event_id++;
524 } else {
525 /*
526 * If the probe is not present, event->desc stays NULL,
527 * waiting for the probe to register, and the event->id
528 * stays unallocated.
529 */
530 ret = add_pending_probe(event, event_param->name);
531 if (ret)
532 goto add_pending_error;
533 }
8020ceb5 534 break;
df854e41 535 case LTTNG_UST_TRACEPOINT_LOGLEVEL:
1f18504e 536 assert(0);
df854e41 537 break;
8020ceb5
MD
538 default:
539 WARN_ON_ONCE(1);
540 }
8165c8da
MD
541 if (event->desc) {
542 ret = _ltt_event_metadata_statedump(chan->session, chan, event);
543 if (ret)
544 goto statedump_error;
545 }
b5234c06 546 cds_list_add(&event->list, &chan->session->events);
576599a0
MD
547 *_event = event;
548 return 0;
8020ceb5
MD
549
550statedump_error:
8165c8da
MD
551 if (event->desc) {
552 WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name,
553 event->desc->probe_callback,
554 event));
555 ltt_event_put(event->desc);
556 }
557add_pending_error:
8020ceb5 558register_error:
b5234c06 559 free(event);
8020ceb5
MD
560cache_error:
561exist:
562full:
576599a0 563 return ret;
8020ceb5
MD
564}
565
566/*
567 * Only used internally at session destruction.
568 */
569int _ltt_event_unregister(struct ltt_event *event)
570{
571 int ret = -EINVAL;
572
573 switch (event->instrumentation) {
b5234c06 574 case LTTNG_UST_TRACEPOINT:
8165c8da
MD
575 if (event->desc) {
576 ret = __tracepoint_probe_unregister(event->desc->name,
577 event->desc->probe_callback,
578 event);
579 if (ret)
580 return ret;
581 } else {
582 remove_pending_probe(event->pending_probe);
583 ret = 0;
584 }
8020ceb5 585 break;
8020ceb5
MD
586 default:
587 WARN_ON_ONCE(1);
588 }
589 return ret;
590}
591
592/*
593 * Only used internally at session destruction.
594 */
595static
596void _ltt_event_destroy(struct ltt_event *event)
597{
598 switch (event->instrumentation) {
b5234c06 599 case LTTNG_UST_TRACEPOINT:
8165c8da
MD
600 if (event->desc) {
601 ltt_event_put(event->desc);
602 }
8020ceb5 603 break;
8020ceb5
MD
604 default:
605 WARN_ON_ONCE(1);
606 }
b5234c06 607 cds_list_del(&event->list);
8020ceb5 608 lttng_destroy_context(event->ctx);
b5234c06 609 free(event);
8020ceb5
MD
610}
611
612/*
613 * We have exclusive access to our metadata buffer (protected by the
17dfb34b 614 * ust_lock), so we can do racy operations such as looking for
8020ceb5
MD
615 * remaining space left in packet and write, since mutual exclusion
616 * protects us from concurrent writes.
617 */
618int lttng_metadata_printf(struct ltt_session *session,
619 const char *fmt, ...)
620{
4cfec15c 621 struct lttng_ust_lib_ring_buffer_ctx ctx;
8020ceb5 622 struct ltt_channel *chan = session->metadata;
b5234c06 623 char *str = NULL;
8020ceb5
MD
624 int ret = 0, waitret;
625 size_t len, reserve_len, pos;
626 va_list ap;
627
b5234c06 628 WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active));
8020ceb5
MD
629
630 va_start(ap, fmt);
b5234c06 631 ret = vasprintf(&str, fmt, ap);
8020ceb5 632 va_end(ap);
b5234c06 633 if (ret < 0)
8020ceb5
MD
634 return -ENOMEM;
635
636 len = strlen(str);
637 pos = 0;
638
639 for (pos = 0; pos < len; pos += reserve_len) {
640 reserve_len = min_t(size_t,
1d498196 641 chan->ops->packet_avail_size(chan->chan, chan->handle),
8020ceb5
MD
642 len - pos);
643 lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
1d498196 644 sizeof(char), -1, chan->handle);
8020ceb5
MD
645 /*
646 * We don't care about metadata buffer's records lost
647 * count, because we always retry here. Report error if
648 * we need to bail out after timeout or being
649 * interrupted.
650 */
b5234c06 651 waitret = wait_cond_interruptible_timeout(
8020ceb5
MD
652 ({
653 ret = chan->ops->event_reserve(&ctx, 0);
654 ret != -ENOBUFS || !ret;
655 }),
b5234c06 656 LTTNG_METADATA_TIMEOUT_MSEC);
b472cfc0 657 if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) {
b5234c06
MD
658 DBG("LTTng: Failure to write metadata to buffers (%s)\n",
659 waitret == -EINTR ? "interrupted" :
8020ceb5 660 (ret == -ENOBUFS ? "timeout" : "I/O error"));
b5234c06 661 if (waitret == -EINTR)
8020ceb5
MD
662 ret = waitret;
663 goto end;
664 }
665 chan->ops->event_write(&ctx, &str[pos], reserve_len);
666 chan->ops->event_commit(&ctx);
667 }
668end:
b5234c06 669 free(str);
8020ceb5
MD
670 return ret;
671}
672
673static
674int _ltt_field_statedump(struct ltt_session *session,
675 const struct lttng_event_field *field)
676{
677 int ret = 0;
678
679 switch (field->type.atype) {
680 case atype_integer:
681 ret = lttng_metadata_printf(session,
4e2ee1f5 682 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
8020ceb5
MD
683 field->type.u.basic.integer.size,
684 field->type.u.basic.integer.alignment,
685 field->type.u.basic.integer.signedness,
686 (field->type.u.basic.integer.encoding == lttng_encode_none)
687 ? "none"
688 : (field->type.u.basic.integer.encoding == lttng_encode_UTF8)
689 ? "UTF8"
690 : "ASCII",
691 field->type.u.basic.integer.base,
8a98a75d 692#if (BYTE_ORDER == BIG_ENDIAN)
403c40b4
MD
693 field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
694#else
695 field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
696#endif
697 field->name);
698 break;
699 case atype_float:
700 ret = lttng_metadata_printf(session,
8a98a75d 701 " floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
403c40b4
MD
702 field->type.u.basic._float.exp_dig,
703 field->type.u.basic._float.mant_dig,
704 field->type.u.basic._float.alignment,
8a98a75d 705#if (BYTE_ORDER == BIG_ENDIAN)
8020ceb5
MD
706 field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
707#else
708 field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
709#endif
710 field->name);
711 break;
712 case atype_enum:
713 ret = lttng_metadata_printf(session,
714 " %s %s;\n",
715 field->type.u.basic.enumeration.name,
716 field->name);
717 break;
718 case atype_array:
719 {
720 const struct lttng_basic_type *elem_type;
721
722 elem_type = &field->type.u.array.elem_type;
723 ret = lttng_metadata_printf(session,
4e2ee1f5 724 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
8020ceb5
MD
725 elem_type->u.basic.integer.size,
726 elem_type->u.basic.integer.alignment,
727 elem_type->u.basic.integer.signedness,
728 (elem_type->u.basic.integer.encoding == lttng_encode_none)
729 ? "none"
730 : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
731 ? "UTF8"
732 : "ASCII",
733 elem_type->u.basic.integer.base,
8a98a75d 734#if (BYTE_ORDER == BIG_ENDIAN)
8020ceb5
MD
735 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
736#else
737 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
738#endif
739 field->name, field->type.u.array.length);
740 break;
741 }
742 case atype_sequence:
743 {
744 const struct lttng_basic_type *elem_type;
745 const struct lttng_basic_type *length_type;
746
747 elem_type = &field->type.u.sequence.elem_type;
748 length_type = &field->type.u.sequence.length_type;
749 ret = lttng_metadata_printf(session,
750 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
751 length_type->u.basic.integer.size,
752 (unsigned int) length_type->u.basic.integer.alignment,
753 length_type->u.basic.integer.signedness,
754 (length_type->u.basic.integer.encoding == lttng_encode_none)
755 ? "none"
756 : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8)
757 ? "UTF8"
758 : "ASCII"),
759 length_type->u.basic.integer.base,
8a98a75d 760#if (BYTE_ORDER == BIG_ENDIAN)
8020ceb5
MD
761 length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
762#else
763 length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
764#endif
765 field->name);
766 if (ret)
767 return ret;
768
769 ret = lttng_metadata_printf(session,
4e2ee1f5 770 " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
8020ceb5
MD
771 elem_type->u.basic.integer.size,
772 (unsigned int) elem_type->u.basic.integer.alignment,
773 elem_type->u.basic.integer.signedness,
774 (elem_type->u.basic.integer.encoding == lttng_encode_none)
775 ? "none"
776 : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
777 ? "UTF8"
778 : "ASCII"),
779 elem_type->u.basic.integer.base,
8a98a75d 780#if (BYTE_ORDER == BIG_ENDIAN)
8020ceb5
MD
781 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
782#else
783 elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
784#endif
785 field->name,
786 field->name);
787 break;
788 }
789
790 case atype_string:
791 /* Default encoding is UTF8 */
792 ret = lttng_metadata_printf(session,
4e2ee1f5 793 " string%s _%s;\n",
8020ceb5
MD
794 field->type.u.basic.string.encoding == lttng_encode_ASCII ?
795 " { encoding = ASCII; }" : "",
796 field->name);
797 break;
798 default:
799 WARN_ON_ONCE(1);
800 return -EINVAL;
801 }
802 return ret;
803}
804
805static
806int _ltt_context_metadata_statedump(struct ltt_session *session,
807 struct lttng_ctx *ctx)
808{
809 int ret = 0;
810 int i;
811
812 if (!ctx)
813 return 0;
814 for (i = 0; i < ctx->nr_fields; i++) {
815 const struct lttng_ctx_field *field = &ctx->fields[i];
816
817 ret = _ltt_field_statedump(session, &field->event_field);
818 if (ret)
819 return ret;
820 }
821 return ret;
822}
823
824static
825int _ltt_fields_metadata_statedump(struct ltt_session *session,
826 struct ltt_event *event)
827{
828 const struct lttng_event_desc *desc = event->desc;
829 int ret = 0;
830 int i;
831
832 for (i = 0; i < desc->nr_fields; i++) {
833 const struct lttng_event_field *field = &desc->fields[i];
834
835 ret = _ltt_field_statedump(session, field);
836 if (ret)
837 return ret;
838 }
839 return ret;
840}
841
842static
843int _ltt_event_metadata_statedump(struct ltt_session *session,
844 struct ltt_channel *chan,
845 struct ltt_event *event)
846{
847 int ret = 0;
848
b5234c06 849 if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
8020ceb5
MD
850 return 0;
851 if (chan == session->metadata)
852 return 0;
8165c8da
MD
853 /*
854 * Don't print events for which probe load is pending.
855 */
856 if (!event->desc)
857 return 0;
8020ceb5
MD
858
859 ret = lttng_metadata_printf(session,
860 "event {\n"
7083f0fe 861 " name = \"%s\";\n"
8020ceb5
MD
862 " id = %u;\n"
863 " stream_id = %u;\n",
864 event->desc->name,
865 event->id,
866 event->chan->id);
867 if (ret)
868 goto end;
869
e6c12e3d
MD
870 if (event->desc->loglevel) {
871 const struct tracepoint_loglevel_entry *ll_entry;
872
873 ll_entry = *event->desc->loglevel;
874 ret = lttng_metadata_printf(session,
875 " loglevel.identifier = \"%s\";\n"
876 " loglevel.value = %lld;\n",
877 ll_entry->identifier,
878 (long long) ll_entry->value);
879 if (ret)
880 goto end;
881 }
882
8020ceb5
MD
883 if (event->ctx) {
884 ret = lttng_metadata_printf(session,
885 " context := struct {\n");
886 if (ret)
887 goto end;
888 }
889 ret = _ltt_context_metadata_statedump(session, event->ctx);
890 if (ret)
891 goto end;
892 if (event->ctx) {
893 ret = lttng_metadata_printf(session,
894 " };\n");
895 if (ret)
896 goto end;
897 }
898
899 ret = lttng_metadata_printf(session,
900 " fields := struct {\n"
901 );
902 if (ret)
903 goto end;
904
905 ret = _ltt_fields_metadata_statedump(session, event);
906 if (ret)
907 goto end;
908
909 /*
910 * LTTng space reservation can only reserve multiples of the
911 * byte size.
912 */
913 ret = lttng_metadata_printf(session,
914 " };\n"
915 "};\n\n");
916 if (ret)
917 goto end;
918
919 event->metadata_dumped = 1;
920end:
921 return ret;
922
923}
924
925static
926int _ltt_channel_metadata_statedump(struct ltt_session *session,
927 struct ltt_channel *chan)
928{
929 int ret = 0;
930
b5234c06 931 if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
8020ceb5
MD
932 return 0;
933 if (chan == session->metadata)
934 return 0;
935
936 WARN_ON_ONCE(!chan->header_type);
937 ret = lttng_metadata_printf(session,
938 "stream {\n"
939 " id = %u;\n"
940 " event.header := %s;\n"
941 " packet.context := struct packet_context;\n",
942 chan->id,
943 chan->header_type == 1 ? "struct event_header_compact" :
944 "struct event_header_large");
945 if (ret)
946 goto end;
947
948 if (chan->ctx) {
949 ret = lttng_metadata_printf(session,
950 " event.context := struct {\n");
951 if (ret)
952 goto end;
953 }
954 ret = _ltt_context_metadata_statedump(session, chan->ctx);
955 if (ret)
956 goto end;
957 if (chan->ctx) {
958 ret = lttng_metadata_printf(session,
959 " };\n");
960 if (ret)
961 goto end;
962 }
963
964 ret = lttng_metadata_printf(session,
965 "};\n\n");
966
967 chan->metadata_dumped = 1;
968end:
969 return ret;
970}
971
972static
973int _ltt_stream_packet_context_declare(struct ltt_session *session)
974{
975 return lttng_metadata_printf(session,
976 "struct packet_context {\n"
977 " uint64_t timestamp_begin;\n"
978 " uint64_t timestamp_end;\n"
979 " uint32_t events_discarded;\n"
980 " uint32_t content_size;\n"
981 " uint32_t packet_size;\n"
982 " uint32_t cpu_id;\n"
983 "};\n\n"
984 );
985}
986
987/*
988 * Compact header:
989 * id: range: 0 - 30.
990 * id 31 is reserved to indicate an extended header.
991 *
992 * Large header:
993 * id: range: 0 - 65534.
994 * id 65535 is reserved to indicate an extended header.
995 */
996static
997int _ltt_event_header_declare(struct ltt_session *session)
998{
999 return lttng_metadata_printf(session,
1000 "struct event_header_compact {\n"
1001 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
1002 " variant <id> {\n"
1003 " struct {\n"
1004 " uint27_t timestamp;\n"
1005 " } compact;\n"
1006 " struct {\n"
1007 " uint32_t id;\n"
1008 " uint64_t timestamp;\n"
1009 " } extended;\n"
1010 " } v;\n"
1011 "} align(%u);\n"
1012 "\n"
1013 "struct event_header_large {\n"
1014 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
1015 " variant <id> {\n"
1016 " struct {\n"
1017 " uint32_t timestamp;\n"
1018 " } compact;\n"
1019 " struct {\n"
1020 " uint32_t id;\n"
1021 " uint64_t timestamp;\n"
1022 " } extended;\n"
1023 " } v;\n"
1024 "} align(%u);\n\n",
1dbfff0c
MD
1025 lttng_alignof(uint32_t) * CHAR_BIT,
1026 lttng_alignof(uint16_t) * CHAR_BIT
8020ceb5
MD
1027 );
1028}
1029
1030/*
1031 * Output metadata into this session's metadata buffers.
1032 */
1033static
1034int _ltt_session_metadata_statedump(struct ltt_session *session)
1035{
b5234c06
MD
1036 unsigned char *uuid_c = session->uuid;
1037 char uuid_s[37];
8020ceb5
MD
1038 struct ltt_channel *chan;
1039 struct ltt_event *event;
1040 int ret = 0;
1041
b5234c06 1042 if (!CMM_ACCESS_ONCE(session->active))
8020ceb5
MD
1043 return 0;
1044 if (session->metadata_dumped)
1045 goto skip_session;
1046 if (!session->metadata) {
b5234c06 1047 DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n");
8020ceb5
MD
1048 return -EPERM;
1049 }
1050
1051 snprintf(uuid_s, sizeof(uuid_s),
1052 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1053 uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3],
1054 uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7],
1055 uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11],
1056 uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]);
1057
1058 ret = lttng_metadata_printf(session,
1059 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
1060 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
1061 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
1062 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
1063 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
1064 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
1065 "\n"
1066 "trace {\n"
1067 " major = %u;\n"
1068 " minor = %u;\n"
1069 " uuid = \"%s\";\n"
1070 " byte_order = %s;\n"
1071 " packet.header := struct {\n"
1072 " uint32_t magic;\n"
1073 " uint8_t uuid[16];\n"
1074 " uint32_t stream_id;\n"
1075 " };\n"
1076 "};\n\n",
1dbfff0c
MD
1077 lttng_alignof(uint8_t) * CHAR_BIT,
1078 lttng_alignof(uint16_t) * CHAR_BIT,
1079 lttng_alignof(uint32_t) * CHAR_BIT,
1080 lttng_alignof(uint64_t) * CHAR_BIT,
8020ceb5
MD
1081 CTF_VERSION_MAJOR,
1082 CTF_VERSION_MINOR,
1083 uuid_s,
8a98a75d 1084#if (BYTE_ORDER == BIG_ENDIAN)
8020ceb5
MD
1085 "be"
1086#else
1087 "le"
1088#endif
1089 );
1090 if (ret)
1091 goto end;
1092
1093 ret = _ltt_stream_packet_context_declare(session);
1094 if (ret)
1095 goto end;
1096
1097 ret = _ltt_event_header_declare(session);
1098 if (ret)
1099 goto end;
1100
1101skip_session:
b5234c06 1102 cds_list_for_each_entry(chan, &session->chan, list) {
8020ceb5
MD
1103 ret = _ltt_channel_metadata_statedump(session, chan);
1104 if (ret)
1105 goto end;
1106 }
1107
b5234c06 1108 cds_list_for_each_entry(event, &session->events, list) {
8020ceb5
MD
1109 ret = _ltt_event_metadata_statedump(session, event->chan, event);
1110 if (ret)
1111 goto end;
1112 }
1113 session->metadata_dumped = 1;
1114end:
1115 return ret;
1116}
1117
003fedf4 1118void lttng_ust_events_exit(void)
8020ceb5
MD
1119{
1120 struct ltt_session *session, *tmpsession;
1121
b5234c06 1122 cds_list_for_each_entry_safe(session, tmpsession, &sessions, list)
8020ceb5 1123 ltt_session_destroy(session);
8020ceb5 1124}
This page took 0.10736 seconds and 4 git commands to generate.