398d9d7b0582ab38178335fb18f41df5d4b23319
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
13 #include <common/defaults.h>
14 #include <common/error.h>
15 #include <common/macros.h>
16 #include <common/utils.h>
24 #include <sys/types.h>
29 * Maximum number of fd we can monitor.
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.
38 static unsigned int poll_max_size
;
41 * Resize the epoll events structure of the new size.
43 * Return 0 on success or else -1 with the current events pointer untouched.
45 static int resize_poll_event(struct lttng_poll_event
*events
,
48 struct epoll_event
*ptr
;
52 ptr
= realloc(events
->events
, new_size
* sizeof(*ptr
));
54 PERROR("realloc epoll add");
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
));
63 events
->alloc_size
= new_size
;
72 * Create epoll set and allocate returned events structure.
75 int compat_epoll_create(struct lttng_poll_event
*events
, int size
, int flags
)
79 if (events
== NULL
|| size
<= 0) {
84 if (lttng_poll_set_max_size()) {
89 /* Don't bust the limit here */
90 if (size
> poll_max_size
) {
94 ret
= compat_glibc_epoll_create(size
, flags
);
96 /* At this point, every error is fatal */
97 PERROR("epoll_create1");
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");
110 events
->alloc_size
= events
->init_size
= size
;
116 ret
= close(events
->epfd
);
125 * Add a fd to the epoll set with requesting events.
128 int compat_epoll_add(struct lttng_poll_event
*events
, int fd
, uint32_t req_events
)
131 struct epoll_event ev
;
133 if (events
== NULL
|| events
->events
== NULL
|| fd
< 0) {
134 ERR("Bad compat epoll add arguments");
139 * Zero struct epoll_event to ensure all representations of its
142 memset(&ev
, 0, sizeof(ev
));
143 ev
.events
= req_events
;
146 ret
= epoll_ctl(events
->epfd
, EPOLL_CTL_ADD
, fd
, &ev
);
150 /* If exist, it's OK. */
154 /* Print PERROR and goto end not failing. Show must go on. */
155 PERROR("epoll_ctl ADD");
158 PERROR("epoll_ctl ADD fatal");
173 * Remove a fd from the epoll set.
176 int compat_epoll_del(struct lttng_poll_event
*events
, int fd
)
180 if (events
== NULL
|| fd
< 0 || events
->nb_fd
== 0) {
184 ret
= epoll_ctl(events
->epfd
, EPOLL_CTL_DEL
, fd
, NULL
);
189 /* Print PERROR and goto end not failing. Show must go on. */
190 PERROR("epoll_ctl DEL");
193 PERROR("epoll_ctl DEL fatal");
208 * Set an fd's events.
211 int compat_epoll_mod(struct lttng_poll_event
*events
, int fd
, uint32_t req_events
)
214 struct epoll_event ev
;
216 if (events
== NULL
|| fd
< 0 || events
->nb_fd
== 0) {
221 * Zero struct epoll_event to ensure all representations of its
224 memset(&ev
, 0, sizeof(ev
));
225 ev
.events
= req_events
;
228 ret
= epoll_ctl(events
->epfd
, EPOLL_CTL_MOD
, fd
, &ev
);
233 /* Print PERROR and goto end not failing. Show must go on. */
234 PERROR("epoll_ctl MOD");
237 PERROR("epoll_ctl MOD fatal");
250 * Wait on epoll set. This is a blocking call of timeout value.
253 int compat_epoll_wait(struct lttng_poll_event
*events
, int timeout
,
259 if (events
== NULL
|| events
->events
== NULL
) {
260 ERR("Wrong arguments in compat_epoll_wait");
264 if (events
->nb_fd
== 0) {
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.
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
);
279 /* ENOMEM problem at this point. */
285 ret
= epoll_wait(events
->epfd
, events
->events
, events
->nb_fd
, timeout
);
286 } while (!interruptible
&& ret
== -1 && errno
== EINTR
);
288 if (errno
!= EINTR
) {
289 PERROR("epoll_wait");
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.
305 * Setup poll set maximum size.
308 int compat_epoll_set_max_size(void)
310 int ret
, fd
, retval
= 0;
314 fd
= open(COMPAT_EPOLL_PROC_PATH
, O_RDONLY
);
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.
322 * [1] /proc/sys/fs/epoll/max_user_watches
328 size_ret
= lttng_read(fd
, buf
, sizeof(buf
));
330 * Allow reading a file smaller than buf, but keep space for
333 if (size_ret
< 0 || size_ret
>= sizeof(buf
)) {
334 PERROR("read set max size");
338 buf
[size_ret
] = '\0';
339 poll_max_size
= atoi(buf
);
346 if (!poll_max_size
) {
347 poll_max_size
= DEFAULT_POLL_SIZE
;
349 DBG("epoll set max size is %d", poll_max_size
);
353 #else /* HAVE_EPOLL */
355 #include <sys/resource.h>
356 #include <sys/time.h>
359 * Maximum number of fd we can monitor.
361 * For poll(2), the max fds must not exceed RLIMIT_NOFILE given by
364 static unsigned int poll_max_size
;
367 * Resize the epoll events structure of the new size.
369 * Return 0 on success or else -1 with the current events pointer untouched.
371 static int resize_poll_event(struct compat_poll_event_array
*array
,
378 /* Refuse to resize the array more than the max size. */
379 if (new_size
> poll_max_size
) {
383 ptr
= realloc(array
->events
, new_size
* sizeof(*ptr
));
385 PERROR("realloc epoll add");
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
));
394 array
->alloc_size
= new_size
;
403 * Update events with the current events object.
405 static int update_current_events(struct lttng_poll_event
*events
)
408 struct compat_poll_event_array
*current
, *wait
;
410 LTTNG_ASSERT(events
);
412 current
= &events
->current
;
413 wait
= &events
->wait
;
415 wait
->nb_fd
= current
->nb_fd
;
416 if (current
->alloc_size
!= wait
->alloc_size
) {
417 ret
= resize_poll_event(wait
, current
->alloc_size
);
422 memcpy(wait
->events
, current
->events
,
423 current
->nb_fd
* sizeof(*current
->events
));
425 /* Update is done. */
426 events
->need_update
= 0;
435 * Create pollfd data structure.
438 int compat_poll_create(struct lttng_poll_event
*events
, int size
)
440 struct compat_poll_event_array
*current
, *wait
;
442 if (events
== NULL
|| size
<= 0) {
443 ERR("Wrong arguments for poll create");
447 if (!poll_max_size
) {
448 if (lttng_poll_set_max_size()) {
453 /* Don't bust the limit here */
454 if (size
> poll_max_size
) {
455 size
= poll_max_size
;
458 /* Reset everything before begining the allocation. */
459 memset(events
, 0, sizeof(struct lttng_poll_event
));
461 current
= &events
->current
;
462 wait
= &events
->wait
;
464 /* This *must* be freed by using lttng_poll_free() */
465 wait
->events
= zmalloc(size
* sizeof(struct pollfd
));
466 if (wait
->events
== NULL
) {
467 PERROR("zmalloc struct pollfd");
471 wait
->alloc_size
= wait
->init_size
= size
;
473 current
->events
= zmalloc(size
* sizeof(struct pollfd
));
474 if (current
->events
== NULL
) {
475 PERROR("zmalloc struct current pollfd");
479 current
->alloc_size
= current
->init_size
= size
;
488 * Add fd to pollfd data structure with requested events.
491 int compat_poll_add(struct lttng_poll_event
*events
, int fd
,
494 int new_size
, ret
, i
;
495 struct compat_poll_event_array
*current
;
497 if (events
== NULL
|| events
->current
.events
== NULL
|| fd
< 0) {
498 ERR("Bad compat poll add arguments");
502 current
= &events
->current
;
504 /* Check if fd we are trying to add is already there. */
505 for (i
= 0; i
< current
->nb_fd
; i
++) {
506 if (current
->events
[i
].fd
== fd
) {
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
) {
515 ret
= resize_poll_event(current
, new_size
);
521 current
->events
[current
->nb_fd
].fd
= fd
;
522 current
->events
[current
->nb_fd
].events
= req_events
;
524 events
->need_update
= 1;
526 DBG("fd %d of %d added to pollfd", fd
, current
->nb_fd
);
535 * Modify an fd's events..
538 int compat_poll_mod(struct lttng_poll_event
*events
, int fd
,
542 struct compat_poll_event_array
*current
;
544 if (events
== NULL
|| events
->current
.nb_fd
== 0 ||
545 events
->current
.events
== NULL
|| fd
< 0) {
546 ERR("Bad compat poll mod arguments");
550 current
= &events
->current
;
552 for (i
= 0; i
< current
->nb_fd
; i
++) {
553 if (current
->events
[i
].fd
== fd
) {
554 current
->events
[i
].events
= req_events
;
555 events
->need_update
= 1;
561 * The epoll flavor doesn't flag modifying a non-included FD as an
572 * Remove a fd from the pollfd structure.
575 int compat_poll_del(struct lttng_poll_event
*events
, int fd
)
577 int i
, count
= 0, ret
;
579 struct compat_poll_event_array
*current
;
581 if (events
== NULL
|| events
->current
.nb_fd
== 0 ||
582 events
->current
.events
== NULL
|| fd
< 0) {
586 /* Ease our life a bit. */
587 current
= &events
->current
;
589 for (i
= 0; i
< current
->nb_fd
; i
++) {
590 /* Don't put back the fd we want to delete */
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
;
598 /* The fd was not in our set, return no error as with epoll. */
599 if (current
->nb_fd
== count
) {
603 /* No fd duplicate should be ever added into array. */
604 LTTNG_ASSERT(current
->nb_fd
- 1 == count
);
605 current
->nb_fd
= count
;
607 /* Resize array if needed. */
608 new_size
= 1U << utils_get_count_order_u32(current
->nb_fd
);
609 if (new_size
!= current
->alloc_size
&& new_size
>= current
->init_size
610 && current
->nb_fd
!= 0) {
611 ret
= resize_poll_event(current
, new_size
);
617 events
->need_update
= 1;
627 * Wait on poll() with timeout. Blocking call.
630 int compat_poll_wait(struct lttng_poll_event
*events
, int timeout
,
633 int ret
, active_fd_count
;
634 size_t pos
= 0, consecutive_entries
= 0, non_idle_pos
;
636 if (events
== NULL
|| events
->current
.events
== NULL
) {
637 ERR("poll wait arguments error");
641 if (events
->current
.nb_fd
== 0) {
642 /* Return an invalid error to be consistent with epoll. */
644 events
->wait
.nb_fd
= 0;
648 if (events
->need_update
) {
649 ret
= update_current_events(events
);
657 ret
= poll(events
->wait
.events
, events
->wait
.nb_fd
, timeout
);
658 } while (!interruptible
&& ret
== -1 && errno
== EINTR
);
660 if (errno
!= EINTR
) {
666 active_fd_count
= ret
;
669 * Move all active pollfd structs to the beginning of the
670 * array to emulate compat-epoll behaviour.
672 if (active_fd_count
== events
->wait
.nb_fd
) {
676 while (consecutive_entries
!= active_fd_count
) {
677 struct pollfd
*current
= &events
->wait
.events
[pos
];
678 struct pollfd idle_entry
;
680 if (current
->revents
!= 0) {
681 consecutive_entries
++;
688 /* Look for next non-idle entry. */
689 while (events
->wait
.events
[++non_idle_pos
].revents
== 0);
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
;
696 consecutive_entries
++;
707 * Setup poll set maximum size.
710 int compat_poll_set_max_size(void)
715 ret
= getrlimit(RLIMIT_NOFILE
, &lim
);
717 PERROR("getrlimit poll RLIMIT_NOFILE");
722 poll_max_size
= lim
.rlim_cur
;
724 if (poll_max_size
== 0) {
725 poll_max_size
= DEFAULT_POLL_SIZE
;
727 DBG("poll set max size set to %u", poll_max_size
);
731 #endif /* !HAVE_EPOLL */
This page took 0.056202 seconds and 4 git commands to generate.