diff options
author | dldmitry <dldmitry@yandex-team.ru> | 2022-02-10 16:47:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:17 +0300 |
commit | 10129030876638368b8965c627671fe44be079bc (patch) | |
tree | 681c849a324535feff6f07677873c9ffc4c51520 /contrib/libs/libevent/epoll.c | |
parent | 5c1eb9f48fd0ac41fd72519a8284ded6f0358f6f (diff) | |
download | ydb-10129030876638368b8965c627671fe44be079bc.tar.gz |
Restoring authorship annotation for <dldmitry@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/libevent/epoll.c')
-rw-r--r-- | contrib/libs/libevent/epoll.c | 618 |
1 files changed, 309 insertions, 309 deletions
diff --git a/contrib/libs/libevent/epoll.c b/contrib/libs/libevent/epoll.c index bdec2e4569..c53f03c24c 100644 --- a/contrib/libs/libevent/epoll.c +++ b/contrib/libs/libevent/epoll.c @@ -1,65 +1,65 @@ -/* - * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> - * Copyright 2007-2012 Niels Provos, Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "event2/event-config.h" +/* + * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> + * Copyright 2007-2012 Niels Provos, Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "event2/event-config.h" #include "evconfig-private.h" - + #ifdef EVENT__HAVE_EPOLL -#include <stdint.h> -#include <sys/types.h> -#include <sys/resource.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/resource.h> #ifdef EVENT__HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#include <sys/epoll.h> -#include <signal.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> +#include <sys/time.h> +#endif +#include <sys/queue.h> +#include <sys/epoll.h> +#include <signal.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> #ifdef EVENT__HAVE_FCNTL_H -#include <fcntl.h> -#endif +#include <fcntl.h> +#endif #ifdef EVENT__HAVE_SYS_TIMERFD_H #include <sys/timerfd.h> #endif - -#include "event-internal.h" -#include "evsignal-internal.h" -#include "event2/thread.h" -#include "evthread-internal.h" -#include "log-internal.h" -#include "evmap-internal.h" -#include "changelist-internal.h" + +#include "event-internal.h" +#include "evsignal-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "changelist-internal.h" #include "time-internal.h" - + /* Since Linux 2.6.17, epoll is able to report about peer half-closed connection using special EPOLLRDHUP flag on a read event. */ @@ -83,66 +83,66 @@ #define USING_TIMERFD #endif -struct epollop { - struct epoll_event *events; - int nevents; - int epfd; +struct epollop { + struct epoll_event *events; + int nevents; + int epfd; #ifdef USING_TIMERFD int timerfd; #endif -}; - -static void *epoll_init(struct event_base *); -static int epoll_dispatch(struct event_base *, struct timeval *); -static void epoll_dealloc(struct event_base *); - -static const struct eventop epollops_changelist = { - "epoll (with changelist)", - epoll_init, +}; + +static void *epoll_init(struct event_base *); +static int epoll_dispatch(struct event_base *, struct timeval *); +static void epoll_dealloc(struct event_base *); + +static const struct eventop epollops_changelist = { + "epoll (with changelist)", + epoll_init, event_changelist_add_, event_changelist_del_, - epoll_dispatch, - epoll_dealloc, - 1, /* need reinit */ + epoll_dispatch, + epoll_dealloc, + 1, /* need reinit */ EV_FEATURE_ET|EV_FEATURE_O1| EARLY_CLOSE_IF_HAVE_RDHUP, - EVENT_CHANGELIST_FDINFO_SIZE -}; - - -static int epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, - short old, short events, void *p); -static int epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, - short old, short events, void *p); - -const struct eventop epollops = { - "epoll", - epoll_init, - epoll_nochangelist_add, - epoll_nochangelist_del, - epoll_dispatch, - epoll_dealloc, - 1, /* need reinit */ + EVENT_CHANGELIST_FDINFO_SIZE +}; + + +static int epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p); +static int epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p); + +const struct eventop epollops = { + "epoll", + epoll_init, + epoll_nochangelist_add, + epoll_nochangelist_del, + epoll_dispatch, + epoll_dealloc, + 1, /* need reinit */ EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_EARLY_CLOSE, - 0 -}; - -#define INITIAL_NEVENT 32 -#define MAX_NEVENT 4096 - -/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout - * values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be - * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the - * largest number of msec we can support here is 2147482. Let's - * round that down by 47 seconds. - */ -#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000) - -static void * -epoll_init(struct event_base *base) -{ + 0 +}; + +#define INITIAL_NEVENT 32 +#define MAX_NEVENT 4096 + +/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout + * values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be + * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the + * largest number of msec we can support here is 2147482. Let's + * round that down by 47 seconds. + */ +#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000) + +static void * +epoll_init(struct event_base *base) +{ int epfd = -1; - struct epollop *epollop; - + struct epollop *epollop; + #ifdef EVENT__HAVE_EPOLL_CREATE1 /* First, try the shiny new epoll_create1 interface, if we have it. */ epfd = epoll_create1(EPOLL_CLOEXEC); @@ -156,31 +156,31 @@ epoll_init(struct event_base *base) return (NULL); } evutil_make_socket_closeonexec(epfd); - } - - if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) { - close(epfd); - return (NULL); - } - - epollop->epfd = epfd; - - /* Initialize fields */ - epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event)); - if (epollop->events == NULL) { - mm_free(epollop); - close(epfd); - return (NULL); - } - epollop->nevents = INITIAL_NEVENT; - - if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 || - ((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 && + } + + if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) { + close(epfd); + return (NULL); + } + + epollop->epfd = epfd; + + /* Initialize fields */ + epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event)); + if (epollop->events == NULL) { + mm_free(epollop); + close(epfd); + return (NULL); + } + epollop->nevents = INITIAL_NEVENT; + + if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 || + ((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 && evutil_getenv_("EVENT_EPOLL_USE_CHANGELIST") != NULL)) { - base->evsel = &epollops_changelist; + base->evsel = &epollops_changelist; } - + #ifdef USING_TIMERFD /* The epoll interface ordinarily gives us one-millisecond precision, @@ -216,36 +216,36 @@ epoll_init(struct event_base *base) epollop->timerfd = -1; } #endif - + evsig_init_(base); - return (epollop); -} - -static const char * -change_to_string(int change) -{ - change &= (EV_CHANGE_ADD|EV_CHANGE_DEL); - if (change == EV_CHANGE_ADD) { - return "add"; - } else if (change == EV_CHANGE_DEL) { - return "del"; - } else if (change == 0) { - return "none"; - } else { - return "???"; - } -} - -static const char * -epoll_op_to_string(int op) -{ - return op == EPOLL_CTL_ADD?"ADD": - op == EPOLL_CTL_DEL?"DEL": - op == EPOLL_CTL_MOD?"MOD": - "???"; -} - + return (epollop); +} + +static const char * +change_to_string(int change) +{ + change &= (EV_CHANGE_ADD|EV_CHANGE_DEL); + if (change == EV_CHANGE_ADD) { + return "add"; + } else if (change == EV_CHANGE_DEL) { + return "del"; + } else if (change == 0) { + return "none"; + } else { + return "???"; + } +} + +static const char * +epoll_op_to_string(int op) +{ + return op == EPOLL_CTL_ADD?"ADD": + op == EPOLL_CTL_DEL?"DEL": + op == EPOLL_CTL_MOD?"MOD": + "???"; +} + #define PRINT_CHANGES(op, events, ch, status) \ "Epoll %s(%d) on fd %d " status ". " \ "Old events were %d; " \ @@ -263,27 +263,27 @@ epoll_op_to_string(int op) ch->close_change, \ change_to_string(ch->close_change) -static int -epoll_apply_one_change(struct event_base *base, - struct epollop *epollop, - const struct event_change *ch) -{ - struct epoll_event epev; - int op, events = 0; +static int +epoll_apply_one_change(struct event_base *base, + struct epollop *epollop, + const struct event_change *ch) +{ + struct epoll_event epev; + int op, events = 0; int idx; - + idx = EPOLL_OP_TABLE_INDEX(ch); op = epoll_op_table[idx].op; events = epoll_op_table[idx].events; - + if (!events) { EVUTIL_ASSERT(op == 0); return 0; } - + if ((ch->read_change|ch->write_change|ch->close_change) & EV_CHANGE_ET) events |= EPOLLET; - + memset(&epev, 0, sizeof(epev)); epev.data.fd = ch->fd; epev.events = events; @@ -291,7 +291,7 @@ epoll_apply_one_change(struct event_base *base, event_debug((PRINT_CHANGES(op, epev.events, ch, "okay"))); return 0; } - + switch (op) { case EPOLL_CTL_MOD: if (errno == ENOENT) { @@ -308,8 +308,8 @@ epoll_apply_one_change(struct event_base *base, (int)epev.events, ch->fd)); return 0; - } - } + } + } break; case EPOLL_CTL_ADD: if (errno == EEXIST) { @@ -326,10 +326,10 @@ epoll_apply_one_change(struct event_base *base, return -1; } else { event_debug(("Epoll ADD(%d) on %d retried as MOD; succeeded.", - (int)epev.events, + (int)epev.events, ch->fd)); return 0; - } + } } break; case EPOLL_CTL_DEL: @@ -338,89 +338,89 @@ epoll_apply_one_change(struct event_base *base, * that's fine too: we closed the fd before we * got around to calling epoll_dispatch. */ event_debug(("Epoll DEL(%d) on fd %d gave %s: DEL was unnecessary.", - (int)epev.events, + (int)epev.events, ch->fd, strerror(errno))); return 0; - } + } break; default: break; - } + } event_warn(PRINT_CHANGES(op, epev.events, ch, "failed")); return -1; -} - -static int -epoll_apply_changes(struct event_base *base) -{ - struct event_changelist *changelist = &base->changelist; - struct epollop *epollop = base->evbase; - struct event_change *ch; - - int r = 0; - int i; - - for (i = 0; i < changelist->n_changes; ++i) { - ch = &changelist->changes[i]; - if (epoll_apply_one_change(base, epollop, ch) < 0) - r = -1; - } - - return (r); -} - -static int -epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, - short old, short events, void *p) -{ - struct event_change ch; - ch.fd = fd; - ch.old_events = old; +} + +static int +epoll_apply_changes(struct event_base *base) +{ + struct event_changelist *changelist = &base->changelist; + struct epollop *epollop = base->evbase; + struct event_change *ch; + + int r = 0; + int i; + + for (i = 0; i < changelist->n_changes; ++i) { + ch = &changelist->changes[i]; + if (epoll_apply_one_change(base, epollop, ch) < 0) + r = -1; + } + + return (r); +} + +static int +epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p) +{ + struct event_change ch; + ch.fd = fd; + ch.old_events = old; ch.read_change = ch.write_change = ch.close_change = 0; - if (events & EV_WRITE) - ch.write_change = EV_CHANGE_ADD | - (events & EV_ET); - if (events & EV_READ) - ch.read_change = EV_CHANGE_ADD | - (events & EV_ET); + if (events & EV_WRITE) + ch.write_change = EV_CHANGE_ADD | + (events & EV_ET); + if (events & EV_READ) + ch.read_change = EV_CHANGE_ADD | + (events & EV_ET); if (events & EV_CLOSED) ch.close_change = EV_CHANGE_ADD | (events & EV_ET); - - return epoll_apply_one_change(base, base->evbase, &ch); -} - -static int -epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, - short old, short events, void *p) -{ - struct event_change ch; - ch.fd = fd; - ch.old_events = old; + + return epoll_apply_one_change(base, base->evbase, &ch); +} + +static int +epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p) +{ + struct event_change ch; + ch.fd = fd; + ch.old_events = old; ch.read_change = ch.write_change = ch.close_change = 0; - if (events & EV_WRITE) + if (events & EV_WRITE) ch.write_change = EV_CHANGE_DEL | (events & EV_ET); - if (events & EV_READ) + if (events & EV_READ) ch.read_change = EV_CHANGE_DEL | (events & EV_ET); if (events & EV_CLOSED) ch.close_change = EV_CHANGE_DEL | (events & EV_ET); - - return epoll_apply_one_change(base, base->evbase, &ch); -} - -static int -epoll_dispatch(struct event_base *base, struct timeval *tv) -{ - struct epollop *epollop = base->evbase; - struct epoll_event *events = epollop->events; - int i, res; - long timeout = -1; - + + return epoll_apply_one_change(base, base->evbase, &ch); +} + +static int +epoll_dispatch(struct event_base *base, struct timeval *tv) +{ + struct epollop *epollop = base->evbase; + struct epoll_event *events = epollop->events; + int i, res; + long timeout = -1; + #ifdef USING_TIMERFD if (epollop->timerfd >= 0) { struct itimerspec is; @@ -448,98 +448,98 @@ epoll_dispatch(struct event_base *base, struct timeval *tv) } } else #endif - if (tv != NULL) { + if (tv != NULL) { timeout = evutil_tv_to_msec_(tv); - if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) { - /* Linux kernels can wait forever if the timeout is - * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */ - timeout = MAX_EPOLL_TIMEOUT_MSEC; - } - } - - epoll_apply_changes(base); + if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) { + /* Linux kernels can wait forever if the timeout is + * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */ + timeout = MAX_EPOLL_TIMEOUT_MSEC; + } + } + + epoll_apply_changes(base); event_changelist_remove_all_(&base->changelist, base); - - EVBASE_RELEASE_LOCK(base, th_base_lock); - - res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); - - EVBASE_ACQUIRE_LOCK(base, th_base_lock); - - if (res == -1) { - if (errno != EINTR) { - event_warn("epoll_wait"); - return (-1); - } - - return (0); - } - - event_debug(("%s: epoll_wait reports %d", __func__, res)); - EVUTIL_ASSERT(res <= epollop->nevents); - - for (i = 0; i < res; i++) { - int what = events[i].events; - short ev = 0; + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (res == -1) { + if (errno != EINTR) { + event_warn("epoll_wait"); + return (-1); + } + + return (0); + } + + event_debug(("%s: epoll_wait reports %d", __func__, res)); + EVUTIL_ASSERT(res <= epollop->nevents); + + for (i = 0; i < res; i++) { + int what = events[i].events; + short ev = 0; #ifdef USING_TIMERFD if (events[i].data.fd == epollop->timerfd) continue; #endif - + if (what & EPOLLERR) { - ev = EV_READ | EV_WRITE; + ev = EV_READ | EV_WRITE; } else if ((what & EPOLLHUP) && !(what & EPOLLRDHUP)) { ev = EV_READ | EV_WRITE; - } else { - if (what & EPOLLIN) - ev |= EV_READ; - if (what & EPOLLOUT) - ev |= EV_WRITE; + } else { + if (what & EPOLLIN) + ev |= EV_READ; + if (what & EPOLLOUT) + ev |= EV_WRITE; if (what & EPOLLRDHUP) ev |= EV_CLOSED; - } - - if (!ev) - continue; - + } + + if (!ev) + continue; + evmap_io_active_(base, events[i].data.fd, ev | EV_ET); - } - - if (res == epollop->nevents && epollop->nevents < MAX_NEVENT) { - /* We used all of the event space this time. We should - be ready for more events next time. */ - int new_nevents = epollop->nevents * 2; - struct epoll_event *new_events; - - new_events = mm_realloc(epollop->events, - new_nevents * sizeof(struct epoll_event)); - if (new_events) { - epollop->events = new_events; - epollop->nevents = new_nevents; - } - } - - return (0); -} - - -static void -epoll_dealloc(struct event_base *base) -{ - struct epollop *epollop = base->evbase; - + } + + if (res == epollop->nevents && epollop->nevents < MAX_NEVENT) { + /* We used all of the event space this time. We should + be ready for more events next time. */ + int new_nevents = epollop->nevents * 2; + struct epoll_event *new_events; + + new_events = mm_realloc(epollop->events, + new_nevents * sizeof(struct epoll_event)); + if (new_events) { + epollop->events = new_events; + epollop->nevents = new_nevents; + } + } + + return (0); +} + + +static void +epoll_dealloc(struct event_base *base) +{ + struct epollop *epollop = base->evbase; + evsig_dealloc_(base); - if (epollop->events) - mm_free(epollop->events); - if (epollop->epfd >= 0) - close(epollop->epfd); + if (epollop->events) + mm_free(epollop->events); + if (epollop->epfd >= 0) + close(epollop->epfd); #ifdef USING_TIMERFD if (epollop->timerfd >= 0) close(epollop->timerfd); #endif - - memset(epollop, 0, sizeof(struct epollop)); - mm_free(epollop); -} + + memset(epollop, 0, sizeof(struct epollop)); + mm_free(epollop); +} #endif /* EVENT__HAVE_EPOLL */ |