Cleanup warnings
[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
fb50c39d 180 for (i = 0; i < objd_table.allocated_len; i++)
824f40b8 181 (void) objd_unref(i);
f4681817 182 free(objd_table.array);
02fb3381
MD
183 objd_table.array = NULL;
184 objd_table.len = 0;
185 objd_table.allocated_len = 0;
17dfb34b 186 objd_table.freelist_head = -1;
f4681817
MD
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
194static const struct objd_ops lttng_ops;
195static const struct objd_ops lttng_session_ops;
196static const struct objd_ops lttng_channel_ops;
197static const struct objd_ops lttng_metadata_ops;
198static const struct objd_ops lttng_event_ops;
381c0f1e 199static const struct objd_ops lib_ring_buffer_objd_ops;
f4681817
MD
200
201enum channel_type {
202 PER_CPU_CHANNEL,
203 METADATA_CHANNEL,
204};
205
46050b1a
MD
206int 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
818173b9 215static
f4681817
MD
216int 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
232objd_error:
233 ltt_session_destroy(session);
234 return ret;
235}
236
237#if 0
238static
239int 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
252objd_error:
253 return ret;
254}
255#endif //0
256
257static
258long 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
267static
268long 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:
438bc215 277 //TODO return lttng_add_vtid_to_ctx(ctx);
f4681817
MD
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 */
302static
303long 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
322static 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 */
331static
332void 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
353create_error:
354 WARN_ON(1);
355 return; /* not allowed to return error */
356}
357
f4681817
MD
358int 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,
193183fb
MD
403 chan_param->read_timer_interval,
404 &chan_param->shm_fd,
405 &chan_param->wait_fd,
406 &chan_param->memory_map_size);
f4681817
MD
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
423chan_error:
1ea11eab
MD
424 {
425 int err;
426
427 err = objd_unref(chan_objd);
428 assert(!err);
429 }
f4681817
MD
430objd_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 */
453static
454long 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 */
486static
1ea11eab 487int lttng_release_session(int objd)
f4681817
MD
488{
489 struct ltt_session *session = objd_private(objd);
490
1ea11eab 491 if (session) {
f4681817 492 ltt_session_destroy(session);
1ea11eab
MD
493 return 0;
494 } else {
495 return -EINVAL;
496 }
f4681817
MD
497}
498
499static const struct objd_ops lttng_session_ops = {
1ea11eab 500 .release = lttng_release_session,
f4681817
MD
501 .cmd = lttng_session_cmd,
502};
503
381c0f1e
MD
504struct stream_priv_data {
505 struct lib_ring_buffer *buf;
506 struct ltt_channel *ltt_chan;
507};
508
f4681817 509static
381c0f1e 510int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info)
f4681817
MD
511{
512 struct ltt_channel *channel = objd_private(channel_objd);
513 struct lib_ring_buffer *buf;
381c0f1e 514 struct stream_priv_data *priv;
f4681817
MD
515 int stream_objd, ret;
516
381c0f1e
MD
517 buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
518 &info->shm_fd, &info->wait_fd, &info->memory_map_size);
f4681817
MD
519 if (!buf)
520 return -ENOENT;
521
381c0f1e
MD
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);
f4681817
MD
530 if (stream_objd < 0) {
531 ret = stream_objd;
532 goto objd_error;
533 }
381c0f1e
MD
534 /* Hold a reference on the channel object descriptor */
535 objd_ref(channel_objd);
f4681817
MD
536 return stream_objd;
537
538objd_error:
381c0f1e
MD
539 free(priv);
540alloc_error:
541 channel->ops->buffer_read_close(buf, channel->handle);
f4681817
MD
542 return ret;
543}
f4681817
MD
544
545static
546int 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
573event_error:
1ea11eab
MD
574 {
575 int err;
576
577 err = objd_unref(event_objd);
578 assert(!err);
579 }
f4681817
MD
580objd_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 */
606static
607long 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:
381c0f1e
MD
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 }
f4681817
MD
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 */
648static
649long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
650{
651 switch (cmd) {
652 case LTTNG_UST_STREAM:
381c0f1e
MD
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 }
f4681817
MD
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 */
672unsigned 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
695static
696int lttng_channel_release(int objd)
697{
698 struct ltt_channel *channel = objd_private(objd);
699
700 if (channel)
1ea11eab 701 return objd_unref(channel->session->objd);
f4681817
MD
702 return 0;
703}
704
705static const struct objd_ops lttng_channel_ops = {
706 .release = lttng_channel_release,
707 //.poll = lttng_channel_poll,
708 .cmd = lttng_channel_cmd,
709};
710
711static const struct objd_ops lttng_metadata_ops = {
712 .release = lttng_channel_release,
713 .cmd = lttng_metadata_cmd,
714};
715
381c0f1e
MD
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 */
727static
728long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg)
729{
fb50c39d 730 //struct stream_priv_data *priv = objd_private(objd);
381c0f1e
MD
731
732 switch (cmd) {
733 default:
734 return -EINVAL;
735 }
736}
737
738static
739int 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);
824f40b8 749 channel->ops->buffer_read_close(buf, channel->handle);
381c0f1e
MD
750
751 return objd_unref(channel->objd);
752 }
753 return 0;
754}
755
756static const struct objd_ops lib_ring_buffer_objd_ops = {
757 .release = lttng_rb_release,
758 .cmd = lttng_rb_cmd,
759};
760
f4681817
MD
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 */
776static
777long 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
795static
796int lttng_event_release(int objd)
797{
798 struct ltt_event *event = objd_private(objd);
799
800 if (event)
1ea11eab 801 return objd_unref(event->chan->objd);
f4681817
MD
802 return 0;
803}
804
805/* TODO: filter control ioctl */
806static const struct objd_ops lttng_event_ops = {
807 .release = lttng_event_release,
808 .cmd = lttng_event_cmd,
809};
810
b35d179d 811void lttng_ust_abi_exit(void)
f4681817 812{
f4681817
MD
813 objd_table_destroy();
814}
This page took 0.053173 seconds and 4 git commands to generate.