diff options
Diffstat (limited to 'data/lighttpd/lighttpd-1.4.53/src/fdevent_linux_sysepoll.c')
-rw-r--r-- | data/lighttpd/lighttpd-1.4.53/src/fdevent_linux_sysepoll.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/data/lighttpd/lighttpd-1.4.53/src/fdevent_linux_sysepoll.c b/data/lighttpd/lighttpd-1.4.53/src/fdevent_linux_sysepoll.c new file mode 100644 index 000000000..453132df9 --- /dev/null +++ b/data/lighttpd/lighttpd-1.4.53/src/fdevent_linux_sysepoll.c @@ -0,0 +1,166 @@ +#include "first.h" + +#include "fdevent_impl.h" +#include "fdevent.h" +#include "buffer.h" +#include "log.h" + +#include <sys/types.h> + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#ifdef FDEVENT_USE_LINUX_EPOLL + +# include <sys/epoll.h> + +#ifndef EPOLLRDHUP +#define EPOLLRDHUP 0 +#endif + +static void fdevent_linux_sysepoll_free(fdevents *ev) { + close(ev->epoll_fd); + free(ev->epoll_events); +} + +static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { + struct epoll_event ep; + + if (fde_ndx < 0) return -1; + + memset(&ep, 0, sizeof(ep)); + + ep.data.fd = fd; + ep.data.ptr = NULL; + + if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) { + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_ctl failed: ", strerror(errno), ", dying"); + + SEGFAULT(); + + return 0; + } + + + return -1; +} + +static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { + struct epoll_event ep; + int add = 0; + + if (fde_ndx == -1) add = 1; + + memset(&ep, 0, sizeof(ep)); + + ep.events = 0; + + if (events & FDEVENT_IN) ep.events |= EPOLLIN; + if (events & FDEVENT_OUT) ep.events |= EPOLLOUT; + if (events & FDEVENT_RDHUP) ep.events |= EPOLLRDHUP; + + /** + * + * with EPOLLET we don't get a FDEVENT_HUP + * if the close is delay after everything has + * sent. + * + */ + + ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */; + + ep.data.ptr = NULL; + ep.data.fd = fd; + + if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_ctl failed: ", strerror(errno), ", dying"); + + SEGFAULT(); + + return 0; + } + + return fd; +} + +static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) { + return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms); +} + +static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) { + int events = 0, e; + + e = ev->epoll_events[ndx].events; + if (e & EPOLLIN) events |= FDEVENT_IN; + if (e & EPOLLOUT) events |= FDEVENT_OUT; + if (e & EPOLLERR) events |= FDEVENT_ERR; + if (e & EPOLLHUP) events |= FDEVENT_HUP; + if (e & EPOLLPRI) events |= FDEVENT_PRI; + if (e & EPOLLRDHUP) events |= FDEVENT_RDHUP; + + return events; +} + +static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) { +# if 0 + log_error_write(ev->srv, __FILE__, __LINE__, "SD, D", + "fdevent_linux_sysepoll_event_get_fd: ", (int) ndx, ev->epoll_events[ndx].data.fd); +# endif + + return ev->epoll_events[ndx].data.fd; +} + +static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) { + size_t i; + + UNUSED(ev); + + i = (ndx < 0) ? 0 : ndx + 1; + + return i; +} + +int fdevent_linux_sysepoll_init(fdevents *ev) { + ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; +#define SET(x) \ + ev->x = fdevent_linux_sysepoll_##x; + + SET(free); + SET(poll); + + SET(event_del); + SET(event_set); + + SET(event_next_fdndx); + SET(event_get_fd); + SET(event_get_revent); + + if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); + + return -1; + } + + fdevent_setfd_cloexec(ev->epoll_fd); + + ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events)); + force_assert(NULL != ev->epoll_events); + + return 0; +} + +#else +int fdevent_linux_sysepoll_init(fdevents *ev) { + UNUSED(ev); + + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\""); + + return -1; +} +#endif |