Cygwin: Generate dummy file descriptors
[lttng-ust.git] / liblttng-ust-ctl / ustctl.c
CommitLineData
57773204
MD
1/*
2 * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
e92f3e28
MD
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License only.
57773204
MD
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
e92f3e28
MD
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
57773204
MD
17 */
18
9d335227 19#define _GNU_SOURCE
57773204 20#include <string.h>
4318ae1b
MD
21#include <lttng/ust-ctl.h>
22#include <lttng/ust-abi.h>
c1fca457 23#include <lttng/ust-events.h>
7a784989 24#include <sys/mman.h>
44c72f10
MD
25
26#include <usterr-signal-safe.h>
b728d87e 27#include <ust-comm.h>
57773204
MD
28
29#include "../libringbuffer/backend.h"
30#include "../libringbuffer/frontend.h"
31
6b120308
MD
32volatile enum ust_loglevel ust_loglevel;
33
42100b84
CB
34static int dummy_pipe[2];
35
36static
37void __attribute__((constructor)) setup_dummy_pipe(void)
38{
39 pipe(dummy_pipe);
40 /* Only dummy_pipe[0] is used */
41 close(dummy_pipe[1]);
42 /* FIXME: Handle pipe() failure */
43}
44
45static
46inline int get_dummy_fd(void)
47{
48 return dup(dummy_pipe[0]);
49}
50
57773204 51static
61f02aea 52void init_object(struct lttng_ust_object_data *data)
57773204
MD
53{
54 data->handle = -1;
55 data->shm_fd = -1;
bf5ff35e 56 data->shm_path = NULL;
57773204 57 data->wait_fd = -1;
bf5ff35e 58 data->wait_pipe_path = NULL;
57773204
MD
59 data->memory_map_size = 0;
60}
61
2be0e72c
MD
62int ustctl_release_handle(int sock, int handle)
63{
64 struct ustcomm_ust_msg lum;
65 struct ustcomm_ust_reply lur;
66 int ret;
67
68 if (sock >= 0) {
69 memset(&lum, 0, sizeof(lum));
70 lum.handle = handle;
71 lum.cmd = LTTNG_UST_RELEASE;
72 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
73 if (ret < 0) {
74 return ret;
75 }
76 }
77 return 0;
78}
12388166
MD
79/*
80 * If sock is negative, it means we don't have to notify the other side
81 * (e.g. application has already vanished).
82 */
d26228ae 83int ustctl_release_object(int sock, struct lttng_ust_object_data *data)
57773204 84{
57773204
MD
85 int ret;
86
9bfc503d
MD
87 if (!data)
88 return -EINVAL;
89
d26228ae
MD
90 if (data->shm_fd >= 0) {
91 ret = close(data->shm_fd);
92 if (ret < 0) {
93 return ret;
94 }
95 }
bf5ff35e
CB
96
97 if (data->shm_path) {
98 free(data->shm_path);
99 }
100
d26228ae
MD
101 if (data->wait_fd >= 0) {
102 ret = close(data->wait_fd);
103 if (ret < 0) {
104 return ret;
105 }
106 }
bf5ff35e
CB
107
108 if (data->wait_pipe_path) {
109 free(data->wait_pipe_path);
110 }
111
2be0e72c 112 return ustctl_release_handle(sock, data->handle);
57773204
MD
113}
114
1c5e467e
MD
115/*
116 * Send registration done packet to the application.
117 */
118int ustctl_register_done(int sock)
119{
120 struct ustcomm_ust_msg lum;
121 struct ustcomm_ust_reply lur;
122 int ret;
123
124 DBG("Sending register done command to %d", sock);
125 memset(&lum, 0, sizeof(lum));
126 lum.handle = LTTNG_UST_ROOT_HANDLE;
127 lum.cmd = LTTNG_UST_REGISTER_DONE;
128 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
129 if (ret)
130 return ret;
131 if (lur.ret_code != USTCOMM_OK) {
132 DBG("Return code: %s", ustcomm_get_readable_code(lur.ret_code));
133 goto error;
134 }
135 return 0;
136
137error:
138 return -1;
139}
140
57773204
MD
141/*
142 * returns session handle.
143 */
144int ustctl_create_session(int sock)
145{
146 struct ustcomm_ust_msg lum;
147 struct ustcomm_ust_reply lur;
148 int ret, session_handle;
149
150 /* Create session */
151 memset(&lum, 0, sizeof(lum));
152 lum.handle = LTTNG_UST_ROOT_HANDLE;
153 lum.cmd = LTTNG_UST_SESSION;
154 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
155 if (ret)
156 return ret;
157 session_handle = lur.ret_val;
158 DBG("received session handle %u", session_handle);
159 return session_handle;
160}
161
162/* open the metadata global channel */
163int ustctl_open_metadata(int sock, int session_handle,
164 struct lttng_ust_channel_attr *chops,
61f02aea 165 struct lttng_ust_object_data **_metadata_data)
57773204
MD
166{
167 struct ustcomm_ust_msg lum;
168 struct ustcomm_ust_reply lur;
61f02aea 169 struct lttng_ust_object_data *metadata_data;
eeee05f3 170 int ret, err = 0;
bf5ff35e 171 char *shm_path, *wait_pipe_path;
57773204 172
9bfc503d
MD
173 if (!chops || !_metadata_data)
174 return -EINVAL;
175
57773204
MD
176 metadata_data = malloc(sizeof(*metadata_data));
177 if (!metadata_data)
178 return -ENOMEM;
179 init_object(metadata_data);
180 /* Create metadata channel */
181 memset(&lum, 0, sizeof(lum));
182 lum.handle = session_handle;
183 lum.cmd = LTTNG_UST_METADATA;
184 lum.u.channel.overwrite = chops->overwrite;
185 lum.u.channel.subbuf_size = chops->subbuf_size;
186 lum.u.channel.num_subbuf = chops->num_subbuf;
187 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
188 lum.u.channel.read_timer_interval = chops->read_timer_interval;
189 lum.u.channel.output = chops->output;
190 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
191 if (ret) {
192 free(metadata_data);
193 return ret;
194 }
195 if (lur.ret_code != USTCOMM_OK) {
196 free(metadata_data);
197 return lur.ret_code;
198 }
199 metadata_data->handle = lur.ret_val;
200 DBG("received metadata handle %u", metadata_data->handle);
201 metadata_data->memory_map_size = lur.u.channel.memory_map_size;
bf5ff35e
CB
202 /* get shm path */
203 shm_path = ustcomm_recv_string(sock);
204 if (!shm_path) {
eeee05f3 205 err = 1;
bf5ff35e
CB
206 } else {
207 DBG("Received shm path: %s\n", shm_path);
42100b84 208 metadata_data->shm_fd = get_dummy_fd();
bf5ff35e
CB
209 metadata_data->shm_path = shm_path;
210 }
211
eeee05f3
MD
212 /*
213 * We need to get the second FD even if the first fails, because
214 * libust expects us to read the two FDs.
215 */
bf5ff35e
CB
216
217 /* get wait pipe path */
218 wait_pipe_path = ustcomm_recv_string(sock);
219 if (!wait_pipe_path) {
220 free(shm_path);
eeee05f3 221 err = 1;
bf5ff35e
CB
222 } else {
223 DBG("Received wait pipe path: %s\n", wait_pipe_path);
42100b84 224 metadata_data->wait_fd = get_dummy_fd();
bf5ff35e
CB
225 metadata_data->wait_pipe_path = wait_pipe_path;
226 }
227
228
eeee05f3 229 if (err)
57773204 230 goto error;
57773204
MD
231 *_metadata_data = metadata_data;
232 return 0;
233
234error:
d26228ae 235 (void) ustctl_release_object(sock, metadata_data);
38970582 236 free(metadata_data);
57773204
MD
237 return -EINVAL;
238}
239
240int ustctl_create_channel(int sock, int session_handle,
241 struct lttng_ust_channel_attr *chops,
61f02aea 242 struct lttng_ust_object_data **_channel_data)
57773204
MD
243{
244 struct ustcomm_ust_msg lum;
245 struct ustcomm_ust_reply lur;
61f02aea 246 struct lttng_ust_object_data *channel_data;
eeee05f3 247 int ret, err = 0;
bf5ff35e 248 char *shm_path, *wait_pipe_path;
57773204 249
9bfc503d
MD
250 if (!chops || !_channel_data)
251 return -EINVAL;
252
57773204
MD
253 channel_data = malloc(sizeof(*channel_data));
254 if (!channel_data)
255 return -ENOMEM;
256 init_object(channel_data);
257 /* Create metadata channel */
258 memset(&lum, 0, sizeof(lum));
259 lum.handle = session_handle;
260 lum.cmd = LTTNG_UST_CHANNEL;
261 lum.u.channel.overwrite = chops->overwrite;
262 lum.u.channel.subbuf_size = chops->subbuf_size;
263 lum.u.channel.num_subbuf = chops->num_subbuf;
264 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
265 lum.u.channel.read_timer_interval = chops->read_timer_interval;
266 lum.u.channel.output = chops->output;
267 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
268 if (ret) {
269 free(channel_data);
270 return ret;
271 }
272 if (lur.ret_code != USTCOMM_OK) {
273 free(channel_data);
274 return lur.ret_code;
275 }
276 channel_data->handle = lur.ret_val;
277 DBG("received channel handle %u", channel_data->handle);
278 channel_data->memory_map_size = lur.u.channel.memory_map_size;
bf5ff35e
CB
279 /* get shm path */
280 shm_path = ustcomm_recv_string(sock);
281 if (!shm_path) {
eeee05f3 282 err = 1;
bf5ff35e
CB
283 } else {
284 DBG("Received shm path: %s\n", shm_path);
42100b84 285 channel_data->shm_fd = get_dummy_fd();
bf5ff35e
CB
286 channel_data->shm_path = shm_path;
287 }
288
eeee05f3
MD
289 /*
290 * We need to get the second FD even if the first fails, because
291 * libust expects us to read the two FDs.
292 */
bf5ff35e
CB
293 /* get wait pipe path */
294 wait_pipe_path = ustcomm_recv_string(sock);
295 if (!wait_pipe_path) {
296 free(shm_path);
eeee05f3 297 err = 1;
bf5ff35e
CB
298 } else {
299 DBG("Received wait pipe path: %s\n", wait_pipe_path);
42100b84 300 channel_data->wait_fd = get_dummy_fd();
bf5ff35e
CB
301 channel_data->wait_pipe_path = wait_pipe_path;
302 }
303
eeee05f3 304 if (err)
57773204 305 goto error;
57773204
MD
306 *_channel_data = channel_data;
307 return 0;
308
309error:
d26228ae 310 (void) ustctl_release_object(sock, channel_data);
38970582 311 free(channel_data);
57773204
MD
312 return -EINVAL;
313}
314
315/*
316 * Return -ENOENT if no more stream is available for creation.
317 * Return 0 on success.
318 * Return negative error value on error.
319 */
61f02aea
MD
320int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
321 struct lttng_ust_object_data **_stream_data)
57773204
MD
322{
323 struct ustcomm_ust_msg lum;
324 struct ustcomm_ust_reply lur;
61f02aea 325 struct lttng_ust_object_data *stream_data;
bf5ff35e
CB
326 int ret, err = 0;
327 char *shm_path, *wait_pipe_path;
57773204 328
9bfc503d
MD
329 if (!channel_data || !_stream_data)
330 return -EINVAL;
331
57773204
MD
332 stream_data = malloc(sizeof(*stream_data));
333 if (!stream_data)
334 return -ENOMEM;
335 init_object(stream_data);
336 memset(&lum, 0, sizeof(lum));
337 lum.handle = channel_data->handle;
338 lum.cmd = LTTNG_UST_STREAM;
339 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
340 if (ret) {
341 free(stream_data);
342 return ret;
343 }
344 if (lur.ret_code != USTCOMM_OK) {
345 free(stream_data);
346 return lur.ret_code;
347 }
348
349 stream_data->handle = lur.ret_val;
350 DBG("received stream handle %u", stream_data->handle);
351 stream_data->memory_map_size = lur.u.stream.memory_map_size;
bf5ff35e
CB
352 /* get shm path */
353 shm_path = ustcomm_recv_string(sock);
354 if (!shm_path) {
eeee05f3 355 err = 1;
bf5ff35e
CB
356 } else {
357 DBG("Received shm path: %s\n", shm_path);
42100b84 358 stream_data->shm_fd = get_dummy_fd();
bf5ff35e
CB
359 stream_data->shm_path = shm_path;
360 }
361
eeee05f3
MD
362 /*
363 * We need to get the second FD even if the first fails, because
364 * libust expects us to read the two FDs.
365 */
bf5ff35e
CB
366 /* get wait pipe path */
367 wait_pipe_path = ustcomm_recv_string(sock);
368 if (!wait_pipe_path) {
369 free(shm_path);
eeee05f3 370 err = 1;
bf5ff35e
CB
371 } else {
372 DBG("Received wait pipe path: %s\n", wait_pipe_path);
42100b84 373 stream_data->wait_fd = get_dummy_fd();
bf5ff35e
CB
374 stream_data->wait_pipe_path = wait_pipe_path;
375 }
376
eeee05f3 377 if (err)
57773204 378 goto error;
57773204
MD
379 *_stream_data = stream_data;
380 return ret;
381
382error:
d26228ae 383 (void) ustctl_release_object(sock, stream_data);
38970582 384 free(stream_data);
57773204
MD
385 return -EINVAL;
386}
387
388int ustctl_create_event(int sock, struct lttng_ust_event *ev,
61f02aea
MD
389 struct lttng_ust_object_data *channel_data,
390 struct lttng_ust_object_data **_event_data)
57773204
MD
391{
392 struct ustcomm_ust_msg lum;
393 struct ustcomm_ust_reply lur;
61f02aea 394 struct lttng_ust_object_data *event_data;
57773204
MD
395 int ret;
396
9bfc503d
MD
397 if (!channel_data || !_event_data)
398 return -EINVAL;
399
57773204
MD
400 event_data = malloc(sizeof(*event_data));
401 if (!event_data)
402 return -ENOMEM;
403 init_object(event_data);
404 memset(&lum, 0, sizeof(lum));
405 lum.handle = channel_data->handle;
406 lum.cmd = LTTNG_UST_EVENT;
407 strncpy(lum.u.event.name, ev->name,
408 LTTNG_UST_SYM_NAME_LEN);
409 lum.u.event.instrumentation = ev->instrumentation;
457a6b58
MD
410 lum.u.event.loglevel_type = ev->loglevel_type;
411 lum.u.event.loglevel = ev->loglevel;
57773204
MD
412 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
413 if (ret) {
414 free(event_data);
415 return ret;
416 }
417 event_data->handle = lur.ret_val;
418 DBG("received event handle %u", event_data->handle);
419 *_event_data = event_data;
420 return 0;
421}
422
423int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
61f02aea
MD
424 struct lttng_ust_object_data *obj_data,
425 struct lttng_ust_object_data **_context_data)
57773204
MD
426{
427 struct ustcomm_ust_msg lum;
428 struct ustcomm_ust_reply lur;
61f02aea 429 struct lttng_ust_object_data *context_data;
57773204
MD
430 int ret;
431
9bfc503d
MD
432 if (!obj_data || !_context_data)
433 return -EINVAL;
434
57773204
MD
435 context_data = malloc(sizeof(*context_data));
436 if (!context_data)
437 return -ENOMEM;
438 init_object(context_data);
439 memset(&lum, 0, sizeof(lum));
3039d8ed 440 lum.handle = obj_data->handle;
57773204
MD
441 lum.cmd = LTTNG_UST_CONTEXT;
442 lum.u.context.ctx = ctx->ctx;
443 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
444 if (ret) {
445 free(context_data);
446 return ret;
447 }
448 context_data->handle = lur.ret_val;
449 DBG("received context handle %u", context_data->handle);
450 *_context_data = context_data;
451 return ret;
452}
453
454/* Enable event, channel and session ioctl */
61f02aea 455int ustctl_enable(int sock, struct lttng_ust_object_data *object)
57773204
MD
456{
457 struct ustcomm_ust_msg lum;
458 struct ustcomm_ust_reply lur;
459 int ret;
460
9bfc503d
MD
461 if (!object)
462 return -EINVAL;
463
57773204
MD
464 memset(&lum, 0, sizeof(lum));
465 lum.handle = object->handle;
466 lum.cmd = LTTNG_UST_ENABLE;
467 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
468 if (ret)
469 return ret;
470 DBG("enabled handle %u", object->handle);
471 return 0;
472}
473
474/* Disable event, channel and session ioctl */
61f02aea 475int ustctl_disable(int sock, struct lttng_ust_object_data *object)
57773204
MD
476{
477 struct ustcomm_ust_msg lum;
478 struct ustcomm_ust_reply lur;
479 int ret;
480
9bfc503d
MD
481 if (!object)
482 return -EINVAL;
483
57773204
MD
484 memset(&lum, 0, sizeof(lum));
485 lum.handle = object->handle;
486 lum.cmd = LTTNG_UST_DISABLE;
487 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
488 if (ret)
489 return ret;
490 DBG("disable handle %u", object->handle);
491 return 0;
492}
493
4a6ca058 494int ustctl_start_session(int sock, int handle)
57773204 495{
61f02aea 496 struct lttng_ust_object_data obj;
4a6ca058
MD
497
498 obj.handle = handle;
499 return ustctl_enable(sock, &obj);
57773204
MD
500}
501
4a6ca058 502int ustctl_stop_session(int sock, int handle)
57773204 503{
61f02aea 504 struct lttng_ust_object_data obj;
4a6ca058
MD
505
506 obj.handle = handle;
507 return ustctl_disable(sock, &obj);
57773204
MD
508}
509
57773204
MD
510int ustctl_tracepoint_list(int sock)
511{
b115631f
MD
512 struct ustcomm_ust_msg lum;
513 struct ustcomm_ust_reply lur;
514 int ret, tp_list_handle;
515
516 memset(&lum, 0, sizeof(lum));
517 lum.handle = LTTNG_UST_ROOT_HANDLE;
518 lum.cmd = LTTNG_UST_TRACEPOINT_LIST;
519 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
520 if (ret)
521 return ret;
522 tp_list_handle = lur.ret_val;
523 DBG("received tracepoint list handle %u", tp_list_handle);
524 return tp_list_handle;
525}
526
527int ustctl_tracepoint_list_get(int sock, int tp_list_handle,
cbef6901 528 struct lttng_ust_tracepoint_iter *iter)
b115631f
MD
529{
530 struct ustcomm_ust_msg lum;
531 struct ustcomm_ust_reply lur;
532 int ret;
533
9bfc503d
MD
534 if (!iter)
535 return -EINVAL;
536
b115631f
MD
537 memset(&lum, 0, sizeof(lum));
538 lum.handle = tp_list_handle;
539 lum.cmd = LTTNG_UST_TRACEPOINT_LIST_GET;
540 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
541 if (ret)
542 return ret;
882a56d7 543 DBG("received tracepoint list entry name %s loglevel %d",
cbef6901 544 lur.u.tracepoint.name,
882a56d7 545 lur.u.tracepoint.loglevel);
cbef6901 546 memcpy(iter, &lur.u.tracepoint, sizeof(*iter));
b115631f 547 return 0;
57773204
MD
548}
549
550int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
551{
552 struct ustcomm_ust_msg lum;
553 struct ustcomm_ust_reply lur;
554 int ret;
555
9bfc503d
MD
556 if (!v)
557 return -EINVAL;
558
57773204
MD
559 memset(&lum, 0, sizeof(lum));
560 lum.handle = LTTNG_UST_ROOT_HANDLE;
561 lum.cmd = LTTNG_UST_TRACER_VERSION;
562 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
563 if (ret)
564 return ret;
565 memcpy(v, &lur.u.version, sizeof(*v));
566 DBG("received tracer version");
567 return 0;
568}
569
570int ustctl_wait_quiescent(int sock)
571{
572 struct ustcomm_ust_msg lum;
573 struct ustcomm_ust_reply lur;
574 int ret;
575
576 memset(&lum, 0, sizeof(lum));
577 lum.handle = LTTNG_UST_ROOT_HANDLE;
578 lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
579 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
580 if (ret)
581 return ret;
582 DBG("waited for quiescent state");
583 return 0;
584}
585
586int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
587{
9bfc503d
MD
588 if (!calibrate)
589 return -EINVAL;
590
57773204
MD
591 return -ENOSYS;
592}
593
f1fffc57
MD
594int ustctl_sock_flush_buffer(int sock, struct lttng_ust_object_data *object)
595{
596 struct ustcomm_ust_msg lum;
597 struct ustcomm_ust_reply lur;
598 int ret;
599
9bfc503d
MD
600 if (!object)
601 return -EINVAL;
602
f1fffc57
MD
603 memset(&lum, 0, sizeof(lum));
604 lum.handle = object->handle;
605 lum.cmd = LTTNG_UST_FLUSH_BUFFER;
606 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
607 if (ret)
608 return ret;
609 DBG("flushed buffer handle %u", object->handle);
610 return 0;
611}
612
57773204
MD
613/* Buffer operations */
614
615/* Map channel shm into process memory */
38fae1d3 616struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *chan_data)
57773204 617{
38fae1d3 618 struct lttng_ust_shm_handle *handle;
57773204
MD
619 struct channel *chan;
620 size_t chan_size;
c1fca457 621 struct lttng_ust_lib_ring_buffer_config *config;
7a784989 622 int ret;
57773204 623
9bfc503d
MD
624 if (!chan_data)
625 return NULL;
626
57773204
MD
627 handle = channel_handle_create(chan_data->shm_fd,
628 chan_data->wait_fd,
629 chan_data->memory_map_size);
630 if (!handle) {
631 ERR("create handle error");
632 return NULL;
633 }
634 /*
0bfe09ec
MD
635 * Set to -1, and then close the shm fd, and set the handle shm
636 * fd to -1 too. We don't need the shm fds after they have been
637 * mapped.
638 * The wait_fd is set to -1 in chan_data because it is now owned
639 * by the handle.
57773204
MD
640 */
641 chan_data->shm_fd = -1;
642 chan_data->wait_fd = -1;
643
0bfe09ec
MD
644 /* chan is object 0. This is hardcoded. */
645 if (handle->table->objects[0].shm_fd >= 0) {
646 ret = close(handle->table->objects[0].shm_fd);
647 if (ret) {
648 perror("Error closing shm_fd");
649 }
650 handle->table->objects[0].shm_fd = -1;
651 }
652
57773204
MD
653 /*
654 * TODO: add consistency checks to be resilient if the
655 * application try to feed us with incoherent channel structure
656 * values.
657 */
658 chan = shmp(handle, handle->chan);
659 /* chan is object 0. This is hardcoded. */
660 chan_size = handle->table->objects[0].allocated_len;
661 handle->shadow_chan = malloc(chan_size);
662 if (!handle->shadow_chan) {
663 channel_destroy(chan, handle, 1);
664 return NULL;
665 }
666 memcpy(handle->shadow_chan, chan, chan_size);
bbc70d1b
MD
667 /*
668 * The callback pointers in the producer are invalid in the
c1fca457 669 * consumer. We need to look them up here.
bbc70d1b 670 */
c1fca457
MD
671 config = &handle->shadow_chan->backend.config;
672 switch (config->client_type) {
673 case LTTNG_CLIENT_METADATA:
674 memcpy(&config->cb, lttng_client_callbacks_metadata,
675 sizeof(config->cb));
676 break;
677 case LTTNG_CLIENT_DISCARD:
678 memcpy(&config->cb, lttng_client_callbacks_discard,
679 sizeof(config->cb));
680 break;
681 case LTTNG_CLIENT_OVERWRITE:
682 memcpy(&config->cb, lttng_client_callbacks_overwrite,
683 sizeof(config->cb));
684 break;
685 default:
686 ERR("Unknown client type %d", config->client_type);
687 channel_destroy(chan, handle, 1);
688 return NULL;
689 }
7a784989
MD
690 /* Replace the object table pointer. */
691 ret = munmap(handle->table->objects[0].memory_map,
692 handle->table->objects[0].memory_map_size);
693 if (ret) {
694 perror("munmap");
695 assert(0);
696 }
697 handle->table->objects[0].memory_map = (char *) handle->shadow_chan;
698 handle->table->objects[0].is_shadow = 1;
57773204
MD
699 return handle;
700}
701
702/* Add stream to channel shm and map its shm into process memory */
38fae1d3 703int ustctl_add_stream(struct lttng_ust_shm_handle *handle,
61f02aea 704 struct lttng_ust_object_data *stream_data)
57773204
MD
705{
706 int ret;
707
9bfc503d
MD
708 if (!handle || !stream_data)
709 return -EINVAL;
710
57773204
MD
711 if (!stream_data->handle)
712 return -ENOENT;
713 /* map stream */
714 ret = channel_handle_add_stream(handle,
715 stream_data->shm_fd,
716 stream_data->wait_fd,
717 stream_data->memory_map_size);
718 if (ret) {
719 ERR("add stream error\n");
720 return ret;
721 }
722 /*
38fae1d3 723 * Set to -1 because the lttng_ust_shm_handle destruction will take care
57773204
MD
724 * of closing shm_fd and wait_fd.
725 */
726 stream_data->shm_fd = -1;
727 stream_data->wait_fd = -1;
728 return 0;
729}
730
38fae1d3 731void ustctl_unmap_channel(struct lttng_ust_shm_handle *handle)
5224b5c8
MD
732{
733 struct channel *chan;
734
9bfc503d 735 assert(handle);
5224b5c8
MD
736 chan = shmp(handle, handle->chan);
737 channel_destroy(chan, handle, 1);
738}
739
0bfe09ec
MD
740/*
741 * ustctl closes the shm_fd fds after mapping it.
742 */
4cfec15c 743struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle,
6e922b24
MD
744 int cpu)
745{
36860b65 746 struct channel *chan;
ef9ff354 747 int *shm_fd, *wait_fd;
bf5ff35e 748 char *shm_path, *wait_pipe_path;
ef9ff354 749 uint64_t *memory_map_size;
4cfec15c 750 struct lttng_ust_lib_ring_buffer *buf;
6e922b24
MD
751 int ret;
752
9bfc503d
MD
753 if (!handle)
754 return NULL;
755
36860b65 756 chan = handle->shadow_chan;
6e922b24 757 buf = channel_get_ring_buffer(&chan->backend.config,
bf5ff35e
CB
758 chan, cpu, handle,
759 &shm_fd, &shm_path,
760 &wait_fd, &wait_pipe_path,
761 &memory_map_size);
6e922b24
MD
762 if (!buf)
763 return NULL;
764 ret = lib_ring_buffer_open_read(buf, handle, 1);
765 if (ret)
766 return NULL;
0bfe09ec
MD
767 /*
768 * We can close shm_fd early, right after is has been mapped.
769 */
770 if (*shm_fd >= 0) {
771 ret = close(*shm_fd);
772 if (ret) {
773 perror("Error closing shm_fd");
774 }
775 *shm_fd = -1;
776 }
6e922b24
MD
777 return buf;
778}
779
38fae1d3 780void ustctl_close_stream_read(struct lttng_ust_shm_handle *handle,
4cfec15c 781 struct lttng_ust_lib_ring_buffer *buf)
6e922b24 782{
9bfc503d 783 assert(handle && buf);
6e922b24
MD
784 lib_ring_buffer_release_read(buf, handle, 1);
785}
786
57773204
MD
787/* For mmap mode, readable without "get" operation */
788
38fae1d3 789void *ustctl_get_mmap_base(struct lttng_ust_shm_handle *handle,
4cfec15c 790 struct lttng_ust_lib_ring_buffer *buf)
9095efe9 791{
9bfc503d
MD
792 if (!handle || !buf)
793 return NULL;
9095efe9
MD
794 return shmp(handle, buf->backend.memory_map);
795}
796
57773204 797/* returns the length to mmap. */
38fae1d3 798int ustctl_get_mmap_len(struct lttng_ust_shm_handle *handle,
4cfec15c 799 struct lttng_ust_lib_ring_buffer *buf,
57773204
MD
800 unsigned long *len)
801{
802 unsigned long mmap_buf_len;
36860b65 803 struct channel *chan;
57773204 804
9bfc503d
MD
805 if (!handle || !buf || !len)
806 return -EINVAL;
807
36860b65 808 chan = handle->shadow_chan;
57773204
MD
809 if (chan->backend.config.output != RING_BUFFER_MMAP)
810 return -EINVAL;
811 mmap_buf_len = chan->backend.buf_size;
812 if (chan->backend.extra_reader_sb)
813 mmap_buf_len += chan->backend.subbuf_size;
814 if (mmap_buf_len > INT_MAX)
815 return -EFBIG;
816 *len = mmap_buf_len;
817 return 0;
818}
819
820/* returns the maximum size for sub-buffers. */
38fae1d3 821int ustctl_get_max_subbuf_size(struct lttng_ust_shm_handle *handle,
4cfec15c 822 struct lttng_ust_lib_ring_buffer *buf,
57773204
MD
823 unsigned long *len)
824{
36860b65 825 struct channel *chan;
57773204 826
9bfc503d
MD
827 if (!handle || !buf || !len)
828 return -EINVAL;
829
36860b65 830 chan = handle->shadow_chan;
57773204
MD
831 *len = chan->backend.subbuf_size;
832 return 0;
833}
834
835/*
836 * For mmap mode, operate on the current packet (between get/put or
837 * get_next/put_next).
838 */
839
840/* returns the offset of the subbuffer belonging to the mmap reader. */
38fae1d3 841int ustctl_get_mmap_read_offset(struct lttng_ust_shm_handle *handle,
4cfec15c 842 struct lttng_ust_lib_ring_buffer *buf, unsigned long *off)
57773204 843{
36860b65 844 struct channel *chan;
57773204
MD
845 unsigned long sb_bindex;
846
9bfc503d
MD
847 if (!handle || !buf || !off)
848 return -EINVAL;
849
36860b65 850 chan = handle->shadow_chan;
57773204
MD
851 if (chan->backend.config.output != RING_BUFFER_MMAP)
852 return -EINVAL;
853 sb_bindex = subbuffer_id_get_index(&chan->backend.config,
854 buf->backend.buf_rsb.id);
855 *off = shmp(handle, shmp_index(handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
856 return 0;
857}
858
859/* returns the size of the current sub-buffer, without padding (for mmap). */
38fae1d3 860int ustctl_get_subbuf_size(struct lttng_ust_shm_handle *handle,
4cfec15c 861 struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
57773204 862{
36860b65 863 struct channel *chan;
57773204 864
9bfc503d
MD
865 if (!handle || !buf || !len)
866 return -EINVAL;
867
36860b65 868 chan = handle->shadow_chan;
57773204
MD
869 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
870 handle);
871 return 0;
872}
873
874/* returns the size of the current sub-buffer, without padding (for mmap). */
38fae1d3 875int ustctl_get_padded_subbuf_size(struct lttng_ust_shm_handle *handle,
4cfec15c 876 struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
57773204 877{
36860b65 878 struct channel *chan;
57773204 879
9bfc503d
MD
880 if (!handle || !buf || !len)
881 return -EINVAL;
882
36860b65 883 chan = handle->shadow_chan;
57773204
MD
884 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
885 handle);
886 *len = PAGE_ALIGN(*len);
887 return 0;
888}
889
890/* Get exclusive read access to the next sub-buffer that can be read. */
38fae1d3 891int ustctl_get_next_subbuf(struct lttng_ust_shm_handle *handle,
4cfec15c 892 struct lttng_ust_lib_ring_buffer *buf)
57773204 893{
9bfc503d
MD
894 if (!handle || !buf)
895 return -EINVAL;
896
57773204
MD
897 return lib_ring_buffer_get_next_subbuf(buf, handle);
898}
899
900
901/* Release exclusive sub-buffer access, move consumer forward. */
38fae1d3 902int ustctl_put_next_subbuf(struct lttng_ust_shm_handle *handle,
4cfec15c 903 struct lttng_ust_lib_ring_buffer *buf)
57773204 904{
9bfc503d
MD
905 if (!handle || !buf)
906 return -EINVAL;
907
57773204
MD
908 lib_ring_buffer_put_next_subbuf(buf, handle);
909 return 0;
910}
911
912/* snapshot */
913
914/* Get a snapshot of the current ring buffer producer and consumer positions */
38fae1d3 915int ustctl_snapshot(struct lttng_ust_shm_handle *handle,
4cfec15c 916 struct lttng_ust_lib_ring_buffer *buf)
57773204 917{
9bfc503d
MD
918 if (!handle || !buf)
919 return -EINVAL;
920
57773204
MD
921 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
922 &buf->prod_snapshot, handle);
923}
924
925/* Get the consumer position (iteration start) */
38fae1d3 926int ustctl_snapshot_get_consumed(struct lttng_ust_shm_handle *handle,
4cfec15c 927 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
57773204 928{
9bfc503d
MD
929 if (!handle || !buf || !pos)
930 return -EINVAL;
931
57773204
MD
932 *pos = buf->cons_snapshot;
933 return 0;
934}
935
936/* Get the producer position (iteration end) */
38fae1d3 937int ustctl_snapshot_get_produced(struct lttng_ust_shm_handle *handle,
4cfec15c 938 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
57773204 939{
9bfc503d
MD
940 if (!handle || !buf || !pos)
941 return -EINVAL;
942
57773204
MD
943 *pos = buf->prod_snapshot;
944 return 0;
945}
946
947/* Get exclusive read access to the specified sub-buffer position */
38fae1d3 948int ustctl_get_subbuf(struct lttng_ust_shm_handle *handle,
4cfec15c 949 struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
57773204 950{
9bfc503d
MD
951 if (!handle || !buf || !pos)
952 return -EINVAL;
953
57773204
MD
954 return lib_ring_buffer_get_subbuf(buf, *pos, handle);
955}
956
957/* Release exclusive sub-buffer access */
38fae1d3 958int ustctl_put_subbuf(struct lttng_ust_shm_handle *handle,
4cfec15c 959 struct lttng_ust_lib_ring_buffer *buf)
57773204 960{
9bfc503d
MD
961 if (!handle || !buf)
962 return -EINVAL;
963
57773204
MD
964 lib_ring_buffer_put_subbuf(buf, handle);
965 return 0;
966}
967
02a15cfb 968void ustctl_flush_buffer(struct lttng_ust_shm_handle *handle,
b52190f2
MD
969 struct lttng_ust_lib_ring_buffer *buf,
970 int producer_active)
57773204 971{
9bfc503d 972 assert(handle && buf);
b52190f2
MD
973 lib_ring_buffer_switch_slow(buf,
974 producer_active ? SWITCH_ACTIVE : SWITCH_FLUSH,
975 handle);
57773204 976}
This page took 0.068947 seconds and 4 git commands to generate.