add ustctl_release_handle
[lttng-ust.git] / liblttng-ust-ctl / ustctl.c
1 /*
2 * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; only version 2
8 * of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include <string.h>
21 #include <lttng/ust-ctl.h>
22 #include <lttng/ust-abi.h>
23 #include <lttng/ust-events.h>
24 #include <sys/mman.h>
25
26 #include <usterr-signal-safe.h>
27 #include <ust-comm.h>
28
29 #include "../libringbuffer/backend.h"
30 #include "../libringbuffer/frontend.h"
31
32 volatile enum ust_loglevel ust_loglevel;
33
34 static
35 void init_object(struct lttng_ust_object_data *data)
36 {
37 data->handle = -1;
38 data->shm_fd = -1;
39 data->wait_fd = -1;
40 data->memory_map_size = 0;
41 }
42
43 int ustctl_release_handle(int sock, int handle)
44 {
45 struct ustcomm_ust_msg lum;
46 struct ustcomm_ust_reply lur;
47 int ret;
48
49 if (sock >= 0) {
50 memset(&lum, 0, sizeof(lum));
51 lum.handle = handle;
52 lum.cmd = LTTNG_UST_RELEASE;
53 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
54 if (ret < 0) {
55 return ret;
56 }
57 }
58 return 0;
59 }
60 /*
61 * If sock is negative, it means we don't have to notify the other side
62 * (e.g. application has already vanished).
63 */
64 int ustctl_release_object(int sock, struct lttng_ust_object_data *data)
65 {
66 struct ustcomm_ust_msg lum;
67 struct ustcomm_ust_reply lur;
68 int ret;
69
70 if (data->shm_fd >= 0) {
71 ret = close(data->shm_fd);
72 if (ret < 0) {
73 return ret;
74 }
75 }
76 if (data->wait_fd >= 0) {
77 ret = close(data->wait_fd);
78 if (ret < 0) {
79 return ret;
80 }
81 }
82 return ustctl_release_handle(sock, data->handle);
83 }
84
85 /*
86 * Send registration done packet to the application.
87 */
88 int ustctl_register_done(int sock)
89 {
90 struct ustcomm_ust_msg lum;
91 struct ustcomm_ust_reply lur;
92 int ret;
93
94 DBG("Sending register done command to %d", sock);
95 memset(&lum, 0, sizeof(lum));
96 lum.handle = LTTNG_UST_ROOT_HANDLE;
97 lum.cmd = LTTNG_UST_REGISTER_DONE;
98 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
99 if (ret)
100 return ret;
101 if (lur.ret_code != USTCOMM_OK) {
102 DBG("Return code: %s", ustcomm_get_readable_code(lur.ret_code));
103 goto error;
104 }
105 return 0;
106
107 error:
108 return -1;
109 }
110
111 /*
112 * returns session handle.
113 */
114 int ustctl_create_session(int sock)
115 {
116 struct ustcomm_ust_msg lum;
117 struct ustcomm_ust_reply lur;
118 int ret, session_handle;
119
120 /* Create session */
121 memset(&lum, 0, sizeof(lum));
122 lum.handle = LTTNG_UST_ROOT_HANDLE;
123 lum.cmd = LTTNG_UST_SESSION;
124 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
125 if (ret)
126 return ret;
127 session_handle = lur.ret_val;
128 DBG("received session handle %u", session_handle);
129 return session_handle;
130 }
131
132 /* open the metadata global channel */
133 int ustctl_open_metadata(int sock, int session_handle,
134 struct lttng_ust_channel_attr *chops,
135 struct lttng_ust_object_data **_metadata_data)
136 {
137 struct ustcomm_ust_msg lum;
138 struct ustcomm_ust_reply lur;
139 struct lttng_ust_object_data *metadata_data;
140 int ret;
141
142 metadata_data = malloc(sizeof(*metadata_data));
143 if (!metadata_data)
144 return -ENOMEM;
145 init_object(metadata_data);
146 /* Create metadata channel */
147 memset(&lum, 0, sizeof(lum));
148 lum.handle = session_handle;
149 lum.cmd = LTTNG_UST_METADATA;
150 lum.u.channel.overwrite = chops->overwrite;
151 lum.u.channel.subbuf_size = chops->subbuf_size;
152 lum.u.channel.num_subbuf = chops->num_subbuf;
153 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
154 lum.u.channel.read_timer_interval = chops->read_timer_interval;
155 lum.u.channel.output = chops->output;
156 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
157 if (ret) {
158 free(metadata_data);
159 return ret;
160 }
161 if (lur.ret_code != USTCOMM_OK) {
162 free(metadata_data);
163 return lur.ret_code;
164 }
165 metadata_data->handle = lur.ret_val;
166 DBG("received metadata handle %u", metadata_data->handle);
167 metadata_data->memory_map_size = lur.u.channel.memory_map_size;
168 /* get shm fd */
169 ret = ustcomm_recv_fd(sock);
170 if (ret < 0)
171 goto error;
172 metadata_data->shm_fd = ret;
173 /* get wait fd */
174 ret = ustcomm_recv_fd(sock);
175 if (ret < 0)
176 goto error;
177 metadata_data->wait_fd = ret;
178 *_metadata_data = metadata_data;
179 return 0;
180
181 error:
182 (void) ustctl_release_object(sock, metadata_data);
183 free(metadata_data);
184 return -EINVAL;
185 }
186
187 int ustctl_create_channel(int sock, int session_handle,
188 struct lttng_ust_channel_attr *chops,
189 struct lttng_ust_object_data **_channel_data)
190 {
191 struct ustcomm_ust_msg lum;
192 struct ustcomm_ust_reply lur;
193 struct lttng_ust_object_data *channel_data;
194 int ret;
195
196 channel_data = malloc(sizeof(*channel_data));
197 if (!channel_data)
198 return -ENOMEM;
199 init_object(channel_data);
200 /* Create metadata channel */
201 memset(&lum, 0, sizeof(lum));
202 lum.handle = session_handle;
203 lum.cmd = LTTNG_UST_CHANNEL;
204 lum.u.channel.overwrite = chops->overwrite;
205 lum.u.channel.subbuf_size = chops->subbuf_size;
206 lum.u.channel.num_subbuf = chops->num_subbuf;
207 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
208 lum.u.channel.read_timer_interval = chops->read_timer_interval;
209 lum.u.channel.output = chops->output;
210 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
211 if (ret) {
212 free(channel_data);
213 return ret;
214 }
215 if (lur.ret_code != USTCOMM_OK) {
216 free(channel_data);
217 return lur.ret_code;
218 }
219 channel_data->handle = lur.ret_val;
220 DBG("received channel handle %u", channel_data->handle);
221 channel_data->memory_map_size = lur.u.channel.memory_map_size;
222 /* get shm fd */
223 ret = ustcomm_recv_fd(sock);
224 if (ret < 0)
225 goto error;
226 channel_data->shm_fd = ret;
227 /* get wait fd */
228 ret = ustcomm_recv_fd(sock);
229 if (ret < 0)
230 goto error;
231 channel_data->wait_fd = ret;
232 *_channel_data = channel_data;
233 return 0;
234
235 error:
236 (void) ustctl_release_object(sock, channel_data);
237 free(channel_data);
238 return -EINVAL;
239 }
240
241 /*
242 * Return -ENOENT if no more stream is available for creation.
243 * Return 0 on success.
244 * Return negative error value on error.
245 */
246 int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
247 struct lttng_ust_object_data **_stream_data)
248 {
249 struct ustcomm_ust_msg lum;
250 struct ustcomm_ust_reply lur;
251 struct lttng_ust_object_data *stream_data;
252 int ret, fd;
253
254 stream_data = malloc(sizeof(*stream_data));
255 if (!stream_data)
256 return -ENOMEM;
257 init_object(stream_data);
258 memset(&lum, 0, sizeof(lum));
259 lum.handle = channel_data->handle;
260 lum.cmd = LTTNG_UST_STREAM;
261 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
262 if (ret) {
263 free(stream_data);
264 return ret;
265 }
266 if (lur.ret_code != USTCOMM_OK) {
267 free(stream_data);
268 return lur.ret_code;
269 }
270
271 stream_data->handle = lur.ret_val;
272 DBG("received stream handle %u", stream_data->handle);
273 stream_data->memory_map_size = lur.u.stream.memory_map_size;
274 /* get shm fd */
275 fd = ustcomm_recv_fd(sock);
276 if (fd < 0)
277 goto error;
278 stream_data->shm_fd = fd;
279 /* get wait fd */
280 fd = ustcomm_recv_fd(sock);
281 if (fd < 0)
282 goto error;
283 stream_data->wait_fd = fd;
284 *_stream_data = stream_data;
285 return ret;
286
287 error:
288 (void) ustctl_release_object(sock, stream_data);
289 free(stream_data);
290 return -EINVAL;
291 }
292
293 int ustctl_create_event(int sock, struct lttng_ust_event *ev,
294 struct lttng_ust_object_data *channel_data,
295 struct lttng_ust_object_data **_event_data)
296 {
297 struct ustcomm_ust_msg lum;
298 struct ustcomm_ust_reply lur;
299 struct lttng_ust_object_data *event_data;
300 int ret;
301
302 event_data = malloc(sizeof(*event_data));
303 if (!event_data)
304 return -ENOMEM;
305 init_object(event_data);
306 memset(&lum, 0, sizeof(lum));
307 lum.handle = channel_data->handle;
308 lum.cmd = LTTNG_UST_EVENT;
309 strncpy(lum.u.event.name, ev->name,
310 LTTNG_UST_SYM_NAME_LEN);
311 lum.u.event.instrumentation = ev->instrumentation;
312 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
313 if (ret) {
314 free(event_data);
315 return ret;
316 }
317 event_data->handle = lur.ret_val;
318 DBG("received event handle %u", event_data->handle);
319 *_event_data = event_data;
320 return 0;
321 }
322
323 int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
324 struct lttng_ust_object_data *obj_data,
325 struct lttng_ust_object_data **_context_data)
326 {
327 struct ustcomm_ust_msg lum;
328 struct ustcomm_ust_reply lur;
329 struct lttng_ust_object_data *context_data;
330 int ret;
331
332 context_data = malloc(sizeof(*context_data));
333 if (!context_data)
334 return -ENOMEM;
335 init_object(context_data);
336 memset(&lum, 0, sizeof(lum));
337 lum.handle = obj_data->handle;
338 lum.cmd = LTTNG_UST_CONTEXT;
339 lum.u.context.ctx = ctx->ctx;
340 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
341 if (ret) {
342 free(context_data);
343 return ret;
344 }
345 context_data->handle = lur.ret_val;
346 DBG("received context handle %u", context_data->handle);
347 *_context_data = context_data;
348 return ret;
349 }
350
351 /* Enable event, channel and session ioctl */
352 int ustctl_enable(int sock, struct lttng_ust_object_data *object)
353 {
354 struct ustcomm_ust_msg lum;
355 struct ustcomm_ust_reply lur;
356 int ret;
357
358 memset(&lum, 0, sizeof(lum));
359 lum.handle = object->handle;
360 lum.cmd = LTTNG_UST_ENABLE;
361 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
362 if (ret)
363 return ret;
364 DBG("enabled handle %u", object->handle);
365 return 0;
366 }
367
368 /* Disable event, channel and session ioctl */
369 int ustctl_disable(int sock, struct lttng_ust_object_data *object)
370 {
371 struct ustcomm_ust_msg lum;
372 struct ustcomm_ust_reply lur;
373 int ret;
374
375 memset(&lum, 0, sizeof(lum));
376 lum.handle = object->handle;
377 lum.cmd = LTTNG_UST_DISABLE;
378 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
379 if (ret)
380 return ret;
381 DBG("disable handle %u", object->handle);
382 return 0;
383 }
384
385 int ustctl_start_session(int sock, int handle)
386 {
387 struct lttng_ust_object_data obj;
388
389 obj.handle = handle;
390 return ustctl_enable(sock, &obj);
391 }
392
393 int ustctl_stop_session(int sock, int handle)
394 {
395 struct lttng_ust_object_data obj;
396
397 obj.handle = handle;
398 return ustctl_disable(sock, &obj);
399 }
400
401 int ustctl_tracepoint_list(int sock)
402 {
403 struct ustcomm_ust_msg lum;
404 struct ustcomm_ust_reply lur;
405 int ret, tp_list_handle;
406
407 memset(&lum, 0, sizeof(lum));
408 lum.handle = LTTNG_UST_ROOT_HANDLE;
409 lum.cmd = LTTNG_UST_TRACEPOINT_LIST;
410 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
411 if (ret)
412 return ret;
413 tp_list_handle = lur.ret_val;
414 DBG("received tracepoint list handle %u", tp_list_handle);
415 return tp_list_handle;
416 }
417
418 int ustctl_tracepoint_list_get(int sock, int tp_list_handle,
419 struct lttng_ust_tracepoint_iter *iter)
420 {
421 struct ustcomm_ust_msg lum;
422 struct ustcomm_ust_reply lur;
423 int ret;
424
425 memset(&lum, 0, sizeof(lum));
426 lum.handle = tp_list_handle;
427 lum.cmd = LTTNG_UST_TRACEPOINT_LIST_GET;
428 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
429 if (ret)
430 return ret;
431 DBG("received tracepoint list entry name %s loglevel %s loglevel_value %lld",
432 lur.u.tracepoint.name,
433 lur.u.tracepoint.loglevel,
434 (unsigned long long) lur.u.tracepoint.loglevel_value);
435 memcpy(iter, &lur.u.tracepoint, sizeof(*iter));
436 return 0;
437 }
438
439 int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
440 {
441 struct ustcomm_ust_msg lum;
442 struct ustcomm_ust_reply lur;
443 int ret;
444
445 memset(&lum, 0, sizeof(lum));
446 lum.handle = LTTNG_UST_ROOT_HANDLE;
447 lum.cmd = LTTNG_UST_TRACER_VERSION;
448 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
449 if (ret)
450 return ret;
451 memcpy(v, &lur.u.version, sizeof(*v));
452 DBG("received tracer version");
453 return 0;
454 }
455
456 int ustctl_wait_quiescent(int sock)
457 {
458 struct ustcomm_ust_msg lum;
459 struct ustcomm_ust_reply lur;
460 int ret;
461
462 memset(&lum, 0, sizeof(lum));
463 lum.handle = LTTNG_UST_ROOT_HANDLE;
464 lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
465 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
466 if (ret)
467 return ret;
468 DBG("waited for quiescent state");
469 return 0;
470 }
471
472 int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
473 {
474 return -ENOSYS;
475 }
476
477 int ustctl_sock_flush_buffer(int sock, struct lttng_ust_object_data *object)
478 {
479 struct ustcomm_ust_msg lum;
480 struct ustcomm_ust_reply lur;
481 int ret;
482
483 memset(&lum, 0, sizeof(lum));
484 lum.handle = object->handle;
485 lum.cmd = LTTNG_UST_FLUSH_BUFFER;
486 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
487 if (ret)
488 return ret;
489 DBG("flushed buffer handle %u", object->handle);
490 return 0;
491 }
492
493 /* Buffer operations */
494
495 /* Map channel shm into process memory */
496 struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *chan_data)
497 {
498 struct lttng_ust_shm_handle *handle;
499 struct channel *chan;
500 size_t chan_size;
501 struct lttng_ust_lib_ring_buffer_config *config;
502 int ret;
503
504 handle = channel_handle_create(chan_data->shm_fd,
505 chan_data->wait_fd,
506 chan_data->memory_map_size);
507 if (!handle) {
508 ERR("create handle error");
509 return NULL;
510 }
511 /*
512 * Set to -1 because the lttng_ust_shm_handle destruction will take care
513 * of closing shm_fd and wait_fd.
514 */
515 chan_data->shm_fd = -1;
516 chan_data->wait_fd = -1;
517
518 /*
519 * TODO: add consistency checks to be resilient if the
520 * application try to feed us with incoherent channel structure
521 * values.
522 */
523 chan = shmp(handle, handle->chan);
524 /* chan is object 0. This is hardcoded. */
525 chan_size = handle->table->objects[0].allocated_len;
526 handle->shadow_chan = malloc(chan_size);
527 if (!handle->shadow_chan) {
528 channel_destroy(chan, handle, 1);
529 return NULL;
530 }
531 memcpy(handle->shadow_chan, chan, chan_size);
532 /*
533 * The callback pointers in the producer are invalid in the
534 * consumer. We need to look them up here.
535 */
536 config = &handle->shadow_chan->backend.config;
537 switch (config->client_type) {
538 case LTTNG_CLIENT_METADATA:
539 memcpy(&config->cb, lttng_client_callbacks_metadata,
540 sizeof(config->cb));
541 break;
542 case LTTNG_CLIENT_DISCARD:
543 memcpy(&config->cb, lttng_client_callbacks_discard,
544 sizeof(config->cb));
545 break;
546 case LTTNG_CLIENT_OVERWRITE:
547 memcpy(&config->cb, lttng_client_callbacks_overwrite,
548 sizeof(config->cb));
549 break;
550 default:
551 ERR("Unknown client type %d", config->client_type);
552 channel_destroy(chan, handle, 1);
553 return NULL;
554 }
555 /* Replace the object table pointer. */
556 ret = munmap(handle->table->objects[0].memory_map,
557 handle->table->objects[0].memory_map_size);
558 if (ret) {
559 perror("munmap");
560 assert(0);
561 }
562 handle->table->objects[0].memory_map = (char *) handle->shadow_chan;
563 handle->table->objects[0].is_shadow = 1;
564 return handle;
565 }
566
567 /* Add stream to channel shm and map its shm into process memory */
568 int ustctl_add_stream(struct lttng_ust_shm_handle *handle,
569 struct lttng_ust_object_data *stream_data)
570 {
571 int ret;
572
573 if (!stream_data->handle)
574 return -ENOENT;
575 /* map stream */
576 ret = channel_handle_add_stream(handle,
577 stream_data->shm_fd,
578 stream_data->wait_fd,
579 stream_data->memory_map_size);
580 if (ret) {
581 ERR("add stream error\n");
582 return ret;
583 }
584 /*
585 * Set to -1 because the lttng_ust_shm_handle destruction will take care
586 * of closing shm_fd and wait_fd.
587 */
588 stream_data->shm_fd = -1;
589 stream_data->wait_fd = -1;
590 return 0;
591 }
592
593 void ustctl_unmap_channel(struct lttng_ust_shm_handle *handle)
594 {
595 struct channel *chan;
596
597 chan = shmp(handle, handle->chan);
598 channel_destroy(chan, handle, 1);
599 }
600
601 struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle,
602 int cpu)
603 {
604 struct channel *chan = handle->shadow_chan;
605 int shm_fd, wait_fd;
606 uint64_t memory_map_size;
607 struct lttng_ust_lib_ring_buffer *buf;
608 int ret;
609
610 buf = channel_get_ring_buffer(&chan->backend.config,
611 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
612 if (!buf)
613 return NULL;
614 ret = lib_ring_buffer_open_read(buf, handle, 1);
615 if (ret)
616 return NULL;
617 return buf;
618 }
619
620 void ustctl_close_stream_read(struct lttng_ust_shm_handle *handle,
621 struct lttng_ust_lib_ring_buffer *buf)
622 {
623 lib_ring_buffer_release_read(buf, handle, 1);
624 }
625
626 /* For mmap mode, readable without "get" operation */
627
628 void *ustctl_get_mmap_base(struct lttng_ust_shm_handle *handle,
629 struct lttng_ust_lib_ring_buffer *buf)
630 {
631 return shmp(handle, buf->backend.memory_map);
632 }
633
634 /* returns the length to mmap. */
635 int ustctl_get_mmap_len(struct lttng_ust_shm_handle *handle,
636 struct lttng_ust_lib_ring_buffer *buf,
637 unsigned long *len)
638 {
639 unsigned long mmap_buf_len;
640 struct channel *chan = handle->shadow_chan;
641
642 if (chan->backend.config.output != RING_BUFFER_MMAP)
643 return -EINVAL;
644 mmap_buf_len = chan->backend.buf_size;
645 if (chan->backend.extra_reader_sb)
646 mmap_buf_len += chan->backend.subbuf_size;
647 if (mmap_buf_len > INT_MAX)
648 return -EFBIG;
649 *len = mmap_buf_len;
650 return 0;
651 }
652
653 /* returns the maximum size for sub-buffers. */
654 int ustctl_get_max_subbuf_size(struct lttng_ust_shm_handle *handle,
655 struct lttng_ust_lib_ring_buffer *buf,
656 unsigned long *len)
657 {
658 struct channel *chan = handle->shadow_chan;
659
660 *len = chan->backend.subbuf_size;
661 return 0;
662 }
663
664 /*
665 * For mmap mode, operate on the current packet (between get/put or
666 * get_next/put_next).
667 */
668
669 /* returns the offset of the subbuffer belonging to the mmap reader. */
670 int ustctl_get_mmap_read_offset(struct lttng_ust_shm_handle *handle,
671 struct lttng_ust_lib_ring_buffer *buf, unsigned long *off)
672 {
673 struct channel *chan = handle->shadow_chan;
674 unsigned long sb_bindex;
675
676 if (chan->backend.config.output != RING_BUFFER_MMAP)
677 return -EINVAL;
678 sb_bindex = subbuffer_id_get_index(&chan->backend.config,
679 buf->backend.buf_rsb.id);
680 *off = shmp(handle, shmp_index(handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
681 return 0;
682 }
683
684 /* returns the size of the current sub-buffer, without padding (for mmap). */
685 int ustctl_get_subbuf_size(struct lttng_ust_shm_handle *handle,
686 struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
687 {
688 struct channel *chan = handle->shadow_chan;
689
690 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
691 handle);
692 return 0;
693 }
694
695 /* returns the size of the current sub-buffer, without padding (for mmap). */
696 int ustctl_get_padded_subbuf_size(struct lttng_ust_shm_handle *handle,
697 struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
698 {
699 struct channel *chan = handle->shadow_chan;
700
701 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
702 handle);
703 *len = PAGE_ALIGN(*len);
704 return 0;
705 }
706
707 /* Get exclusive read access to the next sub-buffer that can be read. */
708 int ustctl_get_next_subbuf(struct lttng_ust_shm_handle *handle,
709 struct lttng_ust_lib_ring_buffer *buf)
710 {
711 return lib_ring_buffer_get_next_subbuf(buf, handle);
712 }
713
714
715 /* Release exclusive sub-buffer access, move consumer forward. */
716 int ustctl_put_next_subbuf(struct lttng_ust_shm_handle *handle,
717 struct lttng_ust_lib_ring_buffer *buf)
718 {
719 lib_ring_buffer_put_next_subbuf(buf, handle);
720 return 0;
721 }
722
723 /* snapshot */
724
725 /* Get a snapshot of the current ring buffer producer and consumer positions */
726 int ustctl_snapshot(struct lttng_ust_shm_handle *handle,
727 struct lttng_ust_lib_ring_buffer *buf)
728 {
729 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
730 &buf->prod_snapshot, handle);
731 }
732
733 /* Get the consumer position (iteration start) */
734 int ustctl_snapshot_get_consumed(struct lttng_ust_shm_handle *handle,
735 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
736 {
737 *pos = buf->cons_snapshot;
738 return 0;
739 }
740
741 /* Get the producer position (iteration end) */
742 int ustctl_snapshot_get_produced(struct lttng_ust_shm_handle *handle,
743 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
744 {
745 *pos = buf->prod_snapshot;
746 return 0;
747 }
748
749 /* Get exclusive read access to the specified sub-buffer position */
750 int ustctl_get_subbuf(struct lttng_ust_shm_handle *handle,
751 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
752 {
753 return lib_ring_buffer_get_subbuf(buf, *pos, handle);
754 }
755
756 /* Release exclusive sub-buffer access */
757 int ustctl_put_subbuf(struct lttng_ust_shm_handle *handle,
758 struct lttng_ust_lib_ring_buffer *buf)
759 {
760 lib_ring_buffer_put_subbuf(buf, handle);
761 return 0;
762 }
763
764 void ustctl_flush_buffer(struct lttng_ust_shm_handle *handle,
765 struct lttng_ust_lib_ring_buffer *buf,
766 int producer_active)
767 {
768 lib_ring_buffer_switch_slow(buf,
769 producer_active ? SWITCH_ACTIVE : SWITCH_FLUSH,
770 handle);
771 }
This page took 0.044198 seconds and 5 git commands to generate.