diff --git a/src/fdevent.c b/src/fdevent.c index e7b19a33..d20e6fd3 100644 --- a/src/fdevent.c +++ b/src/fdevent.c @@ -302,8 +302,10 @@ int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { fdn->handler = handler; fdn->fd = fd; fdn->ctx = ctx; - fdn->handler_ctx = NULL; fdn->events = 0; + #ifdef FDEVENT_USE_LIBEV + fdn->handler_ctx = NULL; + #endif ev->fdarray[fd] = fdn; diff --git a/src/fdevent.h b/src/fdevent.h index d459e876..715f0ae9 100644 --- a/src/fdevent.h +++ b/src/fdevent.h @@ -12,13 +12,17 @@ typedef handler_t (*fdevent_handler)(struct server *srv, void *ctx, int revents) /* these are the POLL* values from (linux poll) */ -#define FDEVENT_IN BV(0) -#define FDEVENT_PRI BV(1) -#define FDEVENT_OUT BV(2) -#define FDEVENT_ERR BV(3) -#define FDEVENT_HUP BV(4) -#define FDEVENT_NVAL BV(5) -#define FDEVENT_RDHUP BV(13) +#define FDEVENT_IN 0x0001 +#define FDEVENT_PRI 0x0002 +#define FDEVENT_OUT 0x0004 +#define FDEVENT_ERR 0x0008 +#define FDEVENT_HUP 0x0010 +#define FDEVENT_NVAL 0x0020 +#if defined(__sun) && defined(__SVR4) /* Solaris */ +#define FDEVENT_RDHUP 0x4000 +#else +#define FDEVENT_RDHUP 0x2000 +#endif #define FDEVENT_STREAM_REQUEST BV(0) #define FDEVENT_STREAM_REQUEST_BUFMIN BV(1) diff --git a/src/fdevent_impl.h b/src/fdevent_impl.h index 056e2fce..ee0e052f 100644 --- a/src/fdevent_impl.h +++ b/src/fdevent_impl.h @@ -63,9 +63,11 @@ typedef enum { typedef struct _fdnode { fdevent_handler handler; void *ctx; - void *handler_ctx; int fd; int events; + #ifdef FDEVENT_USE_LIBEV + void *handler_ctx; + #endif } fdnode; /** @@ -83,17 +85,34 @@ typedef struct { #endif struct fdevents { - struct server *srv; - fdevent_handler_t type; - fdnode **fdarray; fdnode *pendclose; - size_t maxfds; + int (*event_set)(struct fdevents *ev, int fde_ndx, int fd, int events); + int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); + int (*poll)(struct fdevents *ev, int timeout_ms); + + struct server *srv; + size_t maxfds; #ifdef FDEVENT_USE_LINUX_EPOLL int epoll_fd; struct epoll_event *epoll_events; #endif + #ifdef FDEVENT_USE_SOLARIS_DEVPOLL + int devpoll_fd; + struct pollfd *devpollfds; + #endif + #ifdef FDEVENT_USE_SOLARIS_PORT + int port_fd; + port_event_t *port_events; + #endif + #ifdef FDEVENT_USE_FREEBSD_KQUEUE + int kq_fd; + struct kevent *kq_results; + #endif + #ifdef FDEVENT_USE_LIBEV + struct ev_loop *libev_loop; + #endif #ifdef FDEVENT_USE_POLL struct pollfd *pollfds; @@ -113,29 +132,10 @@ struct fdevents { int select_max_fd; #endif - #ifdef FDEVENT_USE_SOLARIS_DEVPOLL - int devpoll_fd; - struct pollfd *devpollfds; - #endif - #ifdef FDEVENT_USE_SOLARIS_PORT - port_event_t *port_events; - #endif - #ifdef FDEVENT_USE_FREEBSD_KQUEUE - int kq_fd; - struct kevent *kq_results; - #endif - #ifdef FDEVENT_USE_SOLARIS_PORT - int port_fd; - #endif - #ifdef FDEVENT_USE_LIBEV - struct ev_loop *libev_loop; - #endif + int (*reset)(struct fdevents *ev); void (*free)(struct fdevents *ev); - - int (*event_set)(struct fdevents *ev, int fde_ndx, int fd, int events); - int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); - int (*poll)(struct fdevents *ev, int timeout_ms); + fdevent_handler_t type; }; int fdevent_select_init(struct fdevents *ev); diff --git a/src/fdevent_linux_sysepoll.c b/src/fdevent_linux_sysepoll.c index 1ff3a8ee..4b4db40d 100644 --- a/src/fdevent_linux_sysepoll.c +++ b/src/fdevent_linux_sysepoll.c @@ -26,16 +26,9 @@ static void fdevent_linux_sysepoll_free(fdevents *ev) { } 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)) { + if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, NULL)) { log_error_write(ev->srv, __FILE__, __LINE__, "SSS", "epoll_ctl failed: ", strerror(errno), ", dying"); @@ -44,23 +37,12 @@ static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { 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; + int add = (-1 == fde_ndx); /** * @@ -70,9 +52,7 @@ static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, i * */ - ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */; - - ep.data.ptr = NULL; + ep.events = events | EPOLLERR | EPOLLHUP /* | EPOLLET */; ep.data.fd = fd; if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { @@ -87,27 +67,13 @@ static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, i return fd; } -static int fdevent_linux_sysepoll_event_get_revent(const 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_poll(fdevents * const ev, int timeout_ms) { int n = epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms); server * const srv = ev->srv; for (int i = 0; i < n; ++i) { + int revents = ev->epoll_events[i].events; fdnode * const fdn = ev->fdarray[ev->epoll_events[i].data.fd]; if (0 == ((uintptr_t)fdn & 0x3)) { - int revents = fdevent_linux_sysepoll_event_get_revent(ev, i); (*fdn->handler)(srv, fdn->ctx, revents); } } @@ -116,6 +82,14 @@ static int fdevent_linux_sysepoll_poll(fdevents * const ev, int timeout_ms) { int fdevent_linux_sysepoll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; + force_assert(EPOLLIN == FDEVENT_IN); + force_assert(EPOLLPRI == FDEVENT_PRI); + force_assert(EPOLLOUT == FDEVENT_OUT); + force_assert(EPOLLERR == FDEVENT_ERR); + force_assert(EPOLLHUP == FDEVENT_HUP); + #if 0 != EPOLLRDHUP + force_assert(EPOLLRDHUP == FDEVENT_RDHUP); + #endif #define SET(x) \ ev->x = fdevent_linux_sysepoll_##x; diff --git a/src/fdevent_poll.c b/src/fdevent_poll.c index ae760991..41e53af6 100644 --- a/src/fdevent_poll.c +++ b/src/fdevent_poll.c @@ -62,30 +62,12 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { return -1; } -#if 0 -static int fdevent_poll_event_compress(fdevents *ev) { - size_t j; - - if (ev->used == 0) return 0; - if (ev->unused.used != 0) return 0; - - for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--; - - return 0; -} -#endif - static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - int pevents = 0; - if (events & FDEVENT_IN) pevents |= POLLIN; - if (events & FDEVENT_OUT) pevents |= POLLOUT; - if (events & FDEVENT_RDHUP) pevents |= POLLRDHUP; - - /* known index */ + int k; if (fde_ndx != -1) { if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = pevents; + ev->pollfds[fde_ndx].events = events; return fde_ndx; } @@ -95,12 +77,8 @@ static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) } if (ev->unused.used > 0) { - int k = ev->unused.ptr[--ev->unused.used]; - - ev->pollfds[k].fd = fd; - ev->pollfds[k].events = pevents; + k = ev->unused.ptr[--ev->unused.used]; - return k; } else { if (ev->size == ev->used) { ev->size += 16; @@ -108,47 +86,16 @@ static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) force_assert(NULL != ev->pollfds); } - ev->pollfds[ev->used].fd = fd; - ev->pollfds[ev->used].events = pevents; - - return ev->used++; - } -} - -static int fdevent_poll_event_get_revent(const fdevents *ev, size_t ndx) { - int r, poll_r; - - if (ndx >= ev->used) { - log_error_write(ev->srv, __FILE__, __LINE__, "sii", - "dying because: event: ", (int) ndx, (int) ev->used); - - SEGFAULT(); - - return 0; + k = ev->used++; } - if (ev->pollfds[ndx].revents & POLLNVAL) { - /* should never happen */ - SEGFAULT(); - } - - r = 0; - poll_r = ev->pollfds[ndx].revents; - - /* map POLL* to FDEVEN_*; they are probably the same, but still. */ - - if (poll_r & POLLIN) r |= FDEVENT_IN; - if (poll_r & POLLOUT) r |= FDEVENT_OUT; - if (poll_r & POLLERR) r |= FDEVENT_ERR; - if (poll_r & POLLHUP) r |= FDEVENT_HUP; - if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; - if (poll_r & POLLPRI) r |= FDEVENT_PRI; - if (poll_r & POLLRDHUP) r |= FDEVENT_RDHUP; + ev->pollfds[k].fd = fd; + ev->pollfds[k].events = events; - return r; + return k; } -static int fdevent_poll_event_next_fdndx(const fdevents *ev, int ndx) { +static int fdevent_poll_next_ndx(const fdevents *ev, int ndx) { for (size_t i = (size_t)(ndx+1); i < ev->used; ++i) { if (ev->pollfds[i].revents) return i; } @@ -156,18 +103,12 @@ static int fdevent_poll_event_next_fdndx(const fdevents *ev, int ndx) { } static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { - #if 0 - fdevent_poll_event_compress(ev); - #endif - int n = poll(ev->pollfds, ev->used, timeout_ms); + const int n = poll(ev->pollfds, ev->used, timeout_ms); server * const srv = ev->srv; - for (int ndx = -1, i = 0; i < n; ++i) { - fdnode *fdn; - ndx = fdevent_poll_event_next_fdndx(ev, ndx); - if (-1 == ndx) break; - fdn = ev->fdarray[ev->pollfds[ndx].fd]; + for (int ndx=-1,i=0; ipollfds[ndx].revents; + fdnode *fdn = ev->fdarray[ev->pollfds[ndx].fd]; if (0 == ((uintptr_t)fdn & 0x3)) { - int revents = fdevent_poll_event_get_revent(ev, ndx); (*fdn->handler)(srv, fdn->ctx, revents); } } @@ -176,6 +117,15 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { int fdevent_poll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_POLL; + force_assert(POLLIN == FDEVENT_IN); + force_assert(POLLPRI == FDEVENT_PRI); + force_assert(POLLOUT == FDEVENT_OUT); + force_assert(POLLERR == FDEVENT_ERR); + force_assert(POLLHUP == FDEVENT_HUP); + force_assert(POLLNVAL == FDEVENT_NVAL); + #if 0 != POLLRDHUP + force_assert(POLLRDHUP == FDEVENT_RDHUP); + #endif #define SET(x) \ ev->x = fdevent_poll_##x; diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c index 60ac7cdb..dd54b47c 100644 --- a/src/fdevent_solaris_devpoll.c +++ b/src/fdevent_solaris_devpoll.c @@ -46,16 +46,10 @@ static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) static int fdevent_solaris_devpoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { struct pollfd pfd; - int add = 0; - - int pevents = 0; - if (events & FDEVENT_IN) pevents |= POLLIN; - if (events & FDEVENT_OUT) pevents |= POLLOUT; - - if (fde_ndx == -1) add = 1; + int add = (-1 == fde_ndx); pfd.fd = fd; - pfd.events = pevents; + pfd.events = events; pfd.revents = 0; if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { @@ -68,24 +62,6 @@ static int fdevent_solaris_devpoll_event_set(fdevents *ev, int fde_ndx, int fd, return fd; } -static int fdevent_solaris_devpoll_event_get_revent(const fdevents *ev, size_t ndx) { - int r, poll_r; - - r = 0; - poll_r = ev->devpollfds[ndx].revents; - - /* map POLL* to FDEVEN_*; they are probably the same, but still. */ - - if (poll_r & POLLIN) r |= FDEVENT_IN; - if (poll_r & POLLOUT) r |= FDEVENT_OUT; - if (poll_r & POLLERR) r |= FDEVENT_ERR; - if (poll_r & POLLHUP) r |= FDEVENT_HUP; - if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; - if (poll_r & POLLPRI) r |= FDEVENT_PRI; - - return r; -} - static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { int n; server * const srv = ev->srv; @@ -98,9 +74,9 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { n = ioctl(ev->devpoll_fd, DP_POLL, &dopoll); for (int i = 0; i < n; ++i) { + int revents = ev->devpollfds[i].revents; fdnode * const fdn = ev->fdarray[ev->devpollfds[i].fd]; if (0 == ((uintptr_t)fdn & 0x3)) { - int revents = fdevent_solaris_devpoll_event_get_revent(ev, i); (*fdn->handler)(srv, fdn->ctx, revents); } } @@ -122,6 +98,13 @@ int fdevent_solaris_devpoll_reset(fdevents *ev) { } int fdevent_solaris_devpoll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL; + force_assert(POLLIN == FDEVENT_IN); + force_assert(POLLPRI == FDEVENT_PRI); + force_assert(POLLOUT == FDEVENT_OUT); + force_assert(POLLERR == FDEVENT_ERR); + force_assert(POLLHUP == FDEVENT_HUP); + force_assert(POLLNVAL == FDEVENT_NVAL); + force_assert(POLLRDHUP == FDEVENT_RDHUP); #define SET(x) \ ev->x = fdevent_solaris_devpoll_##x; diff --git a/src/fdevent_solaris_port.c b/src/fdevent_solaris_port.c index b60b0a58..37782936 100644 --- a/src/fdevent_solaris_port.c +++ b/src/fdevent_solaris_port.c @@ -58,20 +58,6 @@ static int fdevent_solaris_port_event_set(fdevents *ev, int fde_ndx, int fd, int return fd; } -static int fdevent_solaris_port_event_get_revent(const fdevents *ev, size_t ndx) { - int events = 0, e; - - e = ev->port_events[ndx].portev_events; - if (e & POLLIN) events |= FDEVENT_IN; - if (e & POLLOUT) events |= FDEVENT_OUT; - if (e & POLLERR) events |= FDEVENT_ERR; - if (e & POLLHUP) events |= FDEVENT_HUP; - if (e & POLLPRI) events |= FDEVENT_PRI; - if (e & POLLNVAL) events |= FDEVENT_NVAL; - - return e; -} - static void fdevent_solaris_port_free(fdevents *ev) { close(ev->port_fd); free(ev->port_events); @@ -119,9 +105,9 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { } for (i = 0; i < available_events; ++i) { + int revents = ev->port_events[i].portev_events; fdnode * const fdn = ev->fdarray[ev->port_events[i].portev_object]; if (0 == ((uintptr_t)fdn & 0x3)) { - int revents = fdevent_solaris_port_event_get_revent(ev, i); (*fdn->handler)(ev->srv, fdn->ctx, revents); } } @@ -130,6 +116,13 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { int fdevent_solaris_port_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_SOLARIS_PORT; + force_assert(POLLIN == FDEVENT_IN); + force_assert(POLLPRI == FDEVENT_PRI); + force_assert(POLLOUT == FDEVENT_OUT); + force_assert(POLLERR == FDEVENT_ERR); + force_assert(POLLHUP == FDEVENT_HUP); + force_assert(POLLNVAL == FDEVENT_NVAL); + force_assert(POLLRDHUP == FDEVENT_RDHUP); #define SET(x) \ ev->x = fdevent_solaris_port_##x;