#include <sys/types.h>
#include <sys/epoll.h>
#include <sys/devpoll.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#if EPOLLIN != POLLIN
#error value of EPOLLIN does not match value of POLLIN
#endif
#if EPOLLPRI != POLLPRI
#error value of EPOLLPRI does not match value of POLLPRI
#endif
#if EPOLLOUT != POLLOUT
#error value of EPOLLOUT does not match value of POLLOUT
#endif
#if EPOLLRDNORM != POLLRDNORM
#error value of EPOLLRDNORM does not match value of POLLRDNORM
#endif
#if EPOLLRDBAND != POLLRDBAND
#error value of EPOLLRDBAND does not match value of POLLRDBAND
#endif
#if EPOLLERR != POLLERR
#error value of EPOLLERR does not match value of POLLERR
#endif
#if EPOLLHUP != POLLHUP
#error value of EPOLLHUP does not match value of POLLHUP
#endif
#define EPOLLIGNORED (EPOLLMSG | EPOLLWAKEUP | EPOLLEXCLUSIVE)
#define EPOLLSWIZZLED \
(EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
#define EPOLL_TIMEOUT_CLAMP(t) (((t) < -1) ? -1 : (t))
int
epoll_create(int size)
{
int fd;
if (size <= 0) {
errno = EINVAL;
return (-1);
}
if ((fd = open("/dev/poll", O_RDWR)) == -1)
return (-1);
if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
(void) close(fd);
return (-1);
}
return (fd);
}
int
epoll_create1(int flags)
{
int fd, oflags = O_RDWR;
if (flags & EPOLL_CLOEXEC) {
oflags |= O_CLOEXEC;
flags ^= EPOLL_CLOEXEC;
}
if (flags != 0) {
errno = EINVAL;
return (-1);
}
if ((fd = open("/dev/poll", oflags)) == -1)
return (-1);
if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
(void) close(fd);
return (-1);
}
return (fd);
}
int
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
dvpoll_epollfd_t epoll[2];
uint32_t events, ev = 0;
int i = 0, res;
epoll[i].dpep_pollfd.fd = fd;
switch (op) {
case EPOLL_CTL_DEL:
ev = POLLREMOVE;
break;
case EPOLL_CTL_MOD:
if ((event->events & EPOLLEXCLUSIVE) != 0) {
errno = EINVAL;
return (-1);
}
epoll[i++].dpep_pollfd.events = POLLREMOVE;
epoll[i].dpep_pollfd.fd = fd;
case EPOLL_CTL_ADD:
events = event->events;
ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED);
if (events & EPOLLRDHUP)
ev |= POLLRDHUP;
if (events & EPOLLET)
ev |= POLLET;
if (events & EPOLLONESHOT)
ev |= POLLONESHOT;
if (events & EPOLLWRNORM)
ev |= POLLWRNORM;
if (events & EPOLLWRBAND)
ev |= POLLWRBAND;
epoll[i].dpep_data = event->data.u64;
break;
default:
errno = EOPNOTSUPP;
return (-1);
}
epoll[i].dpep_pollfd.events = ev;
retry:
res = write(epfd, epoll, sizeof (epoll[0]) * (i + 1));
if (res == -1) {
if (errno == EINTR) {
goto retry;
}
if (errno == ELOOP) {
errno = EINVAL;
}
return (-1);
}
return (0);
}
int
epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout)
{
struct dvpoll arg;
if (maxevents <= 0) {
errno = EINVAL;
return (-1);
}
arg.dp_nfds = maxevents;
arg.dp_timeout = EPOLL_TIMEOUT_CLAMP(timeout);
arg.dp_fds = (pollfd_t *)events;
return (ioctl(epfd, DP_POLL, &arg));
}
int
epoll_pwait(int epfd, struct epoll_event *events,
int maxevents, int timeout, const sigset_t *sigmask)
{
struct dvpoll arg;
if (maxevents <= 0) {
errno = EINVAL;
return (-1);
}
arg.dp_nfds = maxevents;
arg.dp_timeout = EPOLL_TIMEOUT_CLAMP(timeout);
arg.dp_fds = (pollfd_t *)events;
arg.dp_setp = (sigset_t *)sigmask;
return (ioctl(epfd, DP_PPOLL, &arg));
}