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
epoll_create(int size)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
epoll_create1(int flags)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
epoll_ctl(int epfd,int op,int fd,struct epoll_event * event)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
epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)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
epoll_pwait(int epfd,struct epoll_event * events,int maxevents,int timeout,const sigset_t * sigmask)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