1*a5eb7107SBryan Cantrill /* 2*a5eb7107SBryan Cantrill * This file and its contents are supplied under the terms of the 3*a5eb7107SBryan Cantrill * Common Development and Distribution License ("CDDL"), version 1.0. 4*a5eb7107SBryan Cantrill * You may only use this file in accordance with the terms of version 5*a5eb7107SBryan Cantrill * 1.0 of the CDDL. 6*a5eb7107SBryan Cantrill * 7*a5eb7107SBryan Cantrill * A full copy of the text of the CDDL should have accompanied this 8*a5eb7107SBryan Cantrill * source. A copy of the CDDL is also available via the Internet at 9*a5eb7107SBryan Cantrill * http://www.illumos.org/license/CDDL. 10*a5eb7107SBryan Cantrill */ 11*a5eb7107SBryan Cantrill 12*a5eb7107SBryan Cantrill /* 13*a5eb7107SBryan Cantrill * Copyright (c) 2014, Joyent, Inc. All rights reserved. 14*a5eb7107SBryan Cantrill */ 15*a5eb7107SBryan Cantrill 16*a5eb7107SBryan Cantrill #include <sys/types.h> 17*a5eb7107SBryan Cantrill #include <sys/epoll.h> 18*a5eb7107SBryan Cantrill #include <sys/devpoll.h> 19*a5eb7107SBryan Cantrill #include <unistd.h> 20*a5eb7107SBryan Cantrill #include <errno.h> 21*a5eb7107SBryan Cantrill #include <fcntl.h> 22*a5eb7107SBryan Cantrill #include <poll.h> 23*a5eb7107SBryan Cantrill 24*a5eb7107SBryan Cantrill /* 25*a5eb7107SBryan Cantrill * Events that match their epoll(7) equivalents. 26*a5eb7107SBryan Cantrill */ 27*a5eb7107SBryan Cantrill #if EPOLLIN != POLLIN 28*a5eb7107SBryan Cantrill #error value of EPOLLIN does not match value of POLLIN 29*a5eb7107SBryan Cantrill #endif 30*a5eb7107SBryan Cantrill 31*a5eb7107SBryan Cantrill #if EPOLLPRI != POLLPRI 32*a5eb7107SBryan Cantrill #error value of EPOLLPRI does not match value of POLLPRI 33*a5eb7107SBryan Cantrill #endif 34*a5eb7107SBryan Cantrill 35*a5eb7107SBryan Cantrill #if EPOLLOUT != POLLOUT 36*a5eb7107SBryan Cantrill #error value of EPOLLOUT does not match value of POLLOUT 37*a5eb7107SBryan Cantrill #endif 38*a5eb7107SBryan Cantrill 39*a5eb7107SBryan Cantrill #if EPOLLRDNORM != POLLRDNORM 40*a5eb7107SBryan Cantrill #error value of EPOLLRDNORM does not match value of POLLRDNORM 41*a5eb7107SBryan Cantrill #endif 42*a5eb7107SBryan Cantrill 43*a5eb7107SBryan Cantrill #if EPOLLRDBAND != POLLRDBAND 44*a5eb7107SBryan Cantrill #error value of EPOLLRDBAND does not match value of POLLRDBAND 45*a5eb7107SBryan Cantrill #endif 46*a5eb7107SBryan Cantrill 47*a5eb7107SBryan Cantrill #if EPOLLERR != POLLERR 48*a5eb7107SBryan Cantrill #error value of EPOLLERR does not match value of POLLERR 49*a5eb7107SBryan Cantrill #endif 50*a5eb7107SBryan Cantrill 51*a5eb7107SBryan Cantrill #if EPOLLHUP != POLLHUP 52*a5eb7107SBryan Cantrill #error value of EPOLLHUP does not match value of POLLHUP 53*a5eb7107SBryan Cantrill #endif 54*a5eb7107SBryan Cantrill 55*a5eb7107SBryan Cantrill /* 56*a5eb7107SBryan Cantrill * Events that we ignore entirely. They can be set in events, but they will 57*a5eb7107SBryan Cantrill * never be returned. 58*a5eb7107SBryan Cantrill */ 59*a5eb7107SBryan Cantrill #define EPOLLIGNORED (EPOLLMSG | EPOLLWAKEUP) 60*a5eb7107SBryan Cantrill 61*a5eb7107SBryan Cantrill /* 62*a5eb7107SBryan Cantrill * Events that we swizzle into other bit positions. 63*a5eb7107SBryan Cantrill */ 64*a5eb7107SBryan Cantrill #define EPOLLSWIZZLED \ 65*a5eb7107SBryan Cantrill (EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM) 66*a5eb7107SBryan Cantrill 67*a5eb7107SBryan Cantrill int 68*a5eb7107SBryan Cantrill epoll_create(int size) 69*a5eb7107SBryan Cantrill { 70*a5eb7107SBryan Cantrill int fd; 71*a5eb7107SBryan Cantrill 72*a5eb7107SBryan Cantrill /* 73*a5eb7107SBryan Cantrill * From the epoll_create() man page: "Since Linux 2.6.8, the size 74*a5eb7107SBryan Cantrill * argument is ignored, but must be greater than zero." You keep using 75*a5eb7107SBryan Cantrill * that word "ignored"... 76*a5eb7107SBryan Cantrill */ 77*a5eb7107SBryan Cantrill if (size <= 0) { 78*a5eb7107SBryan Cantrill errno = EINVAL; 79*a5eb7107SBryan Cantrill return (-1); 80*a5eb7107SBryan Cantrill } 81*a5eb7107SBryan Cantrill 82*a5eb7107SBryan Cantrill if ((fd = open("/dev/poll", O_RDWR)) == -1) 83*a5eb7107SBryan Cantrill return (-1); 84*a5eb7107SBryan Cantrill 85*a5eb7107SBryan Cantrill if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) { 86*a5eb7107SBryan Cantrill (void) close(fd); 87*a5eb7107SBryan Cantrill return (-1); 88*a5eb7107SBryan Cantrill } 89*a5eb7107SBryan Cantrill 90*a5eb7107SBryan Cantrill return (fd); 91*a5eb7107SBryan Cantrill } 92*a5eb7107SBryan Cantrill 93*a5eb7107SBryan Cantrill int 94*a5eb7107SBryan Cantrill epoll_create1(int flags) 95*a5eb7107SBryan Cantrill { 96*a5eb7107SBryan Cantrill int fd, oflags = O_RDWR; 97*a5eb7107SBryan Cantrill 98*a5eb7107SBryan Cantrill if (flags & EPOLL_CLOEXEC) 99*a5eb7107SBryan Cantrill oflags |= O_CLOEXEC; 100*a5eb7107SBryan Cantrill 101*a5eb7107SBryan Cantrill if ((fd = open("/dev/poll", oflags)) == -1) 102*a5eb7107SBryan Cantrill return (-1); 103*a5eb7107SBryan Cantrill 104*a5eb7107SBryan Cantrill if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) { 105*a5eb7107SBryan Cantrill (void) close(fd); 106*a5eb7107SBryan Cantrill return (-1); 107*a5eb7107SBryan Cantrill } 108*a5eb7107SBryan Cantrill 109*a5eb7107SBryan Cantrill return (fd); 110*a5eb7107SBryan Cantrill } 111*a5eb7107SBryan Cantrill 112*a5eb7107SBryan Cantrill int 113*a5eb7107SBryan Cantrill epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 114*a5eb7107SBryan Cantrill { 115*a5eb7107SBryan Cantrill dvpoll_epollfd_t epoll[2]; 116*a5eb7107SBryan Cantrill uint32_t events, ev = 0; 117*a5eb7107SBryan Cantrill int i = 0; 118*a5eb7107SBryan Cantrill 119*a5eb7107SBryan Cantrill epoll[i].dpep_pollfd.fd = fd; 120*a5eb7107SBryan Cantrill 121*a5eb7107SBryan Cantrill switch (op) { 122*a5eb7107SBryan Cantrill case EPOLL_CTL_DEL: 123*a5eb7107SBryan Cantrill ev = POLLREMOVE; 124*a5eb7107SBryan Cantrill break; 125*a5eb7107SBryan Cantrill 126*a5eb7107SBryan Cantrill case EPOLL_CTL_MOD: 127*a5eb7107SBryan Cantrill /* 128*a5eb7107SBryan Cantrill * In the modify case, we pass down two events: one to 129*a5eb7107SBryan Cantrill * remove the event and another to add it back. 130*a5eb7107SBryan Cantrill */ 131*a5eb7107SBryan Cantrill epoll[i++].dpep_pollfd.events = POLLREMOVE; 132*a5eb7107SBryan Cantrill epoll[i].dpep_pollfd.fd = fd; 133*a5eb7107SBryan Cantrill /* FALLTHROUGH */ 134*a5eb7107SBryan Cantrill 135*a5eb7107SBryan Cantrill case EPOLL_CTL_ADD: 136*a5eb7107SBryan Cantrill /* 137*a5eb7107SBryan Cantrill * Mask off the events that we ignore, and then swizzle the 138*a5eb7107SBryan Cantrill * events for which our values differ from their epoll(7) 139*a5eb7107SBryan Cantrill * equivalents. 140*a5eb7107SBryan Cantrill */ 141*a5eb7107SBryan Cantrill events = event->events; 142*a5eb7107SBryan Cantrill ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED); 143*a5eb7107SBryan Cantrill 144*a5eb7107SBryan Cantrill if (events & EPOLLRDHUP) 145*a5eb7107SBryan Cantrill ev |= POLLRDHUP; 146*a5eb7107SBryan Cantrill 147*a5eb7107SBryan Cantrill if (events & EPOLLET) 148*a5eb7107SBryan Cantrill ev |= POLLET; 149*a5eb7107SBryan Cantrill 150*a5eb7107SBryan Cantrill if (events & EPOLLONESHOT) 151*a5eb7107SBryan Cantrill ev |= POLLONESHOT; 152*a5eb7107SBryan Cantrill 153*a5eb7107SBryan Cantrill if (events & EPOLLWRNORM) 154*a5eb7107SBryan Cantrill ev |= POLLWRNORM; 155*a5eb7107SBryan Cantrill 156*a5eb7107SBryan Cantrill if (events & EPOLLWRBAND) 157*a5eb7107SBryan Cantrill ev |= POLLWRBAND; 158*a5eb7107SBryan Cantrill 159*a5eb7107SBryan Cantrill epoll[i].dpep_data = event->data.u64; 160*a5eb7107SBryan Cantrill break; 161*a5eb7107SBryan Cantrill 162*a5eb7107SBryan Cantrill default: 163*a5eb7107SBryan Cantrill errno = EOPNOTSUPP; 164*a5eb7107SBryan Cantrill return (-1); 165*a5eb7107SBryan Cantrill } 166*a5eb7107SBryan Cantrill 167*a5eb7107SBryan Cantrill epoll[i].dpep_pollfd.events = ev; 168*a5eb7107SBryan Cantrill 169*a5eb7107SBryan Cantrill return (write(epfd, epoll, sizeof (epoll[0]) * (i + 1)) == -1 ? -1 : 0); 170*a5eb7107SBryan Cantrill } 171*a5eb7107SBryan Cantrill 172*a5eb7107SBryan Cantrill int 173*a5eb7107SBryan Cantrill epoll_wait(int epfd, struct epoll_event *events, 174*a5eb7107SBryan Cantrill int maxevents, int timeout) 175*a5eb7107SBryan Cantrill { 176*a5eb7107SBryan Cantrill struct dvpoll arg; 177*a5eb7107SBryan Cantrill 178*a5eb7107SBryan Cantrill if (maxevents <= 0) { 179*a5eb7107SBryan Cantrill errno = EINVAL; 180*a5eb7107SBryan Cantrill return (-1); 181*a5eb7107SBryan Cantrill } 182*a5eb7107SBryan Cantrill 183*a5eb7107SBryan Cantrill arg.dp_nfds = maxevents; 184*a5eb7107SBryan Cantrill arg.dp_timeout = timeout; 185*a5eb7107SBryan Cantrill arg.dp_fds = (pollfd_t *)events; 186*a5eb7107SBryan Cantrill 187*a5eb7107SBryan Cantrill return (ioctl(epfd, DP_POLL, &arg)); 188*a5eb7107SBryan Cantrill } 189*a5eb7107SBryan Cantrill 190*a5eb7107SBryan Cantrill int 191*a5eb7107SBryan Cantrill epoll_pwait(int epfd, struct epoll_event *events, 192*a5eb7107SBryan Cantrill int maxevents, int timeout, const sigset_t *sigmask) 193*a5eb7107SBryan Cantrill { 194*a5eb7107SBryan Cantrill struct dvpoll arg; 195*a5eb7107SBryan Cantrill 196*a5eb7107SBryan Cantrill if (maxevents <= 0) { 197*a5eb7107SBryan Cantrill errno = EINVAL; 198*a5eb7107SBryan Cantrill return (-1); 199*a5eb7107SBryan Cantrill } 200*a5eb7107SBryan Cantrill 201*a5eb7107SBryan Cantrill arg.dp_nfds = maxevents; 202*a5eb7107SBryan Cantrill arg.dp_timeout = timeout; 203*a5eb7107SBryan Cantrill arg.dp_fds = (pollfd_t *)events; 204*a5eb7107SBryan Cantrill arg.dp_setp = (sigset_t *)sigmask; 205*a5eb7107SBryan Cantrill 206*a5eb7107SBryan Cantrill return (ioctl(epfd, DP_PPOLL, &arg)); 207*a5eb7107SBryan Cantrill } 208