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