6eb74ed8170d2b5ae1bdcd2c63a7fc57dc0af14e
[ust.git] / libust / lttng-ust-abi.c
1 /*
2 * lttng-ust-abi.c
3 *
4 * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng UST ABI
7 *
8 * Mimic system calls for:
9 * - session creation, returns an object descriptor or failure.
10 * - channel creation, returns an object descriptor or failure.
11 * - Operates on a session object descriptor
12 * - Takes all channel options as parameters.
13 * - stream get, returns an object descriptor or failure.
14 * - Operates on a channel object descriptor.
15 * - stream notifier get, returns an object descriptor or failure.
16 * - Operates on a channel object descriptor.
17 * - event creation, returns an object descriptor or failure.
18 * - Operates on a channel object descriptor
19 * - Takes an event name as parameter
20 * - Takes an instrumentation source as parameter
21 * - e.g. tracepoints, dynamic_probes...
22 * - Takes instrumentation source specific arguments.
23 *
24 * Dual LGPL v2.1/GPL v2 license.
25 */
26
27 #include <ust/lttng-ust-abi.h>
28 #include <urcu/compiler.h>
29 #include <urcu/list.h>
30 #include <ust/lttng-events.h>
31 #include <ust/usterr-signal-safe.h>
32 #include "ust/core.h"
33 #include "ltt-tracer.h"
34
35 /*
36 * Object descriptor table. Should be protected from concurrent access
37 * by the caller.
38 */
39
40 struct obj {
41 union {
42 struct {
43 void *private_data;
44 const struct objd_ops *ops;
45 int f_count;
46 } s;
47 int freelist_next; /* offset freelist. end is -1. */
48 } u;
49 };
50
51 struct objd_table {
52 struct obj *array;
53 unsigned int len, allocated_len;
54 int freelist_head; /* offset freelist head. end is -1 */
55 };
56
57 static struct objd_table objd_table = {
58 .freelist_head = -1,
59 };
60
61 static
62 int objd_alloc(void *private_data, const struct objd_ops *ops)
63 {
64 struct obj *obj;
65
66 if (objd_table.freelist_head != -1) {
67 obj = &objd_table.array[objd_table.freelist_head];
68 objd_table.freelist_head = obj->u.freelist_next;
69 goto end;
70 }
71
72 if (objd_table.len >= objd_table.allocated_len) {
73 unsigned int new_allocated_len, old_allocated_len;
74 struct obj *new_table, *old_table;
75
76 old_allocated_len = objd_table.allocated_len;
77 old_table = objd_table.array;
78 if (!old_allocated_len)
79 new_allocated_len = 1;
80 else
81 new_allocated_len = old_allocated_len << 1;
82 new_table = zmalloc(sizeof(struct obj) * new_allocated_len);
83 if (!new_table)
84 return -ENOMEM;
85 memcpy(new_table, old_table,
86 sizeof(struct obj) * old_allocated_len);
87 free(old_table);
88 objd_table.array = new_table;
89 objd_table.allocated_len = new_allocated_len;
90 }
91 obj = &objd_table.array[objd_table.len];
92 objd_table.len++;
93 end:
94 obj->u.s.private_data = private_data;
95 obj->u.s.ops = ops;
96 obj->u.s.f_count = 2; /* count == 1 : object is allocated */
97 /* count == 2 : allocated + hold ref */
98 return obj - objd_table.array;
99 }
100
101 static
102 struct obj *_objd_get(int id)
103 {
104 if (id >= objd_table.len)
105 return NULL;
106 if (!objd_table.array[id].u.s.f_count)
107 return NULL;
108 return &objd_table.array[id];
109 }
110
111 static
112 void *objd_private(int id)
113 {
114 struct obj *obj = _objd_get(id);
115 assert(obj);
116 return obj->u.s.private_data;
117 }
118
119 static
120 void objd_set_private(int id, void *private_data)
121 {
122 struct obj *obj = _objd_get(id);
123 assert(obj);
124 obj->u.s.private_data = private_data;
125 }
126
127 const struct objd_ops *objd_ops(int id)
128 {
129 struct obj *obj = _objd_get(id);
130
131 if (!obj)
132 return NULL;
133 return obj->u.s.ops;
134 }
135
136 static
137 void objd_free(int id)
138 {
139 struct obj *obj = _objd_get(id);
140
141 assert(obj);
142 obj->u.freelist_next = objd_table.freelist_head;
143 objd_table.freelist_head = obj - objd_table.array;
144 assert(obj->u.s.f_count == 1);
145 obj->u.s.f_count = 0; /* deallocated */
146 }
147
148 static
149 void objd_ref(int id)
150 {
151 struct obj *obj = _objd_get(id);
152 obj->u.s.f_count++;
153 }
154
155 int objd_unref(int id)
156 {
157 struct obj *obj = _objd_get(id);
158
159 if (!obj)
160 return -EINVAL;
161 if (obj->u.s.f_count == 1) {
162 ERR("Reference counting error\n");
163 return -EINVAL;
164 }
165 if ((--obj->u.s.f_count) == 1) {
166 const struct objd_ops *ops = objd_ops(id);
167
168 if (ops->release)
169 ops->release(id);
170 objd_free(id);
171 }
172 return 0;
173 }
174
175 static
176 void objd_table_destroy(void)
177 {
178 int i;
179
180 for (i = 0; i < objd_table.allocated_len; i++)
181 (void) objd_unref(i);
182 free(objd_table.array);
183 objd_table.array = NULL;
184 objd_table.len = 0;
185 objd_table.allocated_len = 0;
186 objd_table.freelist_head = -1;
187 }
188
189 /*
190 * This is LTTng's own personal way to create an ABI for sessiond.
191 * We send commands over a socket.
192 */
193
194 static const struct objd_ops lttng_ops;
195 static const struct objd_ops lttng_session_ops;
196 static const struct objd_ops lttng_channel_ops;
197 static const struct objd_ops lttng_metadata_ops;
198 static const struct objd_ops lttng_event_ops;
199 static const struct objd_ops lib_ring_buffer_objd_ops;
200
201 enum channel_type {
202 PER_CPU_CHANNEL,
203 METADATA_CHANNEL,
204 };
205
206 int lttng_abi_create_root_handle(void)
207 {
208 int root_handle;
209
210 root_handle = objd_alloc(NULL, &lttng_ops);
211 assert(root_handle == 0);
212 return root_handle;
213 }
214
215 static
216 int lttng_abi_create_session(void)
217 {
218 struct ltt_session *session;
219 int session_objd, ret;
220
221 session = ltt_session_create();
222 if (!session)
223 return -ENOMEM;
224 session_objd = objd_alloc(session, &lttng_session_ops);
225 if (session_objd < 0) {
226 ret = session_objd;
227 goto objd_error;
228 }
229 session->objd = session_objd;
230 return session_objd;
231
232 objd_error:
233 ltt_session_destroy(session);
234 return ret;
235 }
236
237 #if 0
238 static
239 int lttng_abi_tracepoint_list(void)
240 {
241 int list_objd, ret;
242
243 /* TODO: Create list private data */
244 list_objd = objd_alloc(NULL, &lttng_tracepoint_list_ops);
245 if (list_objd < 0) {
246 ret = list_objd;
247 goto objd_error;
248 }
249
250 return list_objd;
251
252 objd_error:
253 return ret;
254 }
255 #endif //0
256
257 static
258 long lttng_abi_tracer_version(int objd,
259 struct lttng_ust_tracer_version *v)
260 {
261 v->version = LTTNG_UST_VERSION;
262 v->patchlevel = LTTNG_UST_PATCHLEVEL;
263 v->sublevel = LTTNG_UST_SUBLEVEL;
264 return 0;
265 }
266
267 static
268 long lttng_abi_add_context(int objd,
269 struct lttng_ust_context *context_param,
270 struct lttng_ctx **ctx, struct ltt_session *session)
271 {
272 if (session->been_active)
273 return -EPERM;
274
275 switch (context_param->ctx) {
276 case LTTNG_UST_CONTEXT_VTID:
277 //TODO return lttng_add_vtid_to_ctx(ctx);
278 default:
279 return -EINVAL;
280 }
281 }
282
283 /**
284 * lttng_cmd - lttng control through socket commands
285 *
286 * @objd: the object descriptor
287 * @cmd: the command
288 * @arg: command arg
289 *
290 * This descriptor implements lttng commands:
291 * LTTNG_UST_SESSION
292 * Returns a LTTng trace session object descriptor
293 * LTTNG_UST_TRACER_VERSION
294 * Returns the LTTng kernel tracer version
295 * LTTNG_UST_TRACEPOINT_LIST
296 * Returns a file descriptor listing available tracepoints
297 * LTTNG_UST_WAIT_QUIESCENT
298 * Returns after all previously running probes have completed
299 *
300 * The returned session will be deleted when its file descriptor is closed.
301 */
302 static
303 long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
304 {
305 switch (cmd) {
306 case LTTNG_UST_SESSION:
307 return lttng_abi_create_session();
308 case LTTNG_UST_TRACER_VERSION:
309 return lttng_abi_tracer_version(objd,
310 (struct lttng_ust_tracer_version *) arg);
311 case LTTNG_UST_TRACEPOINT_LIST:
312 return -ENOSYS; //TODO
313 //return lttng_abi_tracepoint_list();
314 case LTTNG_UST_WAIT_QUIESCENT:
315 synchronize_trace();
316 return 0;
317 default:
318 return -EINVAL;
319 }
320 }
321
322 static const struct objd_ops lttng_ops = {
323 .cmd = lttng_cmd,
324 };
325
326 /*
327 * We tolerate no failure in this function (if one happens, we print a dmesg
328 * error, but cannot return any error, because the channel information is
329 * invariant.
330 */
331 static
332 void lttng_metadata_create_events(int channel_objd)
333 {
334 struct ltt_channel *channel = objd_private(channel_objd);
335 static struct lttng_ust_event metadata_params = {
336 .instrumentation = LTTNG_UST_TRACEPOINT,
337 .name = "lttng_metadata",
338 };
339 struct ltt_event *event;
340 int ret;
341
342 /*
343 * We tolerate no failure path after event creation. It will stay
344 * invariant for the rest of the session.
345 */
346 event = ltt_event_create(channel, &metadata_params, NULL);
347 if (!event) {
348 ret = -EINVAL;
349 goto create_error;
350 }
351 return;
352
353 create_error:
354 WARN_ON(1);
355 return; /* not allowed to return error */
356 }
357
358 int lttng_abi_create_channel(int session_objd,
359 struct lttng_ust_channel *chan_param,
360 enum channel_type channel_type)
361 {
362 struct ltt_session *session = objd_private(session_objd);
363 const struct objd_ops *ops;
364 const char *transport_name;
365 struct ltt_channel *chan;
366 int chan_objd;
367 int ret = 0;
368
369 chan_objd = objd_alloc(NULL, &lttng_channel_ops);
370 if (chan_objd < 0) {
371 ret = chan_objd;
372 goto objd_error;
373 }
374 switch (channel_type) {
375 case PER_CPU_CHANNEL:
376 if (chan_param->output == LTTNG_UST_MMAP) {
377 transport_name = chan_param->overwrite ?
378 "relay-overwrite-mmap" : "relay-discard-mmap";
379 } else {
380 return -EINVAL;
381 }
382 ops = &lttng_channel_ops;
383 break;
384 case METADATA_CHANNEL:
385 if (chan_param->output == LTTNG_UST_MMAP)
386 transport_name = "relay-metadata-mmap";
387 else
388 return -EINVAL;
389 ops = &lttng_metadata_ops;
390 break;
391 default:
392 transport_name = "<unknown>";
393 break;
394 }
395 /*
396 * We tolerate no failure path after channel creation. It will stay
397 * invariant for the rest of the session.
398 */
399 chan = ltt_channel_create(session, transport_name, NULL,
400 chan_param->subbuf_size,
401 chan_param->num_subbuf,
402 chan_param->switch_timer_interval,
403 chan_param->read_timer_interval,
404 &chan_param->shm_fd,
405 &chan_param->wait_fd,
406 &chan_param->memory_map_size);
407 if (!chan) {
408 ret = -EINVAL;
409 goto chan_error;
410 }
411 objd_set_private(chan_objd, chan);
412 chan->objd = chan_objd;
413 if (channel_type == METADATA_CHANNEL) {
414 session->metadata = chan;
415 lttng_metadata_create_events(chan_objd);
416 }
417
418 /* The channel created holds a reference on the session */
419 objd_ref(session_objd);
420
421 return chan_objd;
422
423 chan_error:
424 {
425 int err;
426
427 err = objd_unref(chan_objd);
428 assert(!err);
429 }
430 objd_error:
431 return ret;
432 }
433
434 /**
435 * lttng_session_cmd - lttng session object command
436 *
437 * @obj: the object
438 * @cmd: the command
439 * @arg: command arg
440 *
441 * This descriptor implements lttng commands:
442 * LTTNG_UST_CHANNEL
443 * Returns a LTTng channel object descriptor
444 * LTTNG_UST_ENABLE
445 * Enables tracing for a session (weak enable)
446 * LTTNG_UST_DISABLE
447 * Disables tracing for a session (strong disable)
448 * LTTNG_UST_METADATA
449 * Returns a LTTng metadata object descriptor
450 *
451 * The returned channel will be deleted when its file descriptor is closed.
452 */
453 static
454 long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
455 {
456 struct ltt_session *session = objd_private(objd);
457
458 switch (cmd) {
459 case LTTNG_UST_CHANNEL:
460 return lttng_abi_create_channel(objd,
461 (struct lttng_ust_channel *) arg,
462 PER_CPU_CHANNEL);
463 case LTTNG_UST_SESSION_START:
464 case LTTNG_UST_ENABLE:
465 return ltt_session_enable(session);
466 case LTTNG_UST_SESSION_STOP:
467 case LTTNG_UST_DISABLE:
468 return ltt_session_disable(session);
469 case LTTNG_UST_METADATA:
470 return lttng_abi_create_channel(objd,
471 (struct lttng_ust_channel *) arg,
472 METADATA_CHANNEL);
473 default:
474 return -EINVAL;
475 }
476 }
477
478 /*
479 * Called when the last file reference is dropped.
480 *
481 * Big fat note: channels and events are invariant for the whole session after
482 * their creation. So this session destruction also destroys all channel and
483 * event structures specific to this session (they are not destroyed when their
484 * individual file is released).
485 */
486 static
487 int lttng_release_session(int objd)
488 {
489 struct ltt_session *session = objd_private(objd);
490
491 if (session) {
492 ltt_session_destroy(session);
493 return 0;
494 } else {
495 return -EINVAL;
496 }
497 }
498
499 static const struct objd_ops lttng_session_ops = {
500 .release = lttng_release_session,
501 .cmd = lttng_session_cmd,
502 };
503
504 struct stream_priv_data {
505 struct lib_ring_buffer *buf;
506 struct ltt_channel *ltt_chan;
507 };
508
509 static
510 int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info)
511 {
512 struct ltt_channel *channel = objd_private(channel_objd);
513 struct lib_ring_buffer *buf;
514 struct stream_priv_data *priv;
515 int stream_objd, ret;
516
517 buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
518 &info->shm_fd, &info->wait_fd, &info->memory_map_size);
519 if (!buf)
520 return -ENOENT;
521
522 priv = zmalloc(sizeof(*priv));
523 if (!priv) {
524 ret = -ENOMEM;
525 goto alloc_error;
526 }
527 priv->buf = buf;
528 priv->ltt_chan = channel;
529 stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops);
530 if (stream_objd < 0) {
531 ret = stream_objd;
532 goto objd_error;
533 }
534 /* Hold a reference on the channel object descriptor */
535 objd_ref(channel_objd);
536 return stream_objd;
537
538 objd_error:
539 free(priv);
540 alloc_error:
541 channel->ops->buffer_read_close(buf, channel->handle);
542 return ret;
543 }
544
545 static
546 int lttng_abi_create_event(int channel_objd,
547 struct lttng_ust_event *event_param)
548 {
549 struct ltt_channel *channel = objd_private(channel_objd);
550 struct ltt_event *event;
551 int event_objd, ret;
552
553 event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
554 event_objd = objd_alloc(NULL, &lttng_event_ops);
555 if (event_objd < 0) {
556 ret = event_objd;
557 goto objd_error;
558 }
559 /*
560 * We tolerate no failure path after event creation. It will stay
561 * invariant for the rest of the session.
562 */
563 event = ltt_event_create(channel, event_param, NULL);
564 if (!event) {
565 ret = -EINVAL;
566 goto event_error;
567 }
568 objd_set_private(event_objd, event);
569 /* The event holds a reference on the channel */
570 objd_ref(channel_objd);
571 return event_objd;
572
573 event_error:
574 {
575 int err;
576
577 err = objd_unref(event_objd);
578 assert(!err);
579 }
580 objd_error:
581 return ret;
582 }
583
584 /**
585 * lttng_channel_cmd - lttng control through object descriptors
586 *
587 * @objd: the object descriptor
588 * @cmd: the command
589 * @arg: command arg
590 *
591 * This object descriptor implements lttng commands:
592 * LTTNG_UST_STREAM
593 * Returns an event stream object descriptor or failure.
594 * (typically, one event stream records events from one CPU)
595 * LTTNG_UST_EVENT
596 * Returns an event object descriptor or failure.
597 * LTTNG_UST_CONTEXT
598 * Prepend a context field to each event in the channel
599 * LTTNG_UST_ENABLE
600 * Enable recording for events in this channel (weak enable)
601 * LTTNG_UST_DISABLE
602 * Disable recording for events in this channel (strong disable)
603 *
604 * Channel and event file descriptors also hold a reference on the session.
605 */
606 static
607 long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
608 {
609 struct ltt_channel *channel = objd_private(objd);
610
611 switch (cmd) {
612 case LTTNG_UST_STREAM:
613 {
614 struct lttng_ust_stream *stream;
615
616 stream = (struct lttng_ust_stream *) arg;
617 /* stream used as output */
618 return lttng_abi_open_stream(objd, stream);
619 }
620 case LTTNG_UST_EVENT:
621 return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg);
622 case LTTNG_UST_CONTEXT:
623 return lttng_abi_add_context(objd,
624 (struct lttng_ust_context *) arg,
625 &channel->ctx, channel->session);
626 case LTTNG_UST_ENABLE:
627 return ltt_channel_enable(channel);
628 case LTTNG_UST_DISABLE:
629 return ltt_channel_disable(channel);
630 default:
631 return -EINVAL;
632 }
633 }
634
635 /**
636 * lttng_metadata_cmd - lttng control through object descriptors
637 *
638 * @objd: the object descriptor
639 * @cmd: the command
640 * @arg: command arg
641 *
642 * This object descriptor implements lttng commands:
643 * LTTNG_UST_STREAM
644 * Returns an event stream file descriptor or failure.
645 *
646 * Channel and event file descriptors also hold a reference on the session.
647 */
648 static
649 long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
650 {
651 switch (cmd) {
652 case LTTNG_UST_STREAM:
653 {
654 struct lttng_ust_stream *stream;
655
656 stream = (struct lttng_ust_stream *) arg;
657 /* stream used as output */
658 return lttng_abi_open_stream(objd, stream);
659 }
660 default:
661 return -EINVAL;
662 }
663 }
664
665 #if 0
666 /**
667 * lttng_channel_poll - lttng stream addition/removal monitoring
668 *
669 * @file: the file
670 * @wait: poll table
671 */
672 unsigned int lttng_channel_poll(struct file *file, poll_table *wait)
673 {
674 struct ltt_channel *channel = file->private_data;
675 unsigned int mask = 0;
676
677 if (file->f_mode & FMODE_READ) {
678 poll_wait_set_exclusive(wait);
679 poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan),
680 wait);
681
682 if (channel->ops->is_disabled(channel->chan))
683 return POLLERR;
684 if (channel->ops->is_finalized(channel->chan))
685 return POLLHUP;
686 if (channel->ops->buffer_has_read_closed_stream(channel->chan))
687 return POLLIN | POLLRDNORM;
688 return 0;
689 }
690 return mask;
691
692 }
693 #endif //0
694
695 static
696 int lttng_channel_release(int objd)
697 {
698 struct ltt_channel *channel = objd_private(objd);
699
700 if (channel)
701 return objd_unref(channel->session->objd);
702 return 0;
703 }
704
705 static const struct objd_ops lttng_channel_ops = {
706 .release = lttng_channel_release,
707 //.poll = lttng_channel_poll,
708 .cmd = lttng_channel_cmd,
709 };
710
711 static const struct objd_ops lttng_metadata_ops = {
712 .release = lttng_channel_release,
713 .cmd = lttng_metadata_cmd,
714 };
715
716 /**
717 * lttng_rb_cmd - lttng ring buffer control through object descriptors
718 *
719 * @objd: the object descriptor
720 * @cmd: the command
721 * @arg: command arg
722 *
723 * This object descriptor implements lttng commands:
724 * (None for now. Access is done directly though shm.)
725 * TODO: Add buffer flush.
726 */
727 static
728 long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg)
729 {
730 //struct stream_priv_data *priv = objd_private(objd);
731
732 switch (cmd) {
733 default:
734 return -EINVAL;
735 }
736 }
737
738 static
739 int lttng_rb_release(int objd)
740 {
741 struct stream_priv_data *priv = objd_private(objd);
742 struct lib_ring_buffer *buf;
743 struct ltt_channel *channel;
744
745 if (priv) {
746 buf = priv->buf;
747 channel = priv->ltt_chan;
748 free(priv);
749 channel->ops->buffer_read_close(buf, channel->handle);
750
751 return objd_unref(channel->objd);
752 }
753 return 0;
754 }
755
756 static const struct objd_ops lib_ring_buffer_objd_ops = {
757 .release = lttng_rb_release,
758 .cmd = lttng_rb_cmd,
759 };
760
761 /**
762 * lttng_event_cmd - lttng control through object descriptors
763 *
764 * @objd: the object descriptor
765 * @cmd: the command
766 * @arg: command arg
767 *
768 * This object descriptor implements lttng commands:
769 * LTTNG_UST_CONTEXT
770 * Prepend a context field to each record of this event
771 * LTTNG_UST_ENABLE
772 * Enable recording for this event (weak enable)
773 * LTTNG_UST_DISABLE
774 * Disable recording for this event (strong disable)
775 */
776 static
777 long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
778 {
779 struct ltt_event *event = objd_private(objd);
780
781 switch (cmd) {
782 case LTTNG_UST_CONTEXT:
783 return lttng_abi_add_context(objd,
784 (struct lttng_ust_context *) arg,
785 &event->ctx, event->chan->session);
786 case LTTNG_UST_ENABLE:
787 return ltt_event_enable(event);
788 case LTTNG_UST_DISABLE:
789 return ltt_event_disable(event);
790 default:
791 return -EINVAL;
792 }
793 }
794
795 static
796 int lttng_event_release(int objd)
797 {
798 struct ltt_event *event = objd_private(objd);
799
800 if (event)
801 return objd_unref(event->chan->objd);
802 return 0;
803 }
804
805 /* TODO: filter control ioctl */
806 static const struct objd_ops lttng_event_ops = {
807 .release = lttng_event_release,
808 .cmd = lttng_event_cmd,
809 };
810
811 void lttng_ust_abi_exit(void)
812 {
813 objd_table_destroy();
814 }
This page took 0.054392 seconds and 3 git commands to generate.