X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fcompat%2Fcompat-epoll.c;h=40451b3d21286106430c1322209b21d9fef9579f;hp=e1672c4c3178afbbce32acddebf2b30cea66fe09;hb=d21b0d71990ac6ec4272c1f80f0ca544103628b3;hpb=c617c0c651432f9d5ae7adf4c5c1a5fd92ad828e diff --git a/src/common/compat/compat-epoll.c b/src/common/compat/compat-epoll.c index e1672c4c3..40451b3d2 100644 --- a/src/common/compat/compat-epoll.c +++ b/src/common/compat/compat-epoll.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -31,6 +32,32 @@ unsigned int poll_max_size; +/* + * Resize the epoll events structure of the new size. + * + * Return 0 on success or else -1 with the current events pointer untouched. + */ +static int resize_poll_event(struct lttng_poll_event *events, + uint32_t new_size) +{ + struct epoll_event *ptr; + + assert(events); + + ptr = realloc(events->events, new_size * sizeof(*ptr)); + if (ptr == NULL) { + PERROR("realloc epoll add"); + goto error; + } + events->events = ptr; + events->alloc_size = new_size; + + return 0; + +error: + return -1; +} + /* * Create epoll set and allocate returned events structure. */ @@ -63,7 +90,7 @@ int compat_epoll_create(struct lttng_poll_event *events, int size, int flags) goto error_close; } - events->events_size = size; + events->alloc_size = events->init_size = size; events->nb_fd = 0; return 0; @@ -82,8 +109,8 @@ error: */ int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events) { - int ret, new_size; - struct epoll_event ev, *ptr; + int ret; + struct epoll_event ev; if (events == NULL || events->events == NULL || fd < 0) { ERR("Bad compat epoll add arguments"); @@ -112,17 +139,6 @@ int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_event events->nb_fd++; - if (events->nb_fd >= events->events_size) { - new_size = 2 * events->events_size; - ptr = realloc(events->events, new_size * sizeof(struct epoll_event)); - if (ptr == NULL) { - PERROR("realloc epoll add"); - goto error; - } - events->events = ptr; - events->events_size = new_size; - } - end: return 0; @@ -172,13 +188,39 @@ error: int compat_epoll_wait(struct lttng_poll_event *events, int timeout) { int ret; + uint32_t new_size; - if (events == NULL || events->events == NULL || - events->events_size < events->nb_fd) { + if (events == NULL || events->events == NULL) { ERR("Wrong arguments in compat_epoll_wait"); goto error; } + /* + * Resize if needed before waiting. We could either expand the array or + * shrink it down. It's important to note that after this step, we are + * ensured that the events argument of the epoll_wait call will be large + * enough to hold every possible returned events. + */ + if (events->nb_fd > events->alloc_size) { + /* Expand if the nb_fd is higher than the actual size. */ + new_size = events->alloc_size << 1UL; + } else if ((events->nb_fd << 1UL) <= events->alloc_size && + events->nb_fd >= events->init_size) { + /* Shrink if nb_fd multiplied by two is <= than the actual size. */ + new_size = events->alloc_size >> 1UL; + } else { + /* Indicate that we don't want to resize. */ + new_size = 0; + } + + if (new_size) { + ret = resize_poll_event(events, new_size); + if (ret < 0) { + /* ENOMEM problem at this point. */ + goto error; + } + } + do { ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout); } while (ret == -1 && errno == EINTR); @@ -220,7 +262,7 @@ void compat_epoll_set_max_size(void) } poll_max_size = atoi(buf); - if (poll_max_size <= 0) { + if (poll_max_size == 0) { /* Extra precaution */ poll_max_size = DEFAULT_POLL_SIZE; }