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