Replace explicit rcu_read_lock/unlock with lttng::urcu::read_lock_guard
[lttng-tools.git] / src / common / compat / poll.cpp
CommitLineData
5eb91c98 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
ab5be9fa 3 * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
5eb91c98 4 *
c922647d 5 * SPDX-License-Identifier: LGPL-2.1-only
5eb91c98 6 *
5eb91c98
DG
7 */
8
6c1c0768 9#define _LGPL_SOURCE
28ab034a 10#include "poll.hpp"
5eb91c98 11
c9e313bc
SM
12#include <common/defaults.hpp>
13#include <common/error.hpp>
14#include <common/macros.hpp>
15#include <common/utils.hpp>
5eb91c98 16
28ab034a
JG
17#include <stdbool.h>
18#include <stdlib.h>
5eb91c98 19
ce7fc42f 20#ifdef HAVE_EPOLL
0060607b
MJ
21
22#include <fcntl.h>
23#include <limits.h>
0060607b 24#include <sys/stat.h>
28ab034a 25#include <sys/types.h>
0060607b
MJ
26#include <unistd.h>
27
28/*
29 * Maximum number of fd we can monitor.
30 *
31 * For epoll(7), /proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28) will
32 * be used for the maximum size of the poll set. If this interface is not
33 * available, according to the manpage, the max_user_watches value is 1/25 (4%)
34 * of the available low memory divided by the registration cost in bytes which
35 * is 90 bytes on a 32-bit kernel and 160 bytes on a 64-bit kernel.
36 *
37 */
38static unsigned int poll_max_size;
39
40/*
41 * Resize the epoll events structure of the new size.
42 *
43 * Return 0 on success or else -1 with the current events pointer untouched.
44 */
28ab034a 45static int resize_poll_event(struct lttng_poll_event *events, uint32_t new_size)
0060607b
MJ
46{
47 struct epoll_event *ptr;
48
a0377dfe 49 LTTNG_ASSERT(events);
0060607b 50
740da7d5 51 ptr = (epoll_event *) realloc(events->events, new_size * sizeof(*ptr));
cd9adb8b 52 if (ptr == nullptr) {
0060607b
MJ
53 PERROR("realloc epoll add");
54 goto error;
55 }
56 if (new_size > events->alloc_size) {
57 /* Zero newly allocated memory */
28ab034a 58 memset(ptr + events->alloc_size, 0, (new_size - events->alloc_size) * sizeof(*ptr));
0060607b
MJ
59 }
60 events->events = ptr;
61 events->alloc_size = new_size;
62
63 return 0;
64
65error:
66 return -1;
67}
68
69/*
70 * Create epoll set and allocate returned events structure.
71 */
64803277 72int compat_epoll_create(struct lttng_poll_event *events, int count, int flags)
0060607b
MJ
73{
74 int ret;
75
cd9adb8b 76 if (events == nullptr || count <= 0) {
0060607b
MJ
77 goto error;
78 }
79
80 if (!poll_max_size) {
81 if (lttng_poll_set_max_size()) {
82 goto error;
83 }
84 }
85
86 /* Don't bust the limit here */
64803277
SM
87 if (count > poll_max_size) {
88 count = poll_max_size;
0060607b
MJ
89 }
90
64803277 91 ret = compat_glibc_epoll_create(count, flags);
0060607b
MJ
92 if (ret < 0) {
93 /* At this point, every error is fatal */
94 PERROR("epoll_create1");
95 goto error;
96 }
97
98 events->epfd = ret;
99
100 /* This *must* be freed by using lttng_poll_free() */
64803277 101 events->events = calloc<epoll_event>(count);
cd9adb8b 102 if (events->events == nullptr) {
0060607b
MJ
103 PERROR("zmalloc epoll set");
104 goto error_close;
105 }
106
64803277 107 events->alloc_size = events->init_size = count;
0060607b
MJ
108 events->nb_fd = 0;
109
110 return 0;
111
112error_close:
113 ret = close(events->epfd);
114 if (ret) {
115 PERROR("close");
116 }
117error:
118 return -1;
119}
120
121/*
122 * Add a fd to the epoll set with requesting events.
123 */
0060607b
MJ
124int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
125{
126 int ret;
127 struct epoll_event ev;
128
cd9adb8b 129 if (events == nullptr || events->events == nullptr || fd < 0) {
0060607b
MJ
130 ERR("Bad compat epoll add arguments");
131 goto error;
132 }
133
134 /*
135 * Zero struct epoll_event to ensure all representations of its
136 * union are zeroed.
137 */
138 memset(&ev, 0, sizeof(ev));
139 ev.events = req_events;
140 ev.data.fd = fd;
141
142 ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
143 if (ret < 0) {
144 switch (errno) {
145 case EEXIST:
146 /* If exist, it's OK. */
147 goto end;
148 case ENOSPC:
149 case EPERM:
150 /* Print PERROR and goto end not failing. Show must go on. */
151 PERROR("epoll_ctl ADD");
152 goto end;
153 default:
154 PERROR("epoll_ctl ADD fatal");
155 goto error;
156 }
157 }
158
159 events->nb_fd++;
160
161end:
162 return 0;
163
164error:
165 return -1;
166}
167
168/*
169 * Remove a fd from the epoll set.
170 */
0060607b
MJ
171int compat_epoll_del(struct lttng_poll_event *events, int fd)
172{
173 int ret;
174
cd9adb8b 175 if (events == nullptr || fd < 0 || events->nb_fd == 0) {
0060607b
MJ
176 goto error;
177 }
178
cd9adb8b 179 ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, nullptr);
0060607b
MJ
180 if (ret < 0) {
181 switch (errno) {
182 case ENOENT:
183 case EPERM:
184 /* Print PERROR and goto end not failing. Show must go on. */
185 PERROR("epoll_ctl DEL");
186 goto end;
187 default:
188 PERROR("epoll_ctl DEL fatal");
189 goto error;
190 }
191 }
192
193 events->nb_fd--;
194
195end:
196 return 0;
197
198error:
199 return -1;
200}
201
202/*
203 * Set an fd's events.
204 */
0060607b
MJ
205int compat_epoll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
206{
207 int ret;
208 struct epoll_event ev;
209
cd9adb8b 210 if (events == nullptr || fd < 0 || events->nb_fd == 0) {
0060607b
MJ
211 goto error;
212 }
213
214 /*
215 * Zero struct epoll_event to ensure all representations of its
216 * union are zeroed.
217 */
218 memset(&ev, 0, sizeof(ev));
219 ev.events = req_events;
220 ev.data.fd = fd;
221
222 ret = epoll_ctl(events->epfd, EPOLL_CTL_MOD, fd, &ev);
223 if (ret < 0) {
224 switch (errno) {
225 case ENOENT:
226 case EPERM:
227 /* Print PERROR and goto end not failing. Show must go on. */
228 PERROR("epoll_ctl MOD");
229 goto end;
230 default:
231 PERROR("epoll_ctl MOD fatal");
232 goto error;
233 }
234 }
235
236end:
237 return 0;
238
239error:
240 return -1;
241}
242
243/*
244 * Wait on epoll set. This is a blocking call of timeout value.
245 */
28ab034a 246int compat_epoll_wait(struct lttng_poll_event *events, int timeout, bool interruptible)
0060607b
MJ
247{
248 int ret;
249 uint32_t new_size;
250
cd9adb8b 251 if (events == nullptr || events->events == nullptr) {
0060607b
MJ
252 ERR("Wrong arguments in compat_epoll_wait");
253 goto error;
254 }
255
256 if (events->nb_fd == 0) {
257 errno = EINVAL;
258 return -1;
259 }
260
261 /*
262 * Resize if needed before waiting. We could either expand the array or
263 * shrink it down. It's important to note that after this step, we are
264 * ensured that the events argument of the epoll_wait call will be large
265 * enough to hold every possible returned events.
266 */
267 new_size = 1U << utils_get_count_order_u32(events->nb_fd);
268 if (new_size != events->alloc_size && new_size >= events->init_size) {
269 ret = resize_poll_event(events, new_size);
270 if (ret < 0) {
271 /* ENOMEM problem at this point. */
272 goto error;
273 }
274 }
275
276 do {
277 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
278 } while (!interruptible && ret == -1 && errno == EINTR);
279 if (ret < 0) {
280 if (errno != EINTR) {
281 PERROR("epoll_wait");
282 }
283 goto error;
284 }
285
286 /*
287 * Since the returned events are set sequentially in the "events" structure
288 * we only need to return the epoll_wait value and iterate over it.
289 */
290 return ret;
291
292error:
293 return -1;
294}
295
296/*
297 * Setup poll set maximum size.
298 */
cd9adb8b 299int compat_epoll_set_max_size()
0060607b
MJ
300{
301 int ret, fd, retval = 0;
302 ssize_t size_ret;
303 char buf[64];
304
305 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
306 if (fd < 0) {
307 /*
308 * Failing on opening [1] is not an error per see. [1] was
309 * introduced in Linux 2.6.28 but epoll is available since
310 * 2.5.44. Hence, goto end and set a default value without
311 * setting an error return value.
312 *
313 * [1] /proc/sys/fs/epoll/max_user_watches
314 */
315 retval = 0;
316 goto end;
317 }
318
319 size_ret = lttng_read(fd, buf, sizeof(buf));
320 /*
321 * Allow reading a file smaller than buf, but keep space for
322 * final \0.
323 */
324 if (size_ret < 0 || size_ret >= sizeof(buf)) {
325 PERROR("read set max size");
326 retval = -1;
327 goto end_read;
328 }
329 buf[size_ret] = '\0';
330 poll_max_size = atoi(buf);
331end_read:
332 ret = close(fd);
333 if (ret) {
334 PERROR("close");
335 }
336end:
337 if (!poll_max_size) {
338 poll_max_size = DEFAULT_POLL_SIZE;
339 }
340 DBG("epoll set max size is %d", poll_max_size);
341 return retval;
342}
343
344#else /* HAVE_EPOLL */
345
346#include <sys/resource.h>
347#include <sys/time.h>
cc0acbd1
JG
348
349/*
350 * Maximum number of fd we can monitor.
351 *
352 * For poll(2), the max fds must not exceed RLIMIT_NOFILE given by
353 * getrlimit(2).
354 */
355static unsigned int poll_max_size;
5eb91c98 356
d21b0d71
DG
357/*
358 * Resize the epoll events structure of the new size.
359 *
360 * Return 0 on success or else -1 with the current events pointer untouched.
361 */
28ab034a 362static int resize_poll_event(struct compat_poll_event_array *array, uint32_t new_size)
d21b0d71
DG
363{
364 struct pollfd *ptr;
365
a0377dfe 366 LTTNG_ASSERT(array);
d21b0d71 367
ac018a8b
DG
368 /* Refuse to resize the array more than the max size. */
369 if (new_size > poll_max_size) {
370 goto error;
371 }
372
9730eb85 373 ptr = (struct pollfd *) realloc(array->events, new_size * sizeof(*ptr));
d21b0d71
DG
374 if (ptr == NULL) {
375 PERROR("realloc epoll add");
376 goto error;
377 }
53efb85a
MD
378 if (new_size > array->alloc_size) {
379 /* Zero newly allocated memory */
28ab034a 380 memset(ptr + array->alloc_size, 0, (new_size - array->alloc_size) * sizeof(*ptr));
53efb85a 381 }
d21b0d71
DG
382 array->events = ptr;
383 array->alloc_size = new_size;
384
385 return 0;
386
387error:
388 return -1;
389}
390
391/*
392 * Update events with the current events object.
393 */
394static int update_current_events(struct lttng_poll_event *events)
395{
396 int ret;
397 struct compat_poll_event_array *current, *wait;
398
a0377dfe 399 LTTNG_ASSERT(events);
d21b0d71
DG
400
401 current = &events->current;
402 wait = &events->wait;
403
404 wait->nb_fd = current->nb_fd;
dbe23f45 405 if (current->alloc_size != wait->alloc_size) {
d21b0d71
DG
406 ret = resize_poll_event(wait, current->alloc_size);
407 if (ret < 0) {
408 goto error;
409 }
410 }
28ab034a 411 memcpy(wait->events, current->events, current->nb_fd * sizeof(*current->events));
d21b0d71 412
dbe23f45 413 /* Update is done. */
d21b0d71 414 events->need_update = 0;
d21b0d71
DG
415
416 return 0;
417
418error:
419 return -1;
420}
421
5eb91c98
DG
422/*
423 * Create pollfd data structure.
424 */
425int compat_poll_create(struct lttng_poll_event *events, int size)
426{
d21b0d71
DG
427 struct compat_poll_event_array *current, *wait;
428
5eb91c98
DG
429 if (events == NULL || size <= 0) {
430 ERR("Wrong arguments for poll create");
431 goto error;
432 }
433
dbe23f45 434 if (!poll_max_size) {
c607fe03
MJ
435 if (lttng_poll_set_max_size()) {
436 goto error;
437 }
dbe23f45
MD
438 }
439
5eb91c98
DG
440 /* Don't bust the limit here */
441 if (size > poll_max_size) {
442 size = poll_max_size;
443 }
444
d21b0d71
DG
445 /* Reset everything before begining the allocation. */
446 memset(events, 0, sizeof(struct lttng_poll_event));
447
d21b0d71
DG
448 current = &events->current;
449 wait = &events->wait;
450
5eb91c98 451 /* This *must* be freed by using lttng_poll_free() */
c56f67e5 452 wait->events = calloc<struct pollfd>(size);
d21b0d71 453 if (wait->events == NULL) {
c56f67e5 454 PERROR("Failed to allocate wait events array during poll initialization");
5eb91c98
DG
455 goto error;
456 }
457
d21b0d71
DG
458 wait->alloc_size = wait->init_size = size;
459
c56f67e5 460 current->events = calloc<struct pollfd>(size);
d21b0d71 461 if (current->events == NULL) {
c56f67e5 462 PERROR("Failed to allocate current events array during poll initialization");
d21b0d71
DG
463 goto error;
464 }
465
466 current->alloc_size = current->init_size = size;
5eb91c98
DG
467
468 return 0;
469
470error:
471 return -1;
472}
473
474/*
475 * Add fd to pollfd data structure with requested events.
476 */
28ab034a 477int compat_poll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
5eb91c98 478{
d21b0d71
DG
479 int new_size, ret, i;
480 struct compat_poll_event_array *current;
5eb91c98 481
d21b0d71 482 if (events == NULL || events->current.events == NULL || fd < 0) {
5eb91c98
DG
483 ERR("Bad compat poll add arguments");
484 goto error;
485 }
486
d21b0d71
DG
487 current = &events->current;
488
489 /* Check if fd we are trying to add is already there. */
490 for (i = 0; i < current->nb_fd; i++) {
d21b0d71
DG
491 if (current->events[i].fd == fd) {
492 errno = EEXIST;
5eb91c98
DG
493 goto error;
494 }
5eb91c98
DG
495 }
496
dbe23f45
MD
497 /* Resize array if needed. */
498 new_size = 1U << utils_get_count_order_u32(current->nb_fd + 1);
499 if (new_size != current->alloc_size && new_size >= current->init_size) {
d21b0d71
DG
500 ret = resize_poll_event(current, new_size);
501 if (ret < 0) {
502 goto error;
503 }
d21b0d71 504 }
5eb91c98 505
d21b0d71
DG
506 current->events[current->nb_fd].fd = fd;
507 current->events[current->nb_fd].events = req_events;
508 current->nb_fd++;
509 events->need_update = 1;
510
511 DBG("fd %d of %d added to pollfd", fd, current->nb_fd);
5eb91c98
DG
512
513 return 0;
514
515error:
516 return -1;
517}
518
f057dfc3
JG
519/*
520 * Modify an fd's events..
521 */
28ab034a 522int compat_poll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
f057dfc3 523{
8a282751 524 int i;
f057dfc3
JG
525 struct compat_poll_event_array *current;
526
28ab034a
JG
527 if (events == NULL || events->current.nb_fd == 0 || events->current.events == NULL ||
528 fd < 0) {
f057dfc3
JG
529 ERR("Bad compat poll mod arguments");
530 goto error;
531 }
532
533 current = &events->current;
534
535 for (i = 0; i < current->nb_fd; i++) {
536 if (current->events[i].fd == fd) {
f057dfc3
JG
537 current->events[i].events = req_events;
538 events->need_update = 1;
539 break;
540 }
541 }
542
a1de8fcc
YL
543 /*
544 * The epoll flavor doesn't flag modifying a non-included FD as an
545 * error.
546 */
f057dfc3
JG
547
548 return 0;
549
550error:
551 return -1;
552}
553
5eb91c98
DG
554/*
555 * Remove a fd from the pollfd structure.
556 */
557int compat_poll_del(struct lttng_poll_event *events, int fd)
558{
a1de8fcc
YL
559 int i, count = 0, ret;
560 uint32_t new_size;
d21b0d71 561 struct compat_poll_event_array *current;
5eb91c98 562
28ab034a
JG
563 if (events == NULL || events->current.nb_fd == 0 || events->current.events == NULL ||
564 fd < 0) {
5eb91c98
DG
565 goto error;
566 }
567
d21b0d71
DG
568 /* Ease our life a bit. */
569 current = &events->current;
5eb91c98 570
d21b0d71 571 for (i = 0; i < current->nb_fd; i++) {
5eb91c98 572 /* Don't put back the fd we want to delete */
d21b0d71
DG
573 if (current->events[i].fd != fd) {
574 current->events[count].fd = current->events[i].fd;
575 current->events[count].events = current->events[i].events;
5eb91c98
DG
576 count++;
577 }
578 }
a1de8fcc
YL
579
580 /* The fd was not in our set, return no error as with epoll. */
581 if (current->nb_fd == count) {
582 goto end;
583 }
584
dbe23f45 585 /* No fd duplicate should be ever added into array. */
a0377dfe 586 LTTNG_ASSERT(current->nb_fd - 1 == count);
dbe23f45
MD
587 current->nb_fd = count;
588
589 /* Resize array if needed. */
590 new_size = 1U << utils_get_count_order_u32(current->nb_fd);
28ab034a
JG
591 if (new_size != current->alloc_size && new_size >= current->init_size &&
592 current->nb_fd != 0) {
dbe23f45
MD
593 ret = resize_poll_event(current, new_size);
594 if (ret < 0) {
595 goto error;
596 }
597 }
5eb91c98 598
d21b0d71 599 events->need_update = 1;
5eb91c98 600
a1de8fcc 601end:
5eb91c98
DG
602 return 0;
603
604error:
605 return -1;
606}
607
608/*
609 * Wait on poll() with timeout. Blocking call.
610 */
28ab034a 611int compat_poll_wait(struct lttng_poll_event *events, int timeout, bool interruptible)
5eb91c98 612{
22a73671 613 int ret, active_fd_count;
3e75a9b7 614 size_t pos = 0, consecutive_entries = 0, non_idle_pos;
5eb91c98 615
d21b0d71 616 if (events == NULL || events->current.events == NULL) {
5eb91c98
DG
617 ERR("poll wait arguments error");
618 goto error;
619 }
620
d21b0d71
DG
621 if (events->current.nb_fd == 0) {
622 /* Return an invalid error to be consistent with epoll. */
623 errno = EINVAL;
dbe23f45 624 events->wait.nb_fd = 0;
d21b0d71
DG
625 goto error;
626 }
627
628 if (events->need_update) {
629 ret = update_current_events(events);
630 if (ret < 0) {
631 errno = ENOMEM;
632 goto error;
633 }
634 }
635
a9b0dbc2
JG
636 do {
637 ret = poll(events->wait.events, events->wait.nb_fd, timeout);
9f32e9bf 638 } while (!interruptible && ret == -1 && errno == EINTR);
5eb91c98 639 if (ret < 0) {
9f32e9bf
MD
640 if (errno != EINTR) {
641 PERROR("poll wait");
642 }
5eb91c98
DG
643 goto error;
644 }
645
22a73671
YL
646 active_fd_count = ret;
647
9ddba525 648 /*
3e75a9b7
JG
649 * Move all active pollfd structs to the beginning of the
650 * array to emulate compat-epoll behaviour.
9ddba525 651 */
22a73671
YL
652 if (active_fd_count == events->wait.nb_fd) {
653 goto end;
654 }
22a73671 655
3e75a9b7
JG
656 while (consecutive_entries != active_fd_count) {
657 struct pollfd *current = &events->wait.events[pos];
658 struct pollfd idle_entry;
22a73671 659
3e75a9b7
JG
660 if (current->revents != 0) {
661 consecutive_entries++;
662 pos++;
663 continue;
22a73671 664 }
22a73671 665
3e75a9b7
JG
666 non_idle_pos = pos;
667
668 /* Look for next non-idle entry. */
28ab034a
JG
669 while (events->wait.events[++non_idle_pos].revents == 0)
670 ;
3e75a9b7
JG
671
672 /* Swap idle and non-idle entries. */
673 idle_entry = *current;
674 *current = events->wait.events[non_idle_pos];
675 events->wait.events[non_idle_pos] = idle_entry;
676
677 consecutive_entries++;
678 pos++;
679 }
22a73671
YL
680end:
681 return ret;
5eb91c98
DG
682
683error:
684 return -1;
685}
686
687/*
688 * Setup poll set maximum size.
689 */
dbe23f45 690int compat_poll_set_max_size(void)
5eb91c98 691{
dbe23f45 692 int ret, retval = 0;
5eb91c98
DG
693 struct rlimit lim;
694
5eb91c98
DG
695 ret = getrlimit(RLIMIT_NOFILE, &lim);
696 if (ret < 0) {
6f04ed72 697 PERROR("getrlimit poll RLIMIT_NOFILE");
dbe23f45
MD
698 retval = -1;
699 goto end;
5eb91c98
DG
700 }
701
702 poll_max_size = lim.rlim_cur;
dbe23f45 703end:
d21b0d71 704 if (poll_max_size == 0) {
990570ed 705 poll_max_size = DEFAULT_POLL_SIZE;
5eb91c98 706 }
5eb91c98 707 DBG("poll set max size set to %u", poll_max_size);
dbe23f45 708 return retval;
5eb91c98 709}
0060607b
MJ
710
711#endif /* !HAVE_EPOLL */
This page took 0.11052 seconds and 4 git commands to generate.