Centralize locking with ust_lock, fork handling
[lttng-ust.git] / libust / lttng-ust-abi.c
CommitLineData
f4681817
MD
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>
1dbfff0c 31#include <ust/usterr-signal-safe.h>
f4681817
MD
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
f4681817
MD
40struct 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
51struct objd_table {
52 struct obj *array;
53 unsigned int len, allocated_len;
54 int freelist_head; /* offset freelist head. end is -1 */
55};
56
57static struct objd_table objd_table = {
58 .freelist_head = -1,
59};
60
61static
62int 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++;
93end:
94 obj->u.s.private_data = private_data;
95 obj->u.s.ops = ops;
a4be8962
MD
96 obj->u.s.f_count = 2; /* count == 1 : object is allocated */
97 /* count == 2 : allocated + hold ref */
f4681817
MD
98 return obj - objd_table.array;
99}
100
101static
102struct obj *_objd_get(int id)
103{
104 if (id >= objd_table.len)
105 return NULL;
a4be8962
MD
106 if (!objd_table.array[id].u.s.f_count)
107 return NULL;
f4681817
MD
108 return &objd_table.array[id];
109}
110
111static
112void *objd_private(int id)
113{
114 struct obj *obj = _objd_get(id);
115 assert(obj);
116 return obj->u.s.private_data;
117}
118
119static
120void 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
f4681817
MD
127const struct objd_ops *objd_ops(int id)
128{
129 struct obj *obj = _objd_get(id);
46050b1a 130
a4be8962
MD
131 if (!obj)
132 return NULL;
f4681817
MD
133 return obj->u.s.ops;
134}
135
136static
137void 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;
a4be8962
MD
144 assert(obj->u.s.f_count == 1);
145 obj->u.s.f_count = 0; /* deallocated */
f4681817
MD
146}
147
148static
149void objd_ref(int id)
150{
151 struct obj *obj = _objd_get(id);
152 obj->u.s.f_count++;
153}
154
1ea11eab 155int objd_unref(int id)
f4681817
MD
156{
157 struct obj *obj = _objd_get(id);
158
1ea11eab
MD
159 if (!obj)
160 return -EINVAL;
a4be8962
MD
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) {
f4681817 166 const struct objd_ops *ops = objd_ops(id);
a4be8962 167
f4681817
MD
168 if (ops->release)
169 ops->release(id);
170 objd_free(id);
171 }
1ea11eab 172 return 0;
f4681817
MD
173}
174
175static
176void objd_table_destroy(void)
177{
a4be8962
MD
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 }
f4681817 190 free(objd_table.array);
17dfb34b 191 objd_table.freelist_head = -1;
f4681817
MD
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
199static const struct objd_ops lttng_ops;
200static const struct objd_ops lttng_session_ops;
201static const struct objd_ops lttng_channel_ops;
202static const struct objd_ops lttng_metadata_ops;
203static const struct objd_ops lttng_event_ops;
204
205enum channel_type {
206 PER_CPU_CHANNEL,
207 METADATA_CHANNEL,
208};
209
46050b1a
MD
210int 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
818173b9 219static
f4681817
MD
220int 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
236objd_error:
237 ltt_session_destroy(session);
238 return ret;
239}
240
241#if 0
242static
243int 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
256objd_error:
257 return ret;
258}
259#endif //0
260
261static
262long 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
271static
272long 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:
438bc215 281 //TODO return lttng_add_vtid_to_ctx(ctx);
f4681817
MD
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 */
306static
307long 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
326static 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 */
335static
336void 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
357create_error:
358 WARN_ON(1);
359 return; /* not allowed to return error */
360}
361
f4681817
MD
362int 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
424chan_error:
1ea11eab
MD
425 {
426 int err;
427
428 err = objd_unref(chan_objd);
429 assert(!err);
430 }
f4681817
MD
431objd_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 */
454static
455long 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 */
487static
1ea11eab 488int lttng_release_session(int objd)
f4681817
MD
489{
490 struct ltt_session *session = objd_private(objd);
491
1ea11eab 492 if (session) {
f4681817 493 ltt_session_destroy(session);
1ea11eab
MD
494 return 0;
495 } else {
496 return -EINVAL;
497 }
f4681817
MD
498}
499
500static const struct objd_ops lttng_session_ops = {
1ea11eab 501 .release = lttng_release_session,
f4681817
MD
502 .cmd = lttng_session_cmd,
503};
504
505#if 0
506static
507int 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
529objd_error:
530 channel->ops->buffer_read_close(buf);
531 return ret;
532}
533#endif //0
534
535static
536int 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
563event_error:
1ea11eab
MD
564 {
565 int err;
566
567 err = objd_unref(event_objd);
568 assert(!err);
569 }
f4681817
MD
570objd_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 */
596static
597long 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 */
633static
634long 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 */
652unsigned 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
675static
676int lttng_channel_release(int objd)
677{
678 struct ltt_channel *channel = objd_private(objd);
679
680 if (channel)
1ea11eab 681 return objd_unref(channel->session->objd);
f4681817
MD
682 return 0;
683}
684
685static const struct objd_ops lttng_channel_ops = {
686 .release = lttng_channel_release,
687 //.poll = lttng_channel_poll,
688 .cmd = lttng_channel_cmd,
689};
690
691static 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 */
711static
712long 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
730static
731int lttng_event_release(int objd)
732{
733 struct ltt_event *event = objd_private(objd);
734
735 if (event)
1ea11eab 736 return objd_unref(event->chan->objd);
f4681817
MD
737 return 0;
738}
739
740/* TODO: filter control ioctl */
741static const struct objd_ops lttng_event_ops = {
742 .release = lttng_event_release,
743 .cmd = lttng_event_cmd,
744};
745
b35d179d 746void lttng_ust_abi_exit(void)
f4681817 747{
f4681817
MD
748 objd_table_destroy();
749}
This page took 0.050732 seconds and 4 git commands to generate.