[core] isolate backend fdevent handler defs
[lighttpd.git] / src / fdevent_linux_sysepoll.c
blob22dd13299e3cfb5cc259cef2ffc125c550bb5fce
1 #include "first.h"
3 #include "fdevent_impl.h"
4 #include "fdevent.h"
5 #include "buffer.h"
6 #include "log.h"
8 #include <sys/types.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
15 #ifdef FDEVENT_USE_LINUX_EPOLL
17 # include <sys/epoll.h>
19 static void fdevent_linux_sysepoll_free(fdevents *ev) {
20 close(ev->epoll_fd);
21 free(ev->epoll_events);
24 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
25 struct epoll_event ep;
27 if (fde_ndx < 0) return -1;
29 memset(&ep, 0, sizeof(ep));
31 ep.data.fd = fd;
32 ep.data.ptr = NULL;
34 if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
35 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
36 "epoll_ctl failed: ", strerror(errno), ", dying");
38 SEGFAULT();
40 return 0;
44 return -1;
47 static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
48 struct epoll_event ep;
49 int add = 0;
51 if (fde_ndx == -1) add = 1;
53 memset(&ep, 0, sizeof(ep));
55 ep.events = 0;
57 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
58 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
60 /**
62 * with EPOLLET we don't get a FDEVENT_HUP
63 * if the close is delay after everything has
64 * sent.
68 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
70 ep.data.ptr = NULL;
71 ep.data.fd = fd;
73 if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
74 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
75 "epoll_ctl failed: ", strerror(errno), ", dying");
77 SEGFAULT();
79 return 0;
82 return fd;
85 static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
86 return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
89 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
90 int events = 0, e;
92 e = ev->epoll_events[ndx].events;
93 if (e & EPOLLIN) events |= FDEVENT_IN;
94 if (e & EPOLLOUT) events |= FDEVENT_OUT;
95 if (e & EPOLLERR) events |= FDEVENT_ERR;
96 if (e & EPOLLHUP) events |= FDEVENT_HUP;
97 if (e & EPOLLPRI) events |= FDEVENT_PRI;
99 return events;
102 static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) {
103 # if 0
104 log_error_write(ev->srv, __FILE__, __LINE__, "SD, D",
105 "fdevent_linux_sysepoll_event_get_fd: ", (int) ndx, ev->epoll_events[ndx].data.fd);
106 # endif
108 return ev->epoll_events[ndx].data.fd;
111 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
112 size_t i;
114 UNUSED(ev);
116 i = (ndx < 0) ? 0 : ndx + 1;
118 return i;
121 int fdevent_linux_sysepoll_init(fdevents *ev) {
122 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
123 #define SET(x) \
124 ev->x = fdevent_linux_sysepoll_##x;
126 SET(free);
127 SET(poll);
129 SET(event_del);
130 SET(event_set);
132 SET(event_next_fdndx);
133 SET(event_get_fd);
134 SET(event_get_revent);
136 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
137 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
138 "epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
140 return -1;
143 fdevent_setfd_cloexec(ev->epoll_fd);
145 ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events));
146 force_assert(NULL != ev->epoll_events);
148 return 0;
151 #else
152 int fdevent_linux_sysepoll_init(fdevents *ev) {
153 UNUSED(ev);
155 log_error_write(ev->srv, __FILE__, __LINE__, "S",
156 "linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
158 return -1;
160 #endif