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