Centralize locking with ust_lock, fork handling
[lttng-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 struct obj *obj = _objd_get(i);
182 const struct objd_ops *ops;
183
184 if (!obj)
185 continue;
186 ops = obj->u.s.ops;
187 if (ops->release)
188 ops->release(i);
189 }
190 free(objd_table.array);
191 objd_table.freelist_head = -1;
192 }
193
194 /*
195 * This is LTTng's own personal way to create an ABI for sessiond.
196 * We send commands over a socket.
197 */
198
199 static const struct objd_ops lttng_ops;
200 static const struct objd_ops lttng_session_ops;
201 static const struct objd_ops lttng_channel_ops;
202 static const struct objd_ops lttng_metadata_ops;
203 static const struct objd_ops lttng_event_ops;
204
205 enum channel_type {
206 PER_CPU_CHANNEL,
207 METADATA_CHANNEL,
208 };
209
210 int lttng_abi_create_root_handle(void)
211 {
212 int root_handle;
213
214 root_handle = objd_alloc(NULL, &lttng_ops);
215 assert(root_handle == 0);
216 return root_handle;
217 }
218
219 static
220 int lttng_abi_create_session(void)
221 {
222 struct ltt_session *session;
223 int session_objd, ret;
224
225 session = ltt_session_create();
226 if (!session)
227 return -ENOMEM;
228 session_objd = objd_alloc(session, &lttng_session_ops);
229 if (session_objd < 0) {
230 ret = session_objd;
231 goto objd_error;
232 }
233 session->objd = session_objd;
234 return session_objd;
235
236 objd_error:
237 ltt_session_destroy(session);
238 return ret;
239 }
240
241 #if 0
242 static
243 int lttng_abi_tracepoint_list(void)
244 {
245 int list_objd, ret;
246
247 /* TODO: Create list private data */
248 list_objd = objd_alloc(NULL, &lttng_tracepoint_list_ops);
249 if (list_objd < 0) {
250 ret = list_objd;
251 goto objd_error;
252 }
253
254 return list_objd;
255
256 objd_error:
257 return ret;
258 }
259 #endif //0
260
261 static
262 long lttng_abi_tracer_version(int objd,
263 struct lttng_ust_tracer_version *v)
264 {
265 v->version = LTTNG_UST_VERSION;
266 v->patchlevel = LTTNG_UST_PATCHLEVEL;
267 v->sublevel = LTTNG_UST_SUBLEVEL;
268 return 0;
269 }
270
271 static
272 long lttng_abi_add_context(int objd,
273 struct lttng_ust_context *context_param,
274 struct lttng_ctx **ctx, struct ltt_session *session)
275 {
276 if (session->been_active)
277 return -EPERM;
278
279 switch (context_param->ctx) {
280 case LTTNG_UST_CONTEXT_VTID:
281 //TODO return lttng_add_vtid_to_ctx(ctx);
282 default:
283 return -EINVAL;
284 }
285 }
286
287 /**
288 * lttng_cmd - lttng control through socket commands
289 *
290 * @objd: the object descriptor
291 * @cmd: the command
292 * @arg: command arg
293 *
294 * This descriptor implements lttng commands:
295 * LTTNG_UST_SESSION
296 * Returns a LTTng trace session object descriptor
297 * LTTNG_UST_TRACER_VERSION
298 * Returns the LTTng kernel tracer version
299 * LTTNG_UST_TRACEPOINT_LIST
300 * Returns a file descriptor listing available tracepoints
301 * LTTNG_UST_WAIT_QUIESCENT
302 * Returns after all previously running probes have completed
303 *
304 * The returned session will be deleted when its file descriptor is closed.
305 */
306 static
307 long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
308 {
309 switch (cmd) {
310 case LTTNG_UST_SESSION:
311 return lttng_abi_create_session();
312 case LTTNG_UST_TRACER_VERSION:
313 return lttng_abi_tracer_version(objd,
314 (struct lttng_ust_tracer_version *) arg);
315 case LTTNG_UST_TRACEPOINT_LIST:
316 return -ENOSYS; //TODO
317 //return lttng_abi_tracepoint_list();
318 case LTTNG_UST_WAIT_QUIESCENT:
319 synchronize_trace();
320 return 0;
321 default:
322 return -EINVAL;
323 }
324 }
325
326 static const struct objd_ops lttng_ops = {
327 .cmd = lttng_cmd,
328 };
329
330 /*
331 * We tolerate no failure in this function (if one happens, we print a dmesg
332 * error, but cannot return any error, because the channel information is
333 * invariant.
334 */
335 static
336 void lttng_metadata_create_events(int channel_objd)
337 {
338 struct ltt_channel *channel = objd_private(channel_objd);
339 static struct lttng_ust_event metadata_params = {
340 .instrumentation = LTTNG_UST_TRACEPOINT,
341 .name = "lttng_metadata",
342 };
343 struct ltt_event *event;
344 int ret;
345
346 /*
347 * We tolerate no failure path after event creation. It will stay
348 * invariant for the rest of the session.
349 */
350 event = ltt_event_create(channel, &metadata_params, NULL);
351 if (!event) {
352 ret = -EINVAL;
353 goto create_error;
354 }
355 return;
356
357 create_error:
358 WARN_ON(1);
359 return; /* not allowed to return error */
360 }
361
362 int lttng_abi_create_channel(int session_objd,
363 struct lttng_ust_channel *chan_param,
364 enum channel_type channel_type)
365 {
366 struct ltt_session *session = objd_private(session_objd);
367 const struct objd_ops *ops;
368 const char *transport_name;
369 struct ltt_channel *chan;
370 int chan_objd;
371 int ret = 0;
372
373 chan_objd = objd_alloc(NULL, &lttng_channel_ops);
374 if (chan_objd < 0) {
375 ret = chan_objd;
376 goto objd_error;
377 }
378 switch (channel_type) {
379 case PER_CPU_CHANNEL:
380 if (chan_param->output == LTTNG_UST_MMAP) {
381 transport_name = chan_param->overwrite ?
382 "relay-overwrite-mmap" : "relay-discard-mmap";
383 } else {
384 return -EINVAL;
385 }
386 ops = &lttng_channel_ops;
387 break;
388 case METADATA_CHANNEL:
389 if (chan_param->output == LTTNG_UST_MMAP)
390 transport_name = "relay-metadata-mmap";
391 else
392 return -EINVAL;
393 ops = &lttng_metadata_ops;
394 break;
395 default:
396 transport_name = "<unknown>";
397 break;
398 }
399 /*
400 * We tolerate no failure path after channel creation. It will stay
401 * invariant for the rest of the session.
402 */
403 chan = ltt_channel_create(session, transport_name, NULL,
404 chan_param->subbuf_size,
405 chan_param->num_subbuf,
406 chan_param->switch_timer_interval,
407 chan_param->read_timer_interval);
408 if (!chan) {
409 ret = -EINVAL;
410 goto chan_error;
411 }
412 objd_set_private(chan_objd, chan);
413 chan->objd = chan_objd;
414 if (channel_type == METADATA_CHANNEL) {
415 session->metadata = chan;
416 lttng_metadata_create_events(chan_objd);
417 }
418
419 /* The channel created holds a reference on the session */
420 objd_ref(session_objd);
421
422 return chan_objd;
423
424 chan_error:
425 {
426 int err;
427
428 err = objd_unref(chan_objd);
429 assert(!err);
430 }
431 objd_error:
432 return ret;
433 }
434
435 /**
436 * lttng_session_cmd - lttng session object command
437 *
438 * @obj: the object
439 * @cmd: the command
440 * @arg: command arg
441 *
442 * This descriptor implements lttng commands:
443 * LTTNG_UST_CHANNEL
444 * Returns a LTTng channel object descriptor
445 * LTTNG_UST_ENABLE
446 * Enables tracing for a session (weak enable)
447 * LTTNG_UST_DISABLE
448 * Disables tracing for a session (strong disable)
449 * LTTNG_UST_METADATA
450 * Returns a LTTng metadata object descriptor
451 *
452 * The returned channel will be deleted when its file descriptor is closed.
453 */
454 static
455 long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
456 {
457 struct ltt_session *session = objd_private(objd);
458
459 switch (cmd) {
460 case LTTNG_UST_CHANNEL:
461 return lttng_abi_create_channel(objd,
462 (struct lttng_ust_channel *) arg,
463 PER_CPU_CHANNEL);
464 case LTTNG_UST_SESSION_START:
465 case LTTNG_UST_ENABLE:
466 return ltt_session_enable(session);
467 case LTTNG_UST_SESSION_STOP:
468 case LTTNG_UST_DISABLE:
469 return ltt_session_disable(session);
470 case LTTNG_UST_METADATA:
471 return lttng_abi_create_channel(objd,
472 (struct lttng_ust_channel *) arg,
473 METADATA_CHANNEL);
474 default:
475 return -EINVAL;
476 }
477 }
478
479 /*
480 * Called when the last file reference is dropped.
481 *
482 * Big fat note: channels and events are invariant for the whole session after
483 * their creation. So this session destruction also destroys all channel and
484 * event structures specific to this session (they are not destroyed when their
485 * individual file is released).
486 */
487 static
488 int lttng_release_session(int objd)
489 {
490 struct ltt_session *session = objd_private(objd);
491
492 if (session) {
493 ltt_session_destroy(session);
494 return 0;
495 } else {
496 return -EINVAL;
497 }
498 }
499
500 static const struct objd_ops lttng_session_ops = {
501 .release = lttng_release_session,
502 .cmd = lttng_session_cmd,
503 };
504
505 #if 0
506 static
507 int lttng_abi_open_stream(int channel_objd)
508 {
509 struct ltt_channel *channel = objd_private(channel_objd);
510 struct lib_ring_buffer *buf;
511 int stream_objd, ret;
512
513 buf = channel->ops->buffer_read_open(channel->chan);
514 if (!buf)
515 return -ENOENT;
516
517 stream_objd = objd_alloc(buf, &lib_ring_buffer_objd_ops);
518 if (stream_objd < 0) {
519 ret = stream_objd;
520 goto objd_error;
521 }
522 /*
523 * The stream holds a reference to the channel within the generic ring
524 * buffer library, so no need to hold a refcount on the channel and
525 * session files here.
526 */
527 return stream_objd;
528
529 objd_error:
530 channel->ops->buffer_read_close(buf);
531 return ret;
532 }
533 #endif //0
534
535 static
536 int lttng_abi_create_event(int channel_objd,
537 struct lttng_ust_event *event_param)
538 {
539 struct ltt_channel *channel = objd_private(channel_objd);
540 struct ltt_event *event;
541 int event_objd, ret;
542
543 event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
544 event_objd = objd_alloc(NULL, &lttng_event_ops);
545 if (event_objd < 0) {
546 ret = event_objd;
547 goto objd_error;
548 }
549 /*
550 * We tolerate no failure path after event creation. It will stay
551 * invariant for the rest of the session.
552 */
553 event = ltt_event_create(channel, event_param, NULL);
554 if (!event) {
555 ret = -EINVAL;
556 goto event_error;
557 }
558 objd_set_private(event_objd, event);
559 /* The event holds a reference on the channel */
560 objd_ref(channel_objd);
561 return event_objd;
562
563 event_error:
564 {
565 int err;
566
567 err = objd_unref(event_objd);
568 assert(!err);
569 }
570 objd_error:
571 return ret;
572 }
573
574 /**
575 * lttng_channel_cmd - lttng control through object descriptors
576 *
577 * @objd: the object descriptor
578 * @cmd: the command
579 * @arg: command arg
580 *
581 * This object descriptor implements lttng commands:
582 * LTTNG_UST_STREAM
583 * Returns an event stream object descriptor or failure.
584 * (typically, one event stream records events from one CPU)
585 * LTTNG_UST_EVENT
586 * Returns an event object descriptor or failure.
587 * LTTNG_UST_CONTEXT
588 * Prepend a context field to each event in the channel
589 * LTTNG_UST_ENABLE
590 * Enable recording for events in this channel (weak enable)
591 * LTTNG_UST_DISABLE
592 * Disable recording for events in this channel (strong disable)
593 *
594 * Channel and event file descriptors also hold a reference on the session.
595 */
596 static
597 long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
598 {
599 struct ltt_channel *channel = objd_private(objd);
600
601 switch (cmd) {
602 case LTTNG_UST_STREAM:
603 return -ENOSYS; //TODO
604 //return lttng_abi_open_stream(objd);
605 case LTTNG_UST_EVENT:
606 return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg);
607 case LTTNG_UST_CONTEXT:
608 return lttng_abi_add_context(objd,
609 (struct lttng_ust_context *) arg,
610 &channel->ctx, channel->session);
611 case LTTNG_UST_ENABLE:
612 return ltt_channel_enable(channel);
613 case LTTNG_UST_DISABLE:
614 return ltt_channel_disable(channel);
615 default:
616 return -EINVAL;
617 }
618 }
619
620 /**
621 * lttng_metadata_cmd - lttng control through object descriptors
622 *
623 * @objd: the object descriptor
624 * @cmd: the command
625 * @arg: command arg
626 *
627 * This object descriptor implements lttng commands:
628 * LTTNG_UST_STREAM
629 * Returns an event stream file descriptor or failure.
630 *
631 * Channel and event file descriptors also hold a reference on the session.
632 */
633 static
634 long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
635 {
636 switch (cmd) {
637 case LTTNG_UST_STREAM:
638 return -ENOSYS; //TODO
639 //return lttng_abi_open_stream(objd);
640 default:
641 return -EINVAL;
642 }
643 }
644
645 #if 0
646 /**
647 * lttng_channel_poll - lttng stream addition/removal monitoring
648 *
649 * @file: the file
650 * @wait: poll table
651 */
652 unsigned int lttng_channel_poll(struct file *file, poll_table *wait)
653 {
654 struct ltt_channel *channel = file->private_data;
655 unsigned int mask = 0;
656
657 if (file->f_mode & FMODE_READ) {
658 poll_wait_set_exclusive(wait);
659 poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan),
660 wait);
661
662 if (channel->ops->is_disabled(channel->chan))
663 return POLLERR;
664 if (channel->ops->is_finalized(channel->chan))
665 return POLLHUP;
666 if (channel->ops->buffer_has_read_closed_stream(channel->chan))
667 return POLLIN | POLLRDNORM;
668 return 0;
669 }
670 return mask;
671
672 }
673 #endif //0
674
675 static
676 int lttng_channel_release(int objd)
677 {
678 struct ltt_channel *channel = objd_private(objd);
679
680 if (channel)
681 return objd_unref(channel->session->objd);
682 return 0;
683 }
684
685 static const struct objd_ops lttng_channel_ops = {
686 .release = lttng_channel_release,
687 //.poll = lttng_channel_poll,
688 .cmd = lttng_channel_cmd,
689 };
690
691 static const struct objd_ops lttng_metadata_ops = {
692 .release = lttng_channel_release,
693 .cmd = lttng_metadata_cmd,
694 };
695
696 /**
697 * lttng_event_cmd - lttng control through object descriptors
698 *
699 * @objd: the object descriptor
700 * @cmd: the command
701 * @arg: command arg
702 *
703 * This object descriptor implements lttng commands:
704 * LTTNG_UST_CONTEXT
705 * Prepend a context field to each record of this event
706 * LTTNG_UST_ENABLE
707 * Enable recording for this event (weak enable)
708 * LTTNG_UST_DISABLE
709 * Disable recording for this event (strong disable)
710 */
711 static
712 long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
713 {
714 struct ltt_event *event = objd_private(objd);
715
716 switch (cmd) {
717 case LTTNG_UST_CONTEXT:
718 return lttng_abi_add_context(objd,
719 (struct lttng_ust_context *) arg,
720 &event->ctx, event->chan->session);
721 case LTTNG_UST_ENABLE:
722 return ltt_event_enable(event);
723 case LTTNG_UST_DISABLE:
724 return ltt_event_disable(event);
725 default:
726 return -EINVAL;
727 }
728 }
729
730 static
731 int lttng_event_release(int objd)
732 {
733 struct ltt_event *event = objd_private(objd);
734
735 if (event)
736 return objd_unref(event->chan->objd);
737 return 0;
738 }
739
740 /* TODO: filter control ioctl */
741 static const struct objd_ops lttng_event_ops = {
742 .release = lttng_event_release,
743 .cmd = lttng_event_cmd,
744 };
745
746 void lttng_ust_abi_exit(void)
747 {
748 objd_table_destroy();
749 }
This page took 0.044524 seconds and 5 git commands to generate.