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