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
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>
25 * Events that match their epoll(7) equivalents.
28 #error value of EPOLLIN does not match value of POLLIN
31 #if EPOLLPRI != POLLPRI
32 #error value of EPOLLPRI does not match value of POLLPRI
35 #if EPOLLOUT != POLLOUT
36 #error value of EPOLLOUT does not match value of POLLOUT
39 #if EPOLLRDNORM != POLLRDNORM
40 #error value of EPOLLRDNORM does not match value of POLLRDNORM
43 #if EPOLLRDBAND != POLLRDBAND
44 #error value of EPOLLRDBAND does not match value of POLLRDBAND
47 #if EPOLLERR != POLLERR
48 #error value of EPOLLERR does not match value of POLLERR
51 #if EPOLLHUP != POLLHUP
52 #error value of EPOLLHUP does not match value of POLLHUP
56 * Events that we ignore entirely. They can be set in events, but they will
59 #define EPOLLIGNORED (EPOLLMSG | EPOLLWAKEUP)
62 * Events that we swizzle into other bit positions.
64 #define EPOLLSWIZZLED \
65 (EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
68 epoll_create(int size
)
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"...
82 if ((fd
= open("/dev/poll", O_RDWR
)) == -1)
85 if (ioctl(fd
, DP_EPOLLCOMPAT
, 0) == -1) {
94 epoll_create1(int flags
)
96 int fd
, oflags
= O_RDWR
;
98 if (flags
& EPOLL_CLOEXEC
) {
100 flags
^= EPOLL_CLOEXEC
;
102 /* Reject unrecognized flags */
108 if ((fd
= open("/dev/poll", oflags
)) == -1)
111 if (ioctl(fd
, DP_EPOLLCOMPAT
, 0) == -1) {
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;
126 epoll
[i
].dpep_pollfd
.fd
= fd
;
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
;
144 * Mask off the events that we ignore, and then swizzle the
145 * events for which our values differ from their epoll(7)
148 events
= event
->events
;
149 ev
= events
& ~(EPOLLIGNORED
| EPOLLSWIZZLED
);
151 if (events
& EPOLLRDHUP
)
154 if (events
& EPOLLET
)
157 if (events
& EPOLLONESHOT
)
160 if (events
& EPOLLWRNORM
)
163 if (events
& EPOLLWRBAND
)
166 epoll
[i
].dpep_data
= event
->data
.u64
;
174 epoll
[i
].dpep_pollfd
.events
= ev
;
176 res
= write(epfd
, epoll
, sizeof (epoll
[0]) * (i
+ 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.
187 if (errno
== ELOOP
) {
189 * Convert the specific /dev/poll error about an fd
190 * loop into what is expected from the Linux epoll
201 epoll_wait(int epfd
, struct epoll_event
*events
,
202 int maxevents
, int timeout
)
206 if (maxevents
<= 0) {
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
)
224 if (maxevents
<= 0) {
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
));