import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / sys / epoll.c
blob34cb151135bc132c5950897694e0b36a478d81f3
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.
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.
13 * Copyright 2016 Joyent, Inc.
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>
25 * Events that match their epoll(7) equivalents.
27 #if EPOLLIN != POLLIN
28 #error value of EPOLLIN does not match value of POLLIN
29 #endif
31 #if EPOLLPRI != POLLPRI
32 #error value of EPOLLPRI does not match value of POLLPRI
33 #endif
35 #if EPOLLOUT != POLLOUT
36 #error value of EPOLLOUT does not match value of POLLOUT
37 #endif
39 #if EPOLLRDNORM != POLLRDNORM
40 #error value of EPOLLRDNORM does not match value of POLLRDNORM
41 #endif
43 #if EPOLLRDBAND != POLLRDBAND
44 #error value of EPOLLRDBAND does not match value of POLLRDBAND
45 #endif
47 #if EPOLLERR != POLLERR
48 #error value of EPOLLERR does not match value of POLLERR
49 #endif
51 #if EPOLLHUP != POLLHUP
52 #error value of EPOLLHUP does not match value of POLLHUP
53 #endif
56 * Events that we ignore entirely. They can be set in events, but they will
57 * never be returned.
59 #define EPOLLIGNORED (EPOLLMSG | EPOLLWAKEUP)
62 * Events that we swizzle into other bit positions.
64 #define EPOLLSWIZZLED \
65 (EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
67 int
68 epoll_create(int size)
70 int fd;
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"...
77 if (size <= 0) {
78 errno = EINVAL;
79 return (-1);
82 if ((fd = open("/dev/poll", O_RDWR)) == -1)
83 return (-1);
85 if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
86 (void) close(fd);
87 return (-1);
90 return (fd);
93 int
94 epoll_create1(int flags)
96 int fd, oflags = O_RDWR;
98 if (flags & EPOLL_CLOEXEC) {
99 oflags |= O_CLOEXEC;
100 flags ^= EPOLL_CLOEXEC;
102 /* Reject unrecognized flags */
103 if (flags != 0) {
104 errno = EINVAL;
105 return (-1);
108 if ((fd = open("/dev/poll", oflags)) == -1)
109 return (-1);
111 if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
112 (void) close(fd);
113 return (-1);
116 return (fd);
120 epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
122 dvpoll_epollfd_t epoll[2];
123 uint32_t events, ev = 0;
124 int i = 0, res;
126 epoll[i].dpep_pollfd.fd = fd;
128 switch (op) {
129 case EPOLL_CTL_DEL:
130 ev = POLLREMOVE;
131 break;
133 case EPOLL_CTL_MOD:
135 * In the modify case, we pass down two events: one to
136 * remove the event and another to add it back.
138 epoll[i++].dpep_pollfd.events = POLLREMOVE;
139 epoll[i].dpep_pollfd.fd = fd;
140 /* FALLTHROUGH */
142 case EPOLL_CTL_ADD:
144 * Mask off the events that we ignore, and then swizzle the
145 * events for which our values differ from their epoll(7)
146 * equivalents.
148 events = event->events;
149 ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED);
151 if (events & EPOLLRDHUP)
152 ev |= POLLRDHUP;
154 if (events & EPOLLET)
155 ev |= POLLET;
157 if (events & EPOLLONESHOT)
158 ev |= POLLONESHOT;
160 if (events & EPOLLWRNORM)
161 ev |= POLLWRNORM;
163 if (events & EPOLLWRBAND)
164 ev |= POLLWRBAND;
166 epoll[i].dpep_data = event->data.u64;
167 break;
169 default:
170 errno = EOPNOTSUPP;
171 return (-1);
174 epoll[i].dpep_pollfd.events = ev;
175 retry:
176 res = write(epfd, epoll, sizeof (epoll[0]) * (i + 1));
178 if (res == -1) {
179 if (errno == EINTR) {
181 * Linux does not document EINTR as an allowed error
182 * for epoll_ctl. The write must be retried if it is
183 * not done automatically via SA_RESTART.
185 goto retry;
187 if (errno == ELOOP) {
189 * Convert the specific /dev/poll error about an fd
190 * loop into what is expected from the Linux epoll
191 * interface.
193 errno = EINVAL;
195 return (-1);
197 return (0);
201 epoll_wait(int epfd, struct epoll_event *events,
202 int maxevents, int timeout)
204 struct dvpoll arg;
206 if (maxevents <= 0) {
207 errno = EINVAL;
208 return (-1);
211 arg.dp_nfds = maxevents;
212 arg.dp_timeout = timeout;
213 arg.dp_fds = (pollfd_t *)events;
215 return (ioctl(epfd, DP_POLL, &arg));
219 epoll_pwait(int epfd, struct epoll_event *events,
220 int maxevents, int timeout, const sigset_t *sigmask)
222 struct dvpoll arg;
224 if (maxevents <= 0) {
225 errno = EINVAL;
226 return (-1);
229 arg.dp_nfds = maxevents;
230 arg.dp_timeout = timeout;
231 arg.dp_fds = (pollfd_t *)events;
232 arg.dp_setp = (sigset_t *)sigmask;
234 return (ioctl(epfd, DP_PPOLL, &arg));