#include "netpoll.h"
-/* For epoll we have to guarantee stability of reference, so the table
- * contains pointers. net_poll_init initializes these pointers. The generic
- * functions always swap elements in and out of the allocated portion of the
- * table. */
-#if defined(NETPOLL_USE_EPOLL)
-#define REF(x) (*(x))
-typedef struct net_pollfd *net_pollfd_tabent_t;
-#else
-#define REF(x) (x)
-typedef struct net_pollfd net_pollfd_tabent_t;
-#endif
-
#define NETPOLL_MAXFDS 1024
-static net_pollfd_tabent_t fds[NETPOLL_MAXFDS] = {};
+static struct net_pollfd fds[NETPOLL_MAXFDS] = {};
static int nfds = 0;
-#if defined(NETPOLL_USE_SELECT)
-static fd_set readfds, writefds, xreadfds, xwritefds;
-static int lastptr = 0;
-void net_poll_init(void)
-{
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
-}
-void net_poll_fini(void)
-{
-}
-static void net_poll_add_impl(int i)
-{
- if (fds[i].fd >= FD_SETSIZE) {
- fprintf(stderr, "net_poll_add_impl: FD_SETSIZE limit\n");
- abort();
- }
- if (lastptr >= i)
- lastptr++;
-}
-static void net_poll_del_impl(int i)
-{
- if (lastptr > i)
- lastptr--;
-}
-static void net_poll_reg_impl(int i, int ev)
-{
- if (ev & NETPOLL_IN)
- FD_SET(fds[i].fd, &readfds);
- else
- FD_CLR(fds[i].fd, &readfds);
- if (ev & NETPOLL_OUT)
- FD_SET(fds[i].fd, &writefds);
- else
- FD_CLR(fds[i].fd, &writefds);
-}
-int net_poll_begin(void)
-{
- memcpy(&xreadfds, &readfds, sizeof(readfds));
- memcpy(&xwritefds, &writefds, sizeof(writefds));
- sigset_t mask;
- sigprocmask(0, 0, &mask);
- sigdelset(&mask, SIGCHLD);
- int highfd = nfds ? fds[nfds-1].fd+1 : 0;
- int rv = pselect(highfd, &xreadfds, &xwritefds, 0, 0, &mask);
- lastptr = 0;
- return rv;
-}
-int net_poll_get(struct net_pollfd *out)
-{
- int ev = 0;
- while (!ev) {
- if (lastptr == nfds)
- return 0;
- if (FD_ISSET(fds[lastptr].fd, &xreadfds))
- ev |= NETPOLL_IN;
- if (FD_ISSET(fds[lastptr].fd, &xwritefds))
- ev |= NETPOLL_OUT;
- lastptr++;
- }
- *out = fds[lastptr-1];
- return ev;
-}
-#elif defined(NETPOLL_USE_POLL)
+#if defined(NETPOLL_USE_POLL)
static struct pollfd pollfds[NETPOLL_MAXFDS] = {};
static int lastptr = 0;
void net_poll_init(void)
*out = fds[lastptr-1];
return ev;
}
-#elif defined(NETPOLL_USE_EPOLL)
-#include <sys/epoll.h>
-static int epollfd = -1;
-static struct epoll_event events[256] = {};
-static int nevents = 0;
-static int lastptr = 0;
-static struct net_pollfd fdsbuf[NETPOLL_MAXFDS] = {};
-void net_poll_init(void)
-{
- for (int i = 0; i < NETPOLL_MAXFDS; i++)
- fds[i] = &fdsbuf[i];
- epollfd = epoll_create1(EPOLL_CLOEXEC);
- if (epollfd == -1) {
- perror("epoll_create");
- abort();
- }
-}
-void net_poll_fini(void)
-{
- close(epollfd);
- epollfd = -1;
-}
-static void net_poll_add_impl(int i)
-{
- struct epoll_event e = { .events = 0, .data = { .ptr = fds[i] }};
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i]->fd, &e) == -1) {
- perror("epoll_ctl(EPOLL_CTL_ADD)");
- abort();
- }
-}
-static void net_poll_del_impl(int i)
-{
- /* prevent leaked references */
- struct epoll_event *p, *q;
- p = q = events+lastptr;
- for (int i = lastptr; i < nevents; i++) {
- if (p->data.ptr != fds[i])
- *q++ = *p;
- p++;
- }
- nevents = q-events;
- if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i]->fd, 0) == -1) {
- perror("epoll_ctl(EPOLL_CTL_DEL)");
- abort();
- }
-}
-static void net_poll_reg_impl(int i, int ev)
-{
- struct epoll_event e = { .events = 0, .data = { .ptr = fds[i] }};
- if (ev & NETPOLL_IN)
- e.events = EPOLLIN;
- if (ev & NETPOLL_OUT)
- e.events = EPOLLOUT;
- if (epoll_ctl(epollfd, EPOLL_CTL_MOD, fds[i]->fd, &e) == -1) {
- perror("epoll_ctl(EPOLL_CTL_MOD)");
- abort();
- }
-}
-int net_poll_begin(void)
-{
- sigset_t mask;
- sigprocmask(0, 0, &mask);
- sigdelset(&mask, SIGCHLD);
- int rv = epoll_pwait(epollfd, events, sizeof(events)/sizeof(events[0]), -1, &mask);
- lastptr = 0;
- nevents = rv;
- return rv;
-}
-int net_poll_get(struct net_pollfd *out)
-{
- int ev = 0;
- while (!ev) {
- if (lastptr == nevents)
- return 0;
- int pev = events[lastptr].events;
- if (pev & EPOLLIN)
- ev |= NETPOLL_IN;
- if (pev & EPOLLOUT)
- ev |= NETPOLL_OUT;
- lastptr++;
- }
- *out = *(struct net_pollfd *)events[lastptr-1].data.ptr;
- return ev;
-}
#elif defined(NETPOLL_USE_LIBUV)
#include <uv.h>
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
int l = 0, r = nfds;
while (l != r) {
int m = (l+r)/2;
- if (REF(fds[m]).fd < fd)
+ if (fds[m].fd < fd)
l = m+1;
- else if (fd < REF(fds[m]).fd)
+ else if (fd < fds[m].fd)
r = m;
else
l = r = m;
}
return l;
}
-#define IS_FOUND(i, f) ((i) < nfds && REF(fds[i]).fd == (f))
+#define IS_FOUND(i, f) ((i) < nfds && fds[i].fd == (f))
void net_poll_add(SOCKET fd, int type, void *assoc)
{
fprintf(stderr, "net_poll_add: NETPOLL_MAXFDS limit\n");
abort();
}
- net_pollfd_tabent_t t = fds[nfds];
memmove(fds+i+1, fds+i, sizeof(fds[0])*(nfds-i));
nfds++;
- fds[i] = t;
- REF(fds[i]) = (struct net_pollfd){ .assoc = assoc, .fd = fd, .type = type };
+ fds[i] = (struct net_pollfd){ .assoc = assoc, .fd = fd, .type = type };
net_poll_add_impl(i);
}
void net_poll_del_and_close(SOCKET fd)
}
net_poll_reg_impl(i, 0);
net_poll_del_impl(i);
- net_pollfd_tabent_t t = fds[i];
memmove(fds+i, fds+i+1, sizeof(fds[0])*(nfds-(i+1)));
nfds--;
- fds[nfds] = t;
#ifndef NETPOLL_USE_LIBUV
closesocket(fd);
#endif